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