• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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