1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "utils_base64.h"
17
18 #include <stdlib.h>
19 #include <stdbool.h>
20 #include <string.h>
21
22 #include "securec.h"
23
24 #include "utils_log.h"
25 #include "utils_mem.h"
26
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30
31 #define MAX_MALLOC_LEN (1 * 1024 * 1024)
32 #define RESIZE4(n) (((n) + 3) & ~3)
33
34 static const char *g_base64EncodeTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
35 static const uint8_t g_base64DecodeTable[256] = { /* 256 due to character size */
36 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
37 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
38 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 62, 65, 65, 65, 63,
39 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 65, 65, 65, 0, 65, 65,
40 65, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
41 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 65, 65, 65, 65, 65,
42 65, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
43 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 65, 65, 65, 65, 65,
44 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
45 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
46 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
47 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
48 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
49 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
50 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
51 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65
52 };
53
54 /*
55 * This function is for Base64 encoding based on the public algorithm
56 */
Base64Encode(const uint8_t * from,uint32_t fromLen,uint8_t * to,uint32_t toCheckLen)57 static int32_t Base64Encode(const uint8_t *from, uint32_t fromLen, uint8_t *to, uint32_t toCheckLen)
58 {
59 bool isInvalidParam = ((from == NULL) || (to == NULL) || (fromLen == 0));
60 if (isInvalidParam) {
61 return -1;
62 }
63
64 uint32_t tmpLen = fromLen;
65 uint32_t toLen = ((tmpLen + 2) / 3); /* Base64 encode size, add 2 for padding, and divided by 3 */
66 int padding = (int)(tmpLen % 3); /* len % 3 to get the padding size. This must be signed type! */
67 padding = (padding == 0) ? 0 : (3 - padding); /* For the padding block out of 3 */
68 if (toLen >= (toLen * 4) || (toLen == 0)) { /* For integer overflow and toLen can not be 0, with 4X */
69 return -1;
70 }
71 toLen *= 4; /* For 4 blocks */
72 if (toCheckLen < toLen) {
73 return -1;
74 }
75
76 uint32_t j = 0;
77 for (uint32_t i = 0; i < fromLen;) {
78 uint32_t a = (i < fromLen) ? (uint8_t)from[i] : 0;
79 i++;
80 uint32_t b = (i < fromLen) ? (uint8_t)from[i] : 0;
81 i++;
82 uint32_t c = (i < fromLen) ? (uint8_t)from[i] : 0;
83 i++;
84 uint32_t byte = (((a << 16) & 0x00FF0000) | ((b << 8) & 0x0000FF00) | ((c << 0) & 0x000000FF)); /* 16, 8 */
85
86 to[j++] = g_base64EncodeTable[(byte >> 18) & 0x3F]; /* get the 1st block by shift 18 */
87 to[j++] = g_base64EncodeTable[(byte >> 12) & 0x3F]; /* get the 2nd block by shift 12 */
88 to[j++] = g_base64EncodeTable[(byte >> 6) & 0x3F]; /* get the 3rd block by shift 6 */
89 to[j++] = g_base64EncodeTable[(byte >> 0) & 0x3F];
90 }
91
92 if (padding-- > 0 && toLen >= 1) {
93 to[toLen - 1] = '='; /* padding the -1 to "=" */
94 }
95 if (padding-- > 0 && toLen >= 2) { /* toLen need to be larger than 2 */
96 to[toLen - 2] = '='; /* padding the -2 to "=" */
97 }
98
99 return toLen;
100 }
101
102 /*
103 * This function is for Base64 decoding based on the public algorithm
104 */
Base64Decode(const uint8_t * from,uint8_t * to,uint32_t toCheckLen)105 static int32_t Base64Decode(const uint8_t *from, uint8_t *to, uint32_t toCheckLen)
106 {
107 bool isInvalidParam = ((from == NULL) || (to == NULL));
108 if (isInvalidParam) {
109 return -1;
110 }
111
112 uint32_t fromLen = strlen((char *)from);
113 // base64 encode Valid data Length is 4
114 bool isInvalidLength = ((fromLen < 4) || ((fromLen % 4) != 0));
115 if (isInvalidLength) {
116 return -1;
117 }
118
119 uint32_t toLen = fromLen / 4 * 3; /* Base64 decode size */
120 if (from[fromLen - 1] == '=') { /* if last 1-bit is null, make it "=" */
121 toLen--;
122 }
123 if (from[fromLen - 2] == '=') { /* if last 2-bit is null, make it "=" */
124 toLen--;
125 }
126 if (toCheckLen < toLen) {
127 return -1;
128 }
129
130 uint32_t j = 0;
131 for (uint32_t i = 0; i < fromLen;) {
132 uint32_t a = g_base64DecodeTable[from[i++]];
133 uint32_t b = g_base64DecodeTable[from[i++]];
134 uint32_t c = g_base64DecodeTable[from[i++]];
135 uint32_t d = g_base64DecodeTable[from[i++]];
136
137 // 64 is decode table max valid num.
138 bool isInvalidVariable = ((a > 64) || (b > 64) || (c > 64) || (d > 64));
139 if (isInvalidVariable) {
140 return -1;
141 }
142
143 // Converts four 6-bit data into three 8-bit data
144 uint32_t byte =
145 (((a << 18) & 0x00FC0000) | ((b << 12) & 0x0003F000) | ((c << 6) & 0x00000FC0) | ((d << 0) & 0x0000003F));
146
147 if (j < toLen) {
148 to[j++] = (byte >> 16) & 0xFF; // 16, the 3rd 8-bit
149 }
150 if (j < toLen) {
151 to[j++] = (byte >> 8) & 0xFF; // 8, the 2nd 8-bit
152 }
153 if (j < toLen) {
154 to[j++] = (byte >> 0) & 0xFF;
155 }
156 }
157 to[toLen] = '\0';
158 return toLen;
159 }
160
Base64EncodeApp(const uint8_t * from,uint32_t fromLen)161 uint8_t *Base64EncodeApp(const uint8_t *from, uint32_t fromLen)
162 {
163 if (from == NULL) {
164 SECURITY_LOG_DEBUG("invalid param, from is null");
165 return NULL;
166 }
167
168 uint32_t outSize = (fromLen + 2) / 3 * 4; // get base64 encode size
169 if (outSize + 1 > MAX_MALLOC_LEN) {
170 SECURITY_LOG_DEBUG("invalid MALLOC length");
171 return NULL;
172 }
173 uint8_t *out = (uint8_t *)MALLOC(outSize + 1);
174 if (out == NULL) {
175 SECURITY_LOG_DEBUG("malloc failed, out is null");
176 return NULL;
177 }
178
179 int realLen = Base64Encode(from, fromLen, out, outSize);
180 if (realLen < 0) {
181 SECURITY_LOG_DEBUG("Base64EncodeApp failed");
182 FREE(out);
183 return NULL;
184 }
185 out[realLen] = '\0';
186 return out;
187 }
188
Base64DecodeApp(const uint8_t * src,uint8_t ** to)189 int32_t Base64DecodeApp(const uint8_t *src, uint8_t **to)
190 {
191 if ((src == NULL) || (to == NULL)) {
192 SECURITY_LOG_DEBUG("invalid params");
193 return 0;
194 }
195
196 uint32_t decodedLen = strlen((char *)src) / 4 * 3; /* Base64 Decode size */
197 if (decodedLen + 1 > MAX_MALLOC_LEN) {
198 SECURITY_LOG_DEBUG("decodedLen error");
199 return 0;
200 }
201
202 uint8_t *decoded = (uint8_t *)MALLOC(decodedLen + 1);
203 if (decoded == NULL) {
204 SECURITY_LOG_DEBUG("malloc failed, decoded is null");
205 return 0;
206 }
207
208 int realLen = Base64Decode(src, decoded, decodedLen);
209 if (realLen < 0) {
210 SECURITY_LOG_DEBUG("Base64Decode failed");
211 FREE(decoded);
212 return 0;
213 }
214
215 decoded[realLen] = '\0';
216 *to = decoded;
217 return realLen;
218 }
219
Base64UrlDecodeApp(const uint8_t * src,uint8_t ** to)220 int32_t Base64UrlDecodeApp(const uint8_t *src, uint8_t **to)
221 {
222 if ((src == NULL) || (to == NULL)) {
223 SECURITY_LOG_DEBUG("invalid params");
224 return 0;
225 }
226
227 uint32_t sourceLen = (uint32_t)strlen((char*)src);
228 uint32_t alignLen = RESIZE4(sourceLen);
229 uint8_t *base64Str = (uint8_t *)malloc(alignLen + 1);
230 if (base64Str == NULL) {
231 SECURITY_LOG_DEBUG("Base64UrlDecodeApp malloc failed");
232 return 0;
233 }
234 (void)memset_s(base64Str, alignLen + 1, '=', alignLen + 1);
235 for (uint32_t i = 0; i < sourceLen; i++) {
236 if (src[i] == '-') {
237 base64Str[i] = '+';
238 } else if (src[i] == '_') {
239 base64Str[i] = '/';
240 } else {
241 base64Str[i] = src[i];
242 }
243 }
244 base64Str[alignLen] = '\0';
245 const uint8_t *from = base64Str;
246 int32_t realLength = Base64DecodeApp(from, to);
247 FREE(base64Str);
248 return realLength;
249 }
250
251 #ifdef __cplusplus
252 }
253 #endif