1 /**
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include <string.h>
17 #include <ImsMediaBinaryFormat.h>
18 #include <ImsMediaTrace.h>
19 
20 // Default value for non-printable characters
21 #define NP         0xFF
22 // Carriage-Return (\r)
23 #define CR         0x0D
24 // Line-Feed (\n)
25 #define LF         0x0A
26 // Padding character for Base64
27 #define BASE64_PAD '='
28 
29 // Constant table for Base64 value encoding / decoding
30 static const char BASE64_ENCODING_TABLE[] =
31         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
32 static const uint8_t BASE64_DECODING_TABLE[] = {
33         NP, NP, NP, NP, NP, NP, NP, NP, NP, NP,  // 0 ~ 9
34         NP, NP, NP, NP, NP, NP, NP, NP, NP, NP,  // 10 ~ 19
35         NP, NP, NP, NP, NP, NP, NP, NP, NP, NP,  // 20 ~ 29
36         NP, NP, NP, NP, NP, NP, NP, NP, NP, NP,  // 30 ~ 39
37         NP, NP, NP, 62, NP, NP, NP, 63, 52, 53,  // 40 ~ 49
38         54, 55, 56, 57, 58, 59, 60, 61, NP, NP,  // 50 ~ 59
39         NP, NP, NP, NP, NP, 0, 1, 2, 3, 4,       // 60 ~ 69
40         5, 6, 7, 8, 9, 10, 11, 12, 13, 14,       // 70 ~ 79
41         15, 16, 17, 18, 19, 20, 21, 22, 23, 24,  // 80 ~ 89
42         25, NP, NP, NP, NP, NP, NP, 26, 27, 28,  // 90 ~ 99
43         29, 30, 31, 32, 33, 34, 35, 36, 37, 38,  // 100 ~ 109
44         39, 40, 41, 42, 43, 44, 45, 46, 47, 48,  // 110 ~ 119
45         49, 50, 51, NP, NP, NP, NP, NP, NP, NP,  // 120 ~ 129
46         NP, NP, NP, NP, NP, NP, NP, NP, NP, NP,  // 130 ~ 139
47         NP, NP, NP, NP, NP, NP, NP, NP, NP, NP,  // 140 ~ 149
48         NP, NP, NP, NP, NP, NP, NP, NP, NP, NP,  // 150 ~ 159
49         NP, NP, NP, NP, NP, NP, NP, NP, NP, NP,  // 160 ~ 169
50         NP, NP, NP, NP, NP, NP, NP, NP, NP, NP,  // 170 ~ 179
51         NP, NP, NP, NP, NP, NP, NP, NP, NP, NP,  // 180 ~ 189
52         NP, NP, NP, NP, NP, NP, NP, NP, NP, NP,  // 190 ~ 199
53         NP, NP, NP, NP, NP, NP, NP, NP, NP, NP,  // 200 ~ 209
54         NP, NP, NP, NP, NP, NP, NP, NP, NP, NP,  // 210 ~ 219
55         NP, NP, NP, NP, NP, NP, NP, NP, NP, NP,  // 220 ~ 229
56         NP, NP, NP, NP, NP, NP, NP, NP, NP, NP,  // 230 ~ 239
57         NP, NP, NP, NP, NP, NP, NP, NP, NP, NP,  // 240 ~ 249
58         NP, NP, NP, NP, NP, NP                   // 250 ~ 256
59 };
60 
BinaryToBase16(char * pszDst,uint32_t nDstBuffSize,uint8_t * pbSrc,uint32_t nSrcSize)61 static bool BinaryToBase16(char* pszDst, uint32_t nDstBuffSize, uint8_t* pbSrc, uint32_t nSrcSize)
62 {
63     if (((nDstBuffSize - 1) >> 1) < nSrcSize)
64         return false;
65 
66     if (nSrcSize > 0)
67     {
68         uint32_t m, n;
69 
70         for (m = 0, n = 0; m < nSrcSize; m++)
71         {
72             int8_t c, h, l;
73 
74             c = (int8_t)pbSrc[m];
75 
76             h = (c >> 4) & 0x0F;
77             l = c & 0x0F;
78 
79             if (h < 10)
80                 h += '0';
81             else
82                 h += 'A' - 10;
83             if (l < 10)
84                 l += '0';
85             else
86                 l += 'A' - 10;
87 
88             pszDst[n++] = h;
89             pszDst[n++] = l;
90         }
91         pszDst[n] = 0;
92     }
93 
94     return true;
95 }
96 
Base16ToBinary(uint8_t * pbDst,uint32_t * pnDstSize,uint32_t nDstBuffSize,char * pszSrc)97 static bool Base16ToBinary(uint8_t* pbDst, uint32_t* pnDstSize, uint32_t nDstBuffSize, char* pszSrc)
98 {
99     uint32_t nSrcLen;
100     uint32_t src_pos, dst_pos;
101 
102     nSrcLen = strlen(pszSrc);
103     if (nSrcLen & 0x1)
104         nSrcLen++;
105     if (nDstBuffSize < (nSrcLen >> 1))
106         return false;
107     for (src_pos = 0, dst_pos = 0; src_pos < nSrcLen; src_pos += 2, dst_pos++)
108     {
109         char h, l;
110 
111         h = pszSrc[src_pos];
112         l = pszSrc[src_pos + 1];
113 
114         if (h >= '0' && h <= '9')
115             h = h - '0';
116         else if (h >= 'a' && h <= 'f')
117             h = h - 'a' + 10;
118         else if (h >= 'A' && h <= 'F')
119             h = h - 'A' + 10;
120 
121         if (l >= '0' && l <= '9')
122             l = l - '0';
123         else if (l >= 'a' && l <= 'f')
124             l = l - 'a' + 10;
125         else if (l >= 'A' && l <= 'F')
126             l = l - 'A' + 10;
127 
128         pbDst[dst_pos] = (h << 4) | l;
129     }
130 
131     *pnDstSize = dst_pos;
132 
133     return true;
134 }
135 
BinaryToBase64(char * pszDst,uint32_t nDstBuffSize,const uint8_t * pbSrc,uint32_t nSrcSize)136 static bool BinaryToBase64(
137         char* pszDst, uint32_t nDstBuffSize, const uint8_t* pbSrc, uint32_t nSrcSize)
138 {
139     char* pEncBuffer = pszDst;
140 
141     if ((nDstBuffSize - 1) < ((nSrcSize + 2) / 3 * 4))
142         return false;
143 
144     for (int32_t nPos = 0; nPos < nSrcSize; ++nPos)
145     {
146         uint8_t c6bit = (pbSrc[nPos] >> 2) & 0x3F;
147         (*pEncBuffer) = BASE64_ENCODING_TABLE[(uint8_t)c6bit];
148         pEncBuffer++;
149 
150         c6bit = (pbSrc[nPos] << 4) & 0x3F;
151 
152         if (++nPos < nSrcSize)
153             c6bit |= (pbSrc[nPos] >> 4) & 0x0F;
154 
155         (*pEncBuffer) = BASE64_ENCODING_TABLE[(uint8_t)c6bit];
156         pEncBuffer++;
157 
158         if (nPos < nSrcSize)
159         {
160             c6bit = (pbSrc[nPos] << 2) & 0x3F;
161 
162             if (++nPos < nSrcSize)
163                 c6bit |= (pbSrc[nPos] >> 6) & 0x03;
164 
165             (*pEncBuffer) = BASE64_ENCODING_TABLE[(uint8_t)c6bit];
166             pEncBuffer++;
167         }
168         else
169         {
170             ++nPos;
171             (*pEncBuffer) = BASE64_PAD;
172             pEncBuffer++;
173         }
174 
175         if (nPos < nSrcSize)
176         {
177             c6bit = pbSrc[nPos] & 0x3F;
178             (*pEncBuffer) = BASE64_ENCODING_TABLE[(uint8_t)c6bit];
179             pEncBuffer++;
180         }
181         else
182         {
183             (*pEncBuffer) = BASE64_PAD;
184             pEncBuffer++;
185         }
186     }
187 
188     (*pEncBuffer) = 0x00;
189 
190     return true;
191 }
192 
Base64ToBinary(uint8_t * pbDst,uint32_t * pnDstSize,uint32_t nDstBuffSize,char * pszSrc)193 static bool Base64ToBinary(uint8_t* pbDst, uint32_t* pnDstSize, uint32_t nDstBuffSize, char* pszSrc)
194 {
195     uint8_t* pDecBuffer = pbDst;
196     uint32_t nSrcLen;
197 
198     nSrcLen = strlen(pszSrc);
199 
200     if (nDstBuffSize < ((nSrcLen >> 2) * 3 + (nSrcLen & 0x3)))
201         return false;
202 
203     for (int32_t nPos = 0; nPos < nSrcLen; ++nPos)
204     {
205         if (pszSrc[nPos] == LF)
206             nPos += 1;
207         if (pszSrc[nPos] == CR)
208             nPos += 2;
209 
210         uint8_t c8bit = BASE64_DECODING_TABLE[(uint8_t)pszSrc[nPos]];
211         ++nPos;
212 
213         if (pszSrc[nPos] == LF)
214             nPos += 1;
215         if (pszSrc[nPos] == CR)
216             nPos += 2;
217 
218         uint8_t c8bit1 = BASE64_DECODING_TABLE[(uint8_t)pszSrc[nPos]];
219         c8bit = (c8bit << 2) | ((c8bit1 >> 4) & 0x03);
220         (*pDecBuffer) = c8bit;
221         pDecBuffer++;
222 
223         if (++nPos < nSrcLen)
224         {
225             if (pszSrc[nPos] == LF)
226                 nPos += 1;
227             if (pszSrc[nPos] == CR)
228                 nPos += 2;
229 
230             c8bit = pszSrc[nPos];
231 
232             if (c8bit == BASE64_PAD)
233                 break;
234 
235             c8bit = BASE64_DECODING_TABLE[(uint8_t)pszSrc[nPos]];
236             c8bit1 = ((c8bit1 << 4) & 0xF0) | ((c8bit >> 2) & 0x0F);
237             (*pDecBuffer) = c8bit1;
238             pDecBuffer++;
239         }
240 
241         if (++nPos < nSrcLen)
242         {
243             if (pszSrc[nPos] == LF)
244                 nPos += 1;
245             if (pszSrc[nPos] == CR)
246                 nPos += 2;
247 
248             c8bit1 = pszSrc[nPos];
249 
250             if (c8bit1 == BASE64_PAD)
251                 break;
252 
253             c8bit1 = BASE64_DECODING_TABLE[(uint8_t)pszSrc[nPos]];
254             c8bit = ((c8bit << 6) & 0xC0) | c8bit1;
255             (*pDecBuffer) = c8bit;
256             pDecBuffer++;
257         }
258     }
259 
260     *pnDstSize = (uint32_t)(pDecBuffer - pbDst);
261 
262     return true;
263 }
264 
BinaryToBase00(char * pszDst,uint32_t nDstBuffSize,uint8_t * pbSrc,uint32_t nSrcSize,uint32_t eFormat)265 bool ImsMediaBinaryFormat::BinaryToBase00(
266         char* pszDst, uint32_t nDstBuffSize, uint8_t* pbSrc, uint32_t nSrcSize, uint32_t eFormat)
267 {
268     switch (eFormat)
269     {
270         case BINARY_FORMAT_BASE16:
271             return BinaryToBase16(pszDst, nDstBuffSize, pbSrc, nSrcSize);
272         case BINARY_FORMAT_BASE64:
273             return BinaryToBase64(pszDst, nDstBuffSize, pbSrc, nSrcSize);
274         case BINARY_FORMAT_BASE32:
275         default:
276             IMLOGE1("[BinaryToBase00] not supported binary format %d", eFormat);
277             return false;
278     }
279 }
280 
Base00ToBinary(uint8_t * pbDst,uint32_t * pnDstSize,uint32_t nDstBuffSize,char * pszSrc,uint32_t eFormat)281 bool ImsMediaBinaryFormat::Base00ToBinary(
282         uint8_t* pbDst, uint32_t* pnDstSize, uint32_t nDstBuffSize, char* pszSrc, uint32_t eFormat)
283 {
284     switch (eFormat)
285     {
286         case BINARY_FORMAT_BASE16:
287             return Base16ToBinary(pbDst, pnDstSize, nDstBuffSize, pszSrc);
288         case BINARY_FORMAT_BASE64:
289             return Base64ToBinary(pbDst, pnDstSize, nDstBuffSize, pszSrc);
290         case BINARY_FORMAT_BASE32:
291         default:
292             IMLOGE1("[Base00ToBinary] not supported binary format %d", eFormat);
293             return false;
294     }
295 }
296