• 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_SHA1
18 
19 #include <stdlib.h>
20 #include "securec.h"
21 #include "crypt_errno.h"
22 #include "crypt_utils.h"
23 #include "bsl_err_internal.h"
24 #include "sha1_core.h"
25 #include "bsl_sal.h"
26 #include "crypt_sha1.h"
27 #include "crypt_types.h"
28 
29 
30 #ifdef __cplusplus
31 extern "C" {
32 #endif /* __cpluscplus */
33 
34 /* SHA-1 context structure */
35 struct CryptSha1Ctx {
36     uint8_t m[CRYPT_SHA1_BLOCKSIZE];                      /* store the remaining data which less than one block */
37     uint32_t h[CRYPT_SHA1_DIGESTSIZE / sizeof(uint32_t)]; /* store the intermediate data of the hash value */
38     uint32_t hNum, lNum;                                  /* input data counter, maximum value 2 ^ 64 bits */
39     int32_t errorCode;                                    /* Error code */
40     uint32_t count;       /* Number of remaining data bytes less than one block, corresponding to the length of the m */
41 };
42 
CRYPT_SHA1_NewCtx(void)43 CRYPT_SHA1_Ctx *CRYPT_SHA1_NewCtx(void)
44 {
45     return BSL_SAL_Calloc(1, sizeof(CRYPT_SHA1_Ctx));
46 }
47 
CRYPT_SHA1_FreeCtx(CRYPT_SHA1_Ctx * ctx)48 void CRYPT_SHA1_FreeCtx(CRYPT_SHA1_Ctx *ctx)
49 {
50     CRYPT_SHA1_Ctx *mdCtx = ctx;
51     if (mdCtx == NULL) {
52         return;
53     }
54     BSL_SAL_ClearFree(ctx, sizeof(CRYPT_SHA1_Ctx));
55 }
56 
57 /* e767 is because H is defined in SHA1 and MD5.
58 But the both the macros are different. So masked
59 this error */
CRYPT_SHA1_Init(CRYPT_SHA1_Ctx * ctx,BSL_Param * param)60 int32_t CRYPT_SHA1_Init(CRYPT_SHA1_Ctx *ctx, BSL_Param *param)
61 {
62     if (ctx == NULL) {
63         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
64         return CRYPT_NULL_INPUT;
65     }
66     (void) param;
67     (void)memset_s(ctx, sizeof(CRYPT_SHA1_Ctx), 0, sizeof(CRYPT_SHA1_Ctx));
68 
69     /**
70      *  RFC3174 6.1 Initialize the H constants of the input ctx
71      *  These constants are provided by the standard
72      */
73     ctx->h[0] = 0x67452301;
74     ctx->h[1] = 0xefcdab89;
75     ctx->h[2] = 0x98badcfe;
76     ctx->h[3] = 0x10325476;
77     ctx->h[4] = 0xc3d2e1f0;
78     return CRYPT_SUCCESS;
79 }
80 
CRYPT_SHA1_Deinit(CRYPT_SHA1_Ctx * ctx)81 void CRYPT_SHA1_Deinit(CRYPT_SHA1_Ctx *ctx)
82 {
83     if (ctx == NULL) {
84         return;
85     }
86     BSL_SAL_CleanseData((void *)(ctx), sizeof(CRYPT_SHA1_Ctx));
87 }
88 
CRYPT_SHA1_CopyCtx(CRYPT_SHA1_Ctx * dst,const CRYPT_SHA1_Ctx * src)89 int32_t CRYPT_SHA1_CopyCtx(CRYPT_SHA1_Ctx *dst, const CRYPT_SHA1_Ctx *src)
90 {
91     if (dst == NULL || src == NULL) {
92         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
93         return CRYPT_NULL_INPUT;
94     }
95 
96     (void)memcpy_s(dst, sizeof(CRYPT_SHA1_Ctx), src, sizeof(CRYPT_SHA1_Ctx));
97     return CRYPT_SUCCESS;
98 }
99 
CRYPT_SHA1_DupCtx(const CRYPT_SHA1_Ctx * src)100 CRYPT_SHA1_Ctx *CRYPT_SHA1_DupCtx(const CRYPT_SHA1_Ctx *src)
101 {
102     if (src == NULL) {
103         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
104         return NULL;
105     }
106     CRYPT_SHA1_Ctx *newCtx = CRYPT_SHA1_NewCtx();
107     if (newCtx == NULL) {
108         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
109         return NULL;
110     }
111     (void)memcpy_s(newCtx, sizeof(CRYPT_SHA1_Ctx), src, sizeof(CRYPT_SHA1_Ctx));
112     return newCtx;
113 }
114 
SHA1_CheckIsCorrupted(CRYPT_SHA1_Ctx * ctx,uint32_t textLen)115 static int32_t SHA1_CheckIsCorrupted(CRYPT_SHA1_Ctx *ctx, uint32_t textLen)
116 {
117     uint32_t low = (ctx->lNum + (textLen << 3)) & 0xffffffffUL;
118     if (low < ctx->lNum) { /* overflow */
119         if (++ctx->hNum == 0) {
120             ctx->errorCode = CRYPT_SHA1_INPUT_OVERFLOW;
121             BSL_ERR_PUSH_ERROR(CRYPT_SHA1_INPUT_OVERFLOW);
122             return CRYPT_SHA1_INPUT_OVERFLOW;
123         }
124     }
125     uint32_t high = ctx->hNum + (uint32_t)(textLen >> (32 - 3));
126     if (high < ctx->hNum) { /* overflow */
127         ctx->errorCode = CRYPT_SHA1_INPUT_OVERFLOW;
128         BSL_ERR_PUSH_ERROR(CRYPT_SHA1_INPUT_OVERFLOW);
129         return CRYPT_SHA1_INPUT_OVERFLOW;
130     }
131     ctx->hNum = high;
132     ctx->lNum = low;
133 
134     return CRYPT_SUCCESS;
135 }
136 
SHA1_UpdateParamIsValid(CRYPT_SHA1_Ctx * ctx,const uint8_t * data,uint32_t nbytes)137 static int32_t SHA1_UpdateParamIsValid(CRYPT_SHA1_Ctx *ctx, const uint8_t *data, uint32_t nbytes)
138 {
139     if ((ctx == NULL) || (data == NULL && nbytes != 0)) {
140         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
141         return CRYPT_NULL_INPUT;
142     }
143 
144     if (ctx->errorCode != CRYPT_SUCCESS) {
145         BSL_ERR_PUSH_ERROR(ctx->errorCode);
146         return ctx->errorCode;
147     }
148 
149     if (SHA1_CheckIsCorrupted(ctx, nbytes) != CRYPT_SUCCESS) {
150         BSL_ERR_PUSH_ERROR(CRYPT_SHA1_INPUT_OVERFLOW);
151         return CRYPT_SHA1_INPUT_OVERFLOW;
152     }
153 
154     return CRYPT_SUCCESS;
155 }
156 
CRYPT_SHA1_Update(CRYPT_SHA1_Ctx * ctx,const uint8_t * in,uint32_t len)157 int32_t CRYPT_SHA1_Update(CRYPT_SHA1_Ctx *ctx, const uint8_t *in, uint32_t len)
158 {
159     int32_t ret = SHA1_UpdateParamIsValid(ctx, in, len);
160     if (ret != CRYPT_SUCCESS) {
161         return ret;
162     }
163     const uint8_t *data = in;
164     uint32_t dataLen = len;
165     uint32_t start = ctx->count;
166     uint32_t left = CRYPT_SHA1_BLOCKSIZE - start;
167 
168     /* Check whether the user input data and cached data can form a block. */
169     if (dataLen < left) {
170         (void)memcpy_s(&ctx->m[start], left, data, dataLen);
171         ctx->count += dataLen;
172         return CRYPT_SUCCESS;
173     }
174 
175     /* Preferentially process the buf data and form a block with the user input data. */
176     if (start != 0) {
177         (void)memcpy_s(&ctx->m[start], left, data, left);
178         (void)SHA1_Step(ctx->m, CRYPT_SHA1_BLOCKSIZE, ctx->h);
179         dataLen -= left;
180         data += left;
181         ctx->count = 0;
182     }
183 
184     /* Cyclically process the input data */
185     data = SHA1_Step(data, dataLen, ctx->h);
186     dataLen = len - (data - in);
187 
188     /* The remaining data is less than one block and stored in the buf. */
189     if (dataLen != 0) {
190         (void)memcpy_s(ctx->m, CRYPT_SHA1_BLOCKSIZE, data, dataLen);
191         ctx->count = dataLen;
192     }
193     return CRYPT_SUCCESS;
194 }
195 
SHA1_FinalParamIsValid(const CRYPT_SHA1_Ctx * ctx,const uint8_t * out,const uint32_t * outLen)196 static int32_t SHA1_FinalParamIsValid(const CRYPT_SHA1_Ctx *ctx, const uint8_t *out, const uint32_t *outLen)
197 {
198     if ((ctx == NULL) || (out == NULL) || (outLen == NULL)) {
199         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
200         return CRYPT_NULL_INPUT;
201     }
202 
203     if (*outLen < CRYPT_SHA1_DIGESTSIZE) {
204         BSL_ERR_PUSH_ERROR(CRYPT_SHA1_OUT_BUFF_LEN_NOT_ENOUGH);
205         return CRYPT_SHA1_OUT_BUFF_LEN_NOT_ENOUGH;
206     }
207 
208     if (ctx->errorCode != CRYPT_SUCCESS) {
209         BSL_ERR_PUSH_ERROR(ctx->errorCode);
210         return ctx->errorCode;
211     }
212 
213     return CRYPT_SUCCESS;
214 }
215 
CRYPT_SHA1_Final(CRYPT_SHA1_Ctx * ctx,uint8_t * out,uint32_t * len)216 int32_t CRYPT_SHA1_Final(CRYPT_SHA1_Ctx *ctx, uint8_t *out, uint32_t *len)
217 {
218     int32_t ret = SHA1_FinalParamIsValid(ctx, out, len);
219     if (ret != CRYPT_SUCCESS) {
220         return ret;
221     }
222     uint32_t padLen;
223     uint32_t padPos;
224     /* Add "1" to the end of the user data */
225     ctx->m[ctx->count] = 0x80;
226     ctx->count++;
227 
228     /* If here is one complete data block, one complete data block is processed first. */
229     if (ctx->count == CRYPT_SHA1_BLOCKSIZE) {
230         (void)SHA1_Step(ctx->m, CRYPT_SHA1_BLOCKSIZE, ctx->h);
231         ctx->count = 0;
232     }
233 
234     /* Calculate the padding position. */
235     padPos = ctx->count;
236     padLen = CRYPT_SHA1_BLOCKSIZE - padPos;
237 
238     if (padLen < 8) {   /* 64 bits (8 bytes) of 512 bits are reserved to pad "0" */
239         (void)memset_s(&ctx->m[padPos], padLen, 0, padLen);
240         padPos = 0;
241         padLen = CRYPT_SHA1_BLOCKSIZE;
242         (void)SHA1_Step(ctx->m, CRYPT_SHA1_BLOCKSIZE, ctx->h);
243     }
244     /* offset 8 bytes, reserved for storing the data length */
245     (void)memset_s(&ctx->m[padPos], (padLen - 8), 0, (padLen - 8));
246     PUT_UINT32_BE(ctx->hNum, ctx->m, 56);    /* The 56th byte starts to store the upper 32-bit data. */
247     PUT_UINT32_BE(ctx->lNum, ctx->m, 60);    /* The 60th byte starts to store the lower 32-bit data. */
248     (void)SHA1_Step(ctx->m, CRYPT_SHA1_BLOCKSIZE, ctx->h);
249 
250     PUT_UINT32_BE(ctx->h[0], out, 0);
251     PUT_UINT32_BE(ctx->h[1], out, 4);
252     PUT_UINT32_BE(ctx->h[2], out, 8);
253     PUT_UINT32_BE(ctx->h[3], out, 12);
254     PUT_UINT32_BE(ctx->h[4], out, 16);
255     *len = CRYPT_SHA1_DIGESTSIZE;
256     return CRYPT_SUCCESS;
257 }
258 
259 #ifdef  __cplusplus
260 }
261 #endif
262 
263 #endif // HITLS_CRYPTO_SHA1
264