• 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_BSL_BASE64
18 #include <stdint.h>
19 #include <string.h>
20 #include <stdbool.h>
21 #include "securec.h"
22 #include "bsl_errno.h"
23 #include "bsl_err_internal.h"
24 #include "bsl_sal.h"
25 #include "bsl_base64_internal.h"
26 #include "bsl_base64.h"
27 
28 /* BASE64 mapping table */
29 static const uint8_t BASE64_DECODE_MAP_TABLE[] = {
30     67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 64U, 67U, 67U, 64U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U,
31     67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 64U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 62U, 67U, 66U,
32     67U, 63U, 52U, 53U, 54U, 55U, 56U, 57U, 58U, 59U, 60U, 61U, 67U, 67U, 67U, 65U, 67U, 67U, 67U, 0U,  1U,  2U,  3U,
33     4U,  5U,  6U,  7U,  8U,  9U,  10U, 11U, 12U, 13U, 14U, 15U, 16U, 17U, 18U, 19U, 20U, 21U, 22U, 23U, 24U, 25U, 67U,
34     67U, 67U, 67U, 67U, 67U, 26U, 27U, 28U, 29U, 30U, 31U, 32U, 33U, 34U, 35U, 36U, 37U, 38U, 39U, 40U, 41U, 42U, 43U,
35     44U, 45U, 46U, 47U, 48U, 49U, 50U, 51U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U,
36     67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U,
37     67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U,
38     67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U,
39     67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U,
40     67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U, 67U,
41     67U, 67U, 67U};
42 
43 
BSL_BASE64_CtxNew(void)44 BSL_Base64Ctx *BSL_BASE64_CtxNew(void)
45 {
46     return BSL_SAL_Malloc(sizeof(BSL_Base64Ctx));
47 }
48 
BSL_BASE64_CtxFree(BSL_Base64Ctx * ctx)49 void BSL_BASE64_CtxFree(BSL_Base64Ctx *ctx)
50 {
51     BSL_SAL_FREE(ctx);
52 }
53 
BSL_BASE64_CtxClear(BSL_Base64Ctx * ctx)54 void BSL_BASE64_CtxClear(BSL_Base64Ctx *ctx)
55 {
56     BSL_SAL_CleanseData(ctx, (uint32_t)sizeof(BSL_Base64Ctx));
57 }
58 
BslBase64EncodeParamsValidate(const uint8_t * srcBuf,const uint32_t srcBufLen,const char * dstBuf,uint32_t * dstBufLen)59 static int32_t BslBase64EncodeParamsValidate(const uint8_t *srcBuf, const uint32_t srcBufLen,
60     const char *dstBuf, uint32_t *dstBufLen)
61 {
62     if (srcBuf == NULL || srcBufLen == 0U || dstBuf == NULL || dstBufLen == NULL) {
63         BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
64         return BSL_NULL_INPUT;
65     }
66     /* The length of dstBuf of the user must be at least (srcBufLen+2)/3*4+1 */
67     if (*dstBufLen < BSL_BASE64_ENC_ENOUGH_LEN(srcBufLen)) {
68         BSL_ERR_PUSH_ERROR(BSL_BASE64_BUF_NOT_ENOUGH);
69         return BSL_BASE64_BUF_NOT_ENOUGH;
70     }
71 
72     return BSL_SUCCESS;
73 }
74 
BslBase64ArithEncodeProc(const uint8_t * srcBuf,const uint32_t srcBufLen,char * dstBuf,uint32_t * dstBufLen)75 static void BslBase64ArithEncodeProc(const uint8_t *srcBuf, const uint32_t srcBufLen,
76     char *dstBuf, uint32_t *dstBufLen)
77 {
78     /* base64-encoding mapping table */
79     static const char *base64Letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
80     uint32_t dstIdx = 0U;
81     const uint8_t *tmpBuf = srcBuf;
82     uint32_t tmpLen;
83 
84     /* @alias Encode characters based on the BASE64 encoding rule. */
85     for (tmpLen = srcBufLen; tmpLen > 2U; tmpLen -= 3U) {
86         dstBuf[dstIdx] = base64Letter[(tmpBuf[0] >> 2U) & 0x3FU];
87         dstIdx++;
88         dstBuf[dstIdx] = base64Letter[((tmpBuf[0] & 0x3U) << 4U) | ((tmpBuf[1U] & 0xF0U) >> 4U)];
89         dstIdx++;
90         dstBuf[dstIdx] = base64Letter[((tmpBuf[1U] & 0x0FU) << 2U) | ((tmpBuf[2U] & 0xC0U) >> 6U)];
91         dstIdx++;
92         dstBuf[dstIdx] = base64Letter[tmpBuf[2U] & 0x3FU];
93         dstIdx++;
94         tmpBuf = &tmpBuf[3U];
95     }
96 
97     /* Handle the case where the remaining length is not 0. */
98     if (tmpLen > 0U) {
99         /* Padded the first byte. */
100         dstBuf[dstIdx] = base64Letter[(tmpBuf[0] >> 2U) & 0x3FU];
101         dstIdx++;
102         if (tmpLen == 1U) {
103             /* Process the case where the remaining length is 1. */
104             dstBuf[dstIdx] = base64Letter[((tmpBuf[0U] & 0x3U) << 4U)];
105             dstIdx++;
106             dstBuf[dstIdx] = '=';
107             dstIdx++;
108         } else {
109             /* Process the case where the remaining length is 2. */
110             dstBuf[dstIdx] = base64Letter[((tmpBuf[0U] & 0x3U) << 4U) | ((tmpBuf[1U] & 0xF0U) >> 4U)];
111             dstIdx++;
112             dstBuf[dstIdx] = base64Letter[((tmpBuf[1U] & 0x0Fu) << 2U)];
113             dstIdx++;
114         }
115         /* Fill the last '='. */
116         dstBuf[dstIdx++] = '=';
117     }
118     /* Fill terminator. */
119     dstBuf[dstIdx] = '\0';
120     *dstBufLen = dstIdx;
121 }
122 
123 /* Encode the entire ctx->buf, 48 characters in total, and return the number of decoded characters. */
BslBase64EncodeBlock(BSL_Base64Ctx * ctx,const uint8_t ** srcBuf,uint32_t * srcBufLen,char ** dstBuf,uint32_t * dstBufLen,uint32_t remainLen)124 static void BslBase64EncodeBlock(BSL_Base64Ctx *ctx, const uint8_t **srcBuf, uint32_t *srcBufLen,
125     char **dstBuf, uint32_t *dstBufLen, uint32_t remainLen)
126 {
127     uint32_t tmpOutLen = 0;
128     uint32_t offset = 0;
129 
130     BslBase64ArithEncodeProc(*srcBuf, ctx->length, *dstBuf, &tmpOutLen);
131 
132     ctx->num = 0;
133 
134     offset = ((remainLen == 0) ? (ctx->length) : remainLen);
135     *srcBuf += offset;
136     *srcBufLen -= offset;
137     *dstBufLen += tmpOutLen;
138     *dstBuf += tmpOutLen;
139 
140     if ((ctx->flags & BSL_BASE64_FLAGS_NO_NEWLINE) == 0) {
141         *(*dstBuf) = '\n';
142         (*dstBuf)++;
143         (*dstBufLen)++;
144     }
145     *(*dstBuf) = '\0';
146 }
147 
BslBase64EncodeProcess(BSL_Base64Ctx * ctx,const uint8_t ** srcBuf,uint32_t * srcBufLen,char * dstBuf,uint32_t * dstBufLen)148 static void BslBase64EncodeProcess(BSL_Base64Ctx *ctx, const uint8_t **srcBuf, uint32_t *srcBufLen,
149     char *dstBuf, uint32_t *dstBufLen)
150 {
151     uint32_t remainLen = 0;
152     const uint8_t *bufTmp = &(ctx->buf[0]);
153     char *dstBufTmp = dstBuf;
154 
155     if (ctx->num != 0) {
156         remainLen = ctx->length - ctx->num;
157         (void)memcpy_s(&(ctx->buf[ctx->num]), remainLen, *srcBuf, remainLen);
158         BslBase64EncodeBlock(ctx, &bufTmp, srcBufLen, &dstBufTmp, dstBufLen, remainLen);
159         *srcBuf += remainLen;
160         remainLen = 0;
161     }
162 
163     const uint8_t *srcBufTmp = *srcBuf;
164     /* Encoding every 48 characters. */
165     while (*srcBufLen >= ctx->length) {
166         BslBase64EncodeBlock(ctx, &srcBufTmp, srcBufLen, &dstBufTmp, dstBufLen, remainLen);
167     }
168     *srcBuf = srcBufTmp;
169 }
170 
BslBase64DecodeCheck(const char src,uint32_t * paddingCnt)171 static int32_t BslBase64DecodeCheck(const char src, uint32_t *paddingCnt)
172 {
173     uint32_t padding = 0;
174     /* 66U is the header identifier '-' (invalid), and 66U or above are invalid characters beyond the range. */
175     if (BASE64_DECODE_MAP_TABLE[(uint8_t)src] == 66U) {
176         BSL_ERR_PUSH_ERROR(BSL_BASE64_HEADER);
177         return BSL_BASE64_HEADER;
178     }
179     if (BASE64_DECODE_MAP_TABLE[(uint8_t)src] > 66U) {
180         BSL_ERR_PUSH_ERROR(BSL_INVALID_ARG);
181         return BSL_INVALID_ARG;
182     }
183     /* 65U is the padding character '=' and also EOF identifier. */
184     if (BASE64_DECODE_MAP_TABLE[(uint8_t)src] == 65U) {
185         if (*paddingCnt < BASE64_PAD_MAX) {
186             padding++;
187         } else { /* paddingCnt > 2 */
188             BSL_ERR_PUSH_ERROR(BSL_BASE64_INVALID);
189             return BSL_BASE64_INVALID;
190         }
191     }
192     /* illegal behavior: data after padding. */
193     if (*paddingCnt > 0 && BASE64_DECODE_MAP_TABLE[(uint8_t)src] < 64U) {
194         BSL_ERR_PUSH_ERROR(BSL_BASE64_DATA_AFTER_PADDING);
195         return BSL_BASE64_DATA_AFTER_PADDING;
196     }
197 
198     *paddingCnt += padding;
199     return BSL_SUCCESS;
200 }
201 
BSL_BASE64_Encode(const uint8_t * srcBuf,const uint32_t srcBufLen,char * dstBuf,uint32_t * dstBufLen)202 int32_t BSL_BASE64_Encode(const uint8_t *srcBuf, const uint32_t srcBufLen, char *dstBuf, uint32_t *dstBufLen)
203 {
204     int32_t ret = BslBase64EncodeParamsValidate(srcBuf, srcBufLen, (const char *)dstBuf, dstBufLen);
205     if (ret != BSL_SUCCESS) {
206         return ret;
207     }
208 
209     BslBase64ArithEncodeProc(srcBuf, srcBufLen, dstBuf, dstBufLen); /* executes the encoding algorithm */
210 
211     return BSL_SUCCESS;
212 }
213 
BslBase64DecodeRemoveBlank(const uint8_t * buf,const uint32_t bufLen,uint8_t * destBuf,uint32_t * destLen)214 static void BslBase64DecodeRemoveBlank(const uint8_t *buf, const uint32_t bufLen, uint8_t *destBuf, uint32_t *destLen)
215 {
216     uint32_t fast = 0;
217     uint32_t slow = 0;
218     for (; fast < bufLen; fast++) {
219         if (BASE64_DECODE_MAP_TABLE[buf[fast]] != 64U) { /* when the character is not ' ' or '\r', '\n' */
220             destBuf[slow++] = buf[fast];
221         }
222     }
223     *destLen = slow;
224 }
225 
BslBase64DecodeCheckAndRmvEqualSign(uint8_t * buf,uint32_t * bufLen)226 static int32_t BslBase64DecodeCheckAndRmvEqualSign(uint8_t *buf, uint32_t *bufLen)
227 {
228     int32_t ret = BSL_SUCCESS;
229     uint32_t i = 0;
230     bool hasEqualSign = false;
231     uint32_t len = *bufLen;
232     for (; i < len; i++) {
233         /* Check whether the characters are invalid characters in the Base64 mapping table. */
234         if (BASE64_DECODE_MAP_TABLE[buf[i]] > 65U) {
235             /* 66U is the status code of invalid characters. */
236             return BSL_BASE64_INVALID_CHARACTER;
237         }
238         /* Process the '=' */
239         if (BASE64_DECODE_MAP_TABLE[buf[i]] == 65U) {
240             hasEqualSign = true;
241             /* 65U is the status code with the '=' */
242             if (i == len - 1) {
243                 break;
244             } else if (i == len - BASE64_PAD_MAX) {
245                 ret = (buf[i + 1] == '=') ? BSL_SUCCESS : BSL_BASE64_INVALID_CHARACTER;
246                 buf[i + 1] = '\0';
247                 break;
248             } else {
249                 return BSL_BASE64_INVALID_CHARACTER;
250             }
251         }
252     }
253     if (ret == BSL_SUCCESS) {
254         if (hasEqualSign == true) {
255             buf[i] = '\0';
256         }
257         *bufLen = i;
258     }
259     return ret;
260 }
261 
BslBase64Normalization(const char * srcBuf,const uint32_t srcBufLen,uint8_t * filterBuf,uint32_t * filterBufLen)262 static int32_t BslBase64Normalization(const char *srcBuf, const uint32_t srcBufLen, uint8_t *filterBuf,
263     uint32_t *filterBufLen)
264 {
265     (void)memset_s(filterBuf, *filterBufLen, 0, *filterBufLen);
266     BslBase64DecodeRemoveBlank((const uint8_t *)srcBuf, srcBufLen, filterBuf, filterBufLen);
267     if (*filterBufLen == 0 || ((*filterBufLen) % BASE64_DECODE_BYTES != 0)) {
268         return BSL_BASE64_INVALID_ENCODE;
269     }
270     return BslBase64DecodeCheckAndRmvEqualSign(filterBuf, filterBufLen);
271 }
272 
273 /* can ensure that dstBuf and dstBufLen are sufficient and that srcBuf does not contain invalid characters */
BslBase64DecodeBuffer(const uint8_t * srcBuf,const uint32_t srcBufLen,uint8_t * dstBuf,uint32_t * dstBufLen)274 static int32_t BslBase64DecodeBuffer(const uint8_t *srcBuf, const uint32_t srcBufLen, uint8_t *dstBuf,
275     uint32_t *dstBufLen)
276 {
277     uint32_t idx = 0U;
278     uint32_t tmpLen;
279     const uint8_t *tmp = srcBuf;
280 
281     for (tmpLen = srcBufLen; tmpLen > 4U; tmpLen -= 4U) {
282         dstBuf[idx] = (BASE64_DECODE_MAP_TABLE[tmp[0U]] << 2U) | (BASE64_DECODE_MAP_TABLE[tmp[1U]] >> 4U);
283         idx++;
284         dstBuf[idx] = (BASE64_DECODE_MAP_TABLE[tmp[1U]] << 4U) | (BASE64_DECODE_MAP_TABLE[tmp[2U]] >> 2U);
285         idx++;
286         dstBuf[idx] = (BASE64_DECODE_MAP_TABLE[tmp[2U]] << 6U) | BASE64_DECODE_MAP_TABLE[tmp[3U]];
287         idx++;
288         tmp = &tmp[4U];
289     }
290 
291     /* processing of less than four characters */
292     if (tmpLen > 1U) {
293         /* process the case of one character */
294         dstBuf[idx] = (BASE64_DECODE_MAP_TABLE[tmp[0U]] << 2U) | (BASE64_DECODE_MAP_TABLE[tmp[1U]] >> 4U);
295         idx++;
296     }
297 
298     if (tmpLen > 2U) {
299         /* process the case of two characters */
300         dstBuf[idx] = (BASE64_DECODE_MAP_TABLE[tmp[1U]] << 4U) | (BASE64_DECODE_MAP_TABLE[tmp[2U]] >> 2U);
301         idx++;
302     }
303 
304     if (tmpLen > 3U) {
305         /* process the case of three characters */
306         dstBuf[idx] = (BASE64_DECODE_MAP_TABLE[tmp[2U]] << 6U) | BASE64_DECODE_MAP_TABLE[tmp[3U]];
307         idx++;
308     }
309     *dstBufLen = idx;
310     return BSL_SUCCESS;
311 }
312 
BslBase64ArithDecodeProc(const char * srcBuf,const uint32_t srcBufLen,uint8_t * dstBuf,uint32_t * dstBufLen)313 static int32_t BslBase64ArithDecodeProc(const char *srcBuf, const uint32_t srcBufLen, uint8_t *dstBuf,
314     uint32_t *dstBufLen)
315 {
316     uint8_t *buf = NULL;
317     uint32_t bufLen; /* length to be decoded after redundant characters are deleted */
318     int32_t ret;
319 
320     buf = BSL_SAL_Malloc((uint32_t)srcBufLen);
321     if (buf == NULL) {
322         return BSL_MALLOC_FAIL;
323     }
324     bufLen = srcBufLen;
325     /* Delete the extra white space characters (\r\n, space, '=') */
326     ret = BslBase64Normalization(srcBuf, (const uint32_t)srcBufLen, buf, &bufLen);
327     if (ret != BSL_SUCCESS) {
328         BSL_SAL_FREE(buf);
329         return ret;
330     }
331 
332     /* Decode the base64 character string. */
333     ret = BslBase64DecodeBuffer(buf, (const uint32_t)bufLen, dstBuf, dstBufLen);
334     if (ret != BSL_SUCCESS) {
335         BSL_SAL_FREE(buf);
336         return ret;
337     }
338 
339     BSL_SAL_FREE(buf);
340     return BSL_SUCCESS;
341 }
342 
343 /* Ensure that dstBuf and dstBufLen are correctly created. */
BSL_BASE64_Decode(const char * srcBuf,const uint32_t srcBufLen,uint8_t * dstBuf,uint32_t * dstBufLen)344 int32_t BSL_BASE64_Decode(const char *srcBuf, const uint32_t srcBufLen, uint8_t *dstBuf, uint32_t *dstBufLen)
345 {
346     int32_t ret;
347 
348     /* An error is returned when a parameter is abnormal. */
349     if (srcBuf == NULL || dstBuf == NULL || dstBufLen == NULL) {
350         BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
351         return BSL_NULL_INPUT;
352     }
353 
354     /* The length of dstBuf of the user must be at least (srcBufLen+3)/4*3. */
355     if (*dstBufLen < BSL_BASE64_DEC_ENOUGH_LEN(srcBufLen)) {
356         BSL_ERR_PUSH_ERROR(BSL_BASE64_BUF_NOT_ENOUGH);
357         return BSL_BASE64_BUF_NOT_ENOUGH;
358     }
359 
360     ret = BslBase64ArithDecodeProc(srcBuf, srcBufLen, dstBuf, dstBufLen);  /* start decoding */
361     if (ret != BSL_SUCCESS) {
362         BSL_ERR_PUSH_ERROR(ret);
363     }
364 
365     return ret;
366 }
367 
BSL_BASE64_EncodeInit(BSL_Base64Ctx * ctx)368 int32_t BSL_BASE64_EncodeInit(BSL_Base64Ctx *ctx)
369 {
370     if (ctx == NULL) {
371         BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
372         return BSL_NULL_INPUT;
373     }
374     ctx->length = HITLS_BASE64_CTX_LENGTH;
375     ctx->num = 0;
376     ctx->flags = 0;
377     return BSL_SUCCESS;
378 }
379 
BSL_BASE64_EncodeUpdate(BSL_Base64Ctx * ctx,const uint8_t * srcBuf,uint32_t srcBufLen,char * dstBuf,uint32_t * dstBufLen)380 int32_t BSL_BASE64_EncodeUpdate(BSL_Base64Ctx *ctx, const uint8_t *srcBuf, uint32_t srcBufLen,
381     char *dstBuf, uint32_t *dstBufLen)
382 {
383     /* ensure the validity of dstBuf */
384     if (ctx == NULL || srcBuf == NULL || dstBuf == NULL || srcBufLen == 0 || dstBufLen == NULL) {
385         BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
386         return BSL_NULL_INPUT;
387     }
388     if (ctx->length != HITLS_BASE64_CTX_LENGTH) {
389         BSL_ERR_PUSH_ERROR(BSL_INVALID_ARG);
390         return BSL_INVALID_ARG;
391     }
392     /* By default, the user selects the line feed, considers the terminator,
393        and checks whether the length meets the (srcBufLen + ctx->num)/48*65+1 requirement. */
394     if (*dstBufLen < ((srcBufLen + ctx->num) / HITLS_BASE64_CTX_LENGTH * (BASE64_DECODE_BLOCKSIZE + 1) + 1)) {
395         BSL_ERR_PUSH_ERROR(BSL_BASE64_BUF_NOT_ENOUGH);
396         return BSL_BASE64_BUF_NOT_ENOUGH;
397     }
398 
399     *dstBufLen = 0;
400 
401     /* If srcBuf is too short for a buf, store it in the buf first. */
402     if (srcBufLen < ctx->length - ctx->num) {
403         (void)memcpy_s(&(ctx->buf[ctx->num]), srcBufLen, srcBuf, srcBufLen);
404         ctx->num += srcBufLen;
405         return BSL_SUCCESS;
406     }
407 
408     BslBase64EncodeProcess(ctx, &srcBuf, &srcBufLen, dstBuf, dstBufLen);
409 
410     /* If the remaining bytes are less than 48 bytes, store the bytes in the buf and wait for next processing. */
411     if (srcBufLen != 0) {
412         /* Ensure that srcBufLen < 48 */
413         (void)memcpy_s(&(ctx->buf[0]), srcBufLen, srcBuf, srcBufLen);
414     }
415     ctx->num = srcBufLen;
416     return BSL_SUCCESS;
417 }
418 
BSL_BASE64_EncodeFinal(BSL_Base64Ctx * ctx,char * dstBuf,uint32_t * dstBufLen)419 int32_t BSL_BASE64_EncodeFinal(BSL_Base64Ctx *ctx, char *dstBuf, uint32_t *dstBufLen)
420 {
421     uint32_t tmpDstLen = 0;
422     if (ctx == NULL || dstBuf == NULL || dstBufLen == NULL) {
423         BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
424         return BSL_NULL_INPUT;
425     }
426     if (ctx->num == 0) {
427         *dstBufLen = 0;
428         return BSL_SUCCESS;
429     }
430 
431     if (*dstBufLen < BSL_BASE64_ENC_ENOUGH_LEN((ctx->num))) {
432         BSL_ERR_PUSH_ERROR(BSL_BASE64_BUF_NOT_ENOUGH);
433         return BSL_BASE64_BUF_NOT_ENOUGH;
434     }
435 
436     BslBase64ArithEncodeProc((const uint8_t *)ctx->buf, ctx->num, dstBuf, &tmpDstLen);
437     if ((ctx->flags & BSL_BASE64_FLAGS_NO_NEWLINE) == 0) {
438         dstBuf[tmpDstLen++] = '\n';
439     }
440     dstBuf[tmpDstLen] = '\0';
441     *dstBufLen = tmpDstLen;
442     ctx->num = 0;
443     return BSL_SUCCESS;
444 }
445 
BSL_BASE64_DecodeInit(BSL_Base64Ctx * ctx)446 int32_t BSL_BASE64_DecodeInit(BSL_Base64Ctx *ctx)
447 {
448     if (ctx == NULL) {
449         BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
450         return BSL_NULL_INPUT;
451     }
452     ctx->num = 0;
453     ctx->length = 0;
454     ctx->flags = 0;
455     ctx->paddingCnt = 0;
456     return BSL_SUCCESS;
457 }
458 
BSL_BASE64_DecodeUpdate(BSL_Base64Ctx * ctx,const char * srcBuf,const uint32_t srcBufLen,uint8_t * dstBuf,uint32_t * dstBufLen)459 int32_t BSL_BASE64_DecodeUpdate(BSL_Base64Ctx *ctx, const char *srcBuf, const uint32_t srcBufLen,
460     uint8_t *dstBuf, uint32_t *dstBufLen)
461 {
462     if (ctx == NULL || srcBuf == NULL || dstBuf == NULL || srcBufLen == 0 || dstBufLen == NULL) {
463         BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
464         return BSL_NULL_INPUT;
465     }
466     /* Estimated maximum value. By default, the input srcBuf is without line feed. Each line contains 64 characters.
467        Check whether the length meets the (srcBufLen + ctx->num)/64*48 requirement. */
468     if (*dstBufLen < ((srcBufLen + ctx->num) / BASE64_DECODE_BLOCKSIZE * HITLS_BASE64_CTX_LENGTH)) {
469         BSL_ERR_PUSH_ERROR(BSL_BASE64_BUF_NOT_ENOUGH);
470         return BSL_BASE64_BUF_NOT_ENOUGH;
471     }
472 
473     uint32_t num = ctx->num;
474     uint32_t totalLen = 0;
475     uint32_t decodeLen = 0;
476     uint8_t *tmpBuf = ctx->buf;
477     int32_t ret = BSL_SUCCESS;
478     uint8_t *dstTmp = dstBuf;
479 
480     for (uint32_t i = 0U; i < srcBufLen; i++) {
481         ret = BslBase64DecodeCheck(srcBuf[i], &ctx->paddingCnt);
482         if (ret != BSL_SUCCESS) {
483             *dstBufLen = 0;
484             if (ret == BSL_BASE64_HEADER) {
485                 *dstBufLen = totalLen;
486             }
487             return ret;
488         }
489 
490         if (BASE64_DECODE_MAP_TABLE[(uint8_t)srcBuf[i]] < 64U) { /* 0U ~ 63U are valid characters */
491             /* If num >= 64, it indicates that someone has modified the ctx.
492                If this happens, refuse to write any more data. */
493             if (num >= BASE64_DECODE_BLOCKSIZE) {
494                 *dstBufLen = 0;
495                 ctx->num = num;
496                 BSL_ERR_PUSH_ERROR(BSL_BASE64_ILLEGALLY_MODIFIED);
497                 return BSL_BASE64_ILLEGALLY_MODIFIED;
498             }
499             tmpBuf[num++] = (uint8_t)srcBuf[i]; /* save valid base64 characters */
500         }
501 
502         /* A round of block decoding is performed every time the num reaches 64, and then the buf is cleared. */
503         if (num == BASE64_DECODE_BLOCKSIZE) {
504             ret = BslBase64DecodeBuffer(tmpBuf, num, dstTmp, &decodeLen);
505             if (ret != BSL_SUCCESS) {
506                 *dstBufLen = 0;
507                 ctx->num = 0;
508                 BSL_ERR_PUSH_ERROR(BSL_BASE64_DECODE_FAILED);
509                 return BSL_BASE64_DECODE_FAILED;
510             }
511             num = 0;
512             totalLen += decodeLen;
513             dstTmp += decodeLen;
514         }
515     }
516     *dstBufLen = totalLen;
517     ctx->num = num;
518     return BSL_SUCCESS;
519 }
520 
BSL_BASE64_DecodeFinal(BSL_Base64Ctx * ctx,uint8_t * dstBuf,uint32_t * dstBufLen)521 int32_t BSL_BASE64_DecodeFinal(BSL_Base64Ctx *ctx, uint8_t *dstBuf, uint32_t *dstBufLen)
522 {
523     int32_t ret = BSL_SUCCESS;
524     uint32_t totalLen = 0;
525 
526     if (ctx == NULL || dstBuf == NULL || dstBufLen == NULL) {
527         BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
528         return BSL_NULL_INPUT;
529     }
530 
531     if (ctx->num == 0) {
532         *dstBufLen = 0;
533         return ret;
534     }
535 
536     if (*dstBufLen < BSL_BASE64_DEC_ENOUGH_LEN((ctx->num))) {
537         BSL_ERR_PUSH_ERROR(BSL_BASE64_BUF_NOT_ENOUGH);
538         return BSL_BASE64_BUF_NOT_ENOUGH;
539     }
540 
541     ret = BslBase64DecodeBuffer((const uint8_t *)ctx->buf, ctx->num, dstBuf, &totalLen);
542     ctx->num = 0;
543     if (ret != BSL_SUCCESS) {
544         BSL_ERR_PUSH_ERROR(BSL_BASE64_DECODE_FAILED);
545         return BSL_BASE64_DECODE_FAILED;
546     }
547 
548     *dstBufLen = totalLen;
549     return ret;
550 }
551 
BSL_BASE64_SetFlags(BSL_Base64Ctx * ctx,uint32_t flags)552 int32_t BSL_BASE64_SetFlags(BSL_Base64Ctx *ctx, uint32_t flags)
553 {
554     if (ctx == NULL) {
555         BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
556         return BSL_NULL_INPUT;
557     }
558     ctx->flags |= flags;
559     return BSL_SUCCESS;
560 }
561 #endif /* HITLS_BSL_BASE64 */
562