• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 "base64_utils.h"
17 
18 #include <array>
19 namespace OHOS {
20 namespace HDI {
21 namespace Drm {
22 namespace V1_0 {
23 #ifdef __linux__
24 static std::string BASE64_CHARS = /* NOLINT */
25     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
26     "abcdefghijklmnopqrstuvwxyz"
27     "0123456789+/";
28 
29 static constexpr const uint32_t CHAR_ARRAY_LENGTH_THREE = 3;
30 static constexpr const uint32_t CHAR_ARRAY_LENGTH_FOUR = 4;
31 
32 enum BASE64_ENCODE_CONSTANT : uint8_t {
33     BASE64_ENCODE_MASK1 = 0xfc,
34     BASE64_ENCODE_MASK2 = 0x03,
35     BASE64_ENCODE_MASK3 = 0x0f,
36     BASE64_ENCODE_MASK4 = 0x3f,
37     BASE64_ENCODE_MASK5 = 0xf0,
38     BASE64_ENCODE_MASK6 = 0xc0,
39     BASE64_ENCODE_OFFSET2 = 2,
40     BASE64_ENCODE_OFFSET4 = 4,
41     BASE64_ENCODE_OFFSET6 = 6,
42     BASE64_ENCODE_INDEX0 = 0,
43     BASE64_ENCODE_INDEX1 = 1,
44     BASE64_ENCODE_INDEX2 = 2,
45 };
46 
47 enum BASE64_DECODE_CONSTANT : uint8_t {
48     BASE64_DECODE_MASK1 = 0x30,
49     BASE64_DECODE_MASK2 = 0xf,
50     BASE64_DECODE_MASK3 = 0x3c,
51     BASE64_DECODE_MASK4 = 0x3,
52     BASE64_DECODE_OFFSET2 = 2,
53     BASE64_DECODE_OFFSET4 = 4,
54     BASE64_DECODE_OFFSET6 = 6,
55     BASE64_DECODE_INDEX0 = 0,
56     BASE64_DECODE_INDEX1 = 1,
57     BASE64_DECODE_INDEX2 = 2,
58     BASE64_DECODE_INDEX3 = 3,
59 };
60 
IsBase64Char(const char c)61 static inline bool IsBase64Char(const char c)
62 {
63     return (isalnum(c) || (c == '+') || (c == '/'));
64 }
65 
MakeCharFour(const std::array<uint8_t,CHAR_ARRAY_LENGTH_THREE> & charArrayThree,std::array<uint8_t,CHAR_ARRAY_LENGTH_FOUR> & charArrayFour)66 static inline void MakeCharFour(const std::array<uint8_t, CHAR_ARRAY_LENGTH_THREE> &charArrayThree,
67     std::array<uint8_t, CHAR_ARRAY_LENGTH_FOUR> &charArrayFour)
68 {
69     const uint8_t table[CHAR_ARRAY_LENGTH_FOUR] = {
70         static_cast<uint8_t>((charArrayThree[BASE64_ENCODE_INDEX0] & BASE64_ENCODE_MASK1) >> BASE64_ENCODE_OFFSET2),
71         static_cast<uint8_t>(((charArrayThree[BASE64_ENCODE_INDEX0] & BASE64_ENCODE_MASK2) << BASE64_ENCODE_OFFSET4) +
72                              ((charArrayThree[BASE64_ENCODE_INDEX1] & BASE64_ENCODE_MASK5) >> BASE64_ENCODE_OFFSET4)),
73         static_cast<uint8_t>(((charArrayThree[BASE64_ENCODE_INDEX1] & BASE64_ENCODE_MASK3) << BASE64_ENCODE_OFFSET2) +
74                              ((charArrayThree[BASE64_ENCODE_INDEX2] & BASE64_ENCODE_MASK6) >> BASE64_ENCODE_OFFSET6)),
75         static_cast<uint8_t>(charArrayThree[BASE64_ENCODE_INDEX2] & BASE64_ENCODE_MASK4),
76     };
77     for (size_t index = 0; index < CHAR_ARRAY_LENGTH_FOUR; ++index) {
78         charArrayFour[index] = table[index];
79     }
80 }
81 
MakeCharTree(const std::array<uint8_t,CHAR_ARRAY_LENGTH_FOUR> & charArrayFour,std::array<uint8_t,CHAR_ARRAY_LENGTH_THREE> & charArrayThree)82 static inline void MakeCharTree(const std::array<uint8_t, CHAR_ARRAY_LENGTH_FOUR> &charArrayFour,
83     std::array<uint8_t, CHAR_ARRAY_LENGTH_THREE> &charArrayThree)
84 {
85     const uint8_t table[CHAR_ARRAY_LENGTH_THREE] = {
86         static_cast<uint8_t>((charArrayFour[BASE64_DECODE_INDEX0] << BASE64_DECODE_OFFSET2) +
87                              ((charArrayFour[BASE64_DECODE_INDEX1] & BASE64_DECODE_MASK1) >> BASE64_DECODE_OFFSET4)),
88         static_cast<uint8_t>(((charArrayFour[BASE64_DECODE_INDEX1] & BASE64_DECODE_MASK2) << BASE64_DECODE_OFFSET4) +
89                              ((charArrayFour[BASE64_DECODE_INDEX2] & BASE64_DECODE_MASK3) >> BASE64_DECODE_OFFSET2)),
90         static_cast<uint8_t>(((charArrayFour[BASE64_DECODE_INDEX2] & BASE64_DECODE_MASK4) << BASE64_DECODE_OFFSET6) +
91                              charArrayFour[BASE64_DECODE_INDEX3]),
92     };
93     for (size_t index = 0; index < CHAR_ARRAY_LENGTH_THREE; ++index) {
94         charArrayThree[index] = table[index];
95     }
96 }
97 
98 #endif
99 
Encode(const std::string & source)100 std::string Encode(const std::string &source)
101 {
102 #ifdef __linux__
103     auto it = source.begin();
104     std::string ret;
105     size_t index = 0;
106     std::array<uint8_t, CHAR_ARRAY_LENGTH_THREE> charArrayThree = { 0 };
107     std::array<uint8_t, CHAR_ARRAY_LENGTH_FOUR> charArrayFour = { 0 };
108 
109     while (it != source.end()) {
110         charArrayThree[index] = *it;
111         ++index;
112         ++it;
113         if (index != CHAR_ARRAY_LENGTH_THREE) {
114             continue;
115         }
116         MakeCharFour(charArrayThree, charArrayFour);
117         for (auto idx : charArrayFour) {
118             ret += BASE64_CHARS[idx];
119         }
120         index = 0;
121     }
122     if (index == 0) {
123         return ret;
124     }
125 
126     for (auto i = index; i < CHAR_ARRAY_LENGTH_THREE; ++i) {
127         charArrayThree[i] = 0;
128     }
129     MakeCharFour(charArrayThree, charArrayFour);
130 
131     for (size_t i = 0; i < index + 1; ++i) {
132         ret += BASE64_CHARS[charArrayFour[i]];
133     }
134 
135     while (index < CHAR_ARRAY_LENGTH_THREE) {
136         ret += '=';
137         ++index;
138     }
139     return ret;
140 #else
141     return {};
142 #endif
143 }
144 
Decode(const std::string & encoded)145 std::string Decode(const std::string &encoded)
146 {
147 #ifdef __linux__
148     auto it = encoded.begin();
149     size_t index = 0;
150     std::array<uint8_t, CHAR_ARRAY_LENGTH_THREE> charArrayThree = { 0 };
151     std::array<uint8_t, CHAR_ARRAY_LENGTH_FOUR> charArrayFour = { 0 };
152     std::string ret;
153 
154     while (it != encoded.end() && IsBase64Char(*it)) {
155         charArrayFour[index] = *it;
156         ++index;
157         ++it;
158         if (index != CHAR_ARRAY_LENGTH_FOUR) {
159             continue;
160         }
161         for (index = 0; index < CHAR_ARRAY_LENGTH_FOUR; ++index) {
162             charArrayFour[index] = BASE64_CHARS.find(static_cast<char>(charArrayFour[index]));
163         }
164         MakeCharTree(charArrayFour, charArrayThree);
165         for (auto idx : charArrayThree) {
166             ret += static_cast<char>(idx);
167         }
168         index = 0;
169     }
170     if (index == 0) {
171         return ret;
172     }
173 
174     for (auto i = index; i < CHAR_ARRAY_LENGTH_FOUR; ++i) {
175         charArrayFour[i] = 0;
176     }
177     for (unsigned char &i : charArrayFour) {
178         i = BASE64_CHARS.find(static_cast<char>(i));
179     }
180     MakeCharTree(charArrayFour, charArrayThree);
181 
182     for (size_t i = 0; i < index - 1; i++) {
183         ret += static_cast<char>(charArrayThree[i]);
184     }
185     return ret;
186 #else
187     return {};
188 #endif
189 }
190 } // V1_0
191 } // Drm
192 } // HDI
193 } // OHOS