1 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2    file Copyright.txt or https://cmake.org/licensing#kwsys for details.  */
3 #include "kwsysPrivate.h"
4 #include KWSYS_HEADER(Base64.h)
5 
6 /* Work-around CMake dependency scanning limitation.  This must
7    duplicate the above list of headers.  */
8 #if 0
9 #  include "Base64.h.in"
10 #endif
11 
12 static const unsigned char kwsysBase64EncodeTable[65] =
13   "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
14   "abcdefghijklmnopqrstuvwxyz"
15   "0123456789+/";
16 
17 static const unsigned char kwsysBase64DecodeTable[256] = {
18   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
19   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
20   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
21   0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xFF, 0xFF, 0x3F, 0x34, 0x35, 0x36, 0x37,
22   0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
23   0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
24   0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
25   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
26   0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D,
27   0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
28   /*------------------------------------*/
29   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
30   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
31   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
32   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
33   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
34   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
35   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
36   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
37   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
38   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
39 };
40 
kwsysBase64EncodeChar(int c)41 static unsigned char kwsysBase64EncodeChar(int c)
42 {
43   return kwsysBase64EncodeTable[(unsigned char)c];
44 }
45 
kwsysBase64DecodeChar(unsigned char c)46 static unsigned char kwsysBase64DecodeChar(unsigned char c)
47 {
48   return kwsysBase64DecodeTable[c];
49 }
50 
51 /* Encode 3 bytes into a 4 byte string. */
kwsysBase64_Encode3(const unsigned char * src,unsigned char * dest)52 void kwsysBase64_Encode3(const unsigned char* src, unsigned char* dest)
53 {
54   dest[0] = kwsysBase64EncodeChar((src[0] >> 2) & 0x3F);
55   dest[1] =
56     kwsysBase64EncodeChar(((src[0] << 4) & 0x30) | ((src[1] >> 4) & 0x0F));
57   dest[2] =
58     kwsysBase64EncodeChar(((src[1] << 2) & 0x3C) | ((src[2] >> 6) & 0x03));
59   dest[3] = kwsysBase64EncodeChar(src[2] & 0x3F);
60 }
61 
62 /* Encode 2 bytes into a 4 byte string. */
kwsysBase64_Encode2(const unsigned char * src,unsigned char * dest)63 void kwsysBase64_Encode2(const unsigned char* src, unsigned char* dest)
64 {
65   dest[0] = kwsysBase64EncodeChar((src[0] >> 2) & 0x3F);
66   dest[1] =
67     kwsysBase64EncodeChar(((src[0] << 4) & 0x30) | ((src[1] >> 4) & 0x0F));
68   dest[2] = kwsysBase64EncodeChar(((src[1] << 2) & 0x3C));
69   dest[3] = '=';
70 }
71 
72 /* Encode 1 bytes into a 4 byte string. */
kwsysBase64_Encode1(const unsigned char * src,unsigned char * dest)73 void kwsysBase64_Encode1(const unsigned char* src, unsigned char* dest)
74 {
75   dest[0] = kwsysBase64EncodeChar((src[0] >> 2) & 0x3F);
76   dest[1] = kwsysBase64EncodeChar(((src[0] << 4) & 0x30));
77   dest[2] = '=';
78   dest[3] = '=';
79 }
80 
81 /* Encode 'length' bytes from the input buffer and store the
82    encoded stream into the output buffer. Return the length of the encoded
83    buffer (output). Note that the output buffer must be allocated by the caller
84    (length * 1.5 should be a safe estimate).  If 'mark_end' is true than an
85    extra set of 4 bytes is added to the end of the stream if the input is a
86    multiple of 3 bytes.  These bytes are invalid chars and therefore they will
87    stop the decoder thus enabling the caller to decode a stream without
88    actually knowing how much data to expect (if the input is not a multiple of
89    3 bytes then the extra padding needed to complete the encode 4 bytes will
90    stop the decoding anyway).  */
kwsysBase64_Encode(const unsigned char * input,size_t length,unsigned char * output,int mark_end)91 size_t kwsysBase64_Encode(const unsigned char* input, size_t length,
92                           unsigned char* output, int mark_end)
93 {
94   const unsigned char* ptr = input;
95   const unsigned char* end = input + length;
96   unsigned char* optr = output;
97 
98   /* Encode complete triplet */
99 
100   while ((end - ptr) >= 3) {
101     kwsysBase64_Encode3(ptr, optr);
102     ptr += 3;
103     optr += 4;
104   }
105 
106   /* Encodes a 2-byte ending into 3 bytes and 1 pad byte and writes. */
107 
108   if (end - ptr == 2) {
109     kwsysBase64_Encode2(ptr, optr);
110     optr += 4;
111   }
112 
113   /* Encodes a 1-byte ending into 2 bytes and 2 pad bytes */
114 
115   else if (end - ptr == 1) {
116     kwsysBase64_Encode1(ptr, optr);
117     optr += 4;
118   }
119 
120   /* Do we need to mark the end */
121 
122   else if (mark_end) {
123     optr[0] = optr[1] = optr[2] = optr[3] = '=';
124     optr += 4;
125   }
126 
127   return (size_t)(optr - output);
128 }
129 
130 /* Decode 4 bytes into a 3 byte string. */
kwsysBase64_Decode3(const unsigned char * src,unsigned char * dest)131 int kwsysBase64_Decode3(const unsigned char* src, unsigned char* dest)
132 {
133   unsigned char d0;
134   unsigned char d1;
135   unsigned char d2;
136   unsigned char d3;
137 
138   d0 = kwsysBase64DecodeChar(src[0]);
139   d1 = kwsysBase64DecodeChar(src[1]);
140   d2 = kwsysBase64DecodeChar(src[2]);
141   d3 = kwsysBase64DecodeChar(src[3]);
142 
143   /* Make sure all characters were valid */
144 
145   if (d0 == 0xFF || d1 == 0xFF || d2 == 0xFF || d3 == 0xFF) {
146     return 0;
147   }
148 
149   /* Decode the 3 bytes */
150 
151   dest[0] = (unsigned char)(((d0 << 2) & 0xFC) | ((d1 >> 4) & 0x03));
152   dest[1] = (unsigned char)(((d1 << 4) & 0xF0) | ((d2 >> 2) & 0x0F));
153   dest[2] = (unsigned char)(((d2 << 6) & 0xC0) | ((d3 >> 0) & 0x3F));
154 
155   /* Return the number of bytes actually decoded */
156 
157   if (src[2] == '=') {
158     return 1;
159   }
160   if (src[3] == '=') {
161     return 2;
162   }
163   return 3;
164 }
165 
166 /* Decode bytes from the input buffer and store the decoded stream
167    into the output buffer until 'length' bytes have been decoded.  Return the
168    real length of the decoded stream (which should be equal to 'length'). Note
169    that the output buffer must be allocated by the caller.  If
170    'max_input_length' is not null, then it specifies the number of encoded
171    bytes that should be at most read from the input buffer. In that case the
172    'length' parameter is ignored. This enables the caller to decode a stream
173    without actually knowing how much decoded data to expect (of course, the
174    buffer must be large enough). */
kwsysBase64_Decode(const unsigned char * input,size_t length,unsigned char * output,size_t max_input_length)175 size_t kwsysBase64_Decode(const unsigned char* input, size_t length,
176                           unsigned char* output, size_t max_input_length)
177 {
178   const unsigned char* ptr = input;
179   unsigned char* optr = output;
180 
181   /* Decode complete triplet */
182 
183   if (max_input_length) {
184     const unsigned char* end = input + max_input_length;
185     while (ptr < end) {
186       int len = kwsysBase64_Decode3(ptr, optr);
187       optr += len;
188       if (len < 3) {
189         return (size_t)(optr - output);
190       }
191       ptr += 4;
192     }
193   } else {
194     unsigned char* oend = output + length;
195     while ((oend - optr) >= 3) {
196       int len = kwsysBase64_Decode3(ptr, optr);
197       optr += len;
198       if (len < 3) {
199         return (size_t)(optr - output);
200       }
201       ptr += 4;
202     }
203 
204     /* Decode the last triplet */
205 
206     if (oend - optr == 2) {
207       unsigned char temp[3];
208       int len = kwsysBase64_Decode3(ptr, temp);
209       if (len >= 2) {
210         optr[0] = temp[0];
211         optr[1] = temp[1];
212         optr += 2;
213       } else if (len > 0) {
214         optr[0] = temp[0];
215         optr += 1;
216       }
217     } else if (oend - optr == 1) {
218       unsigned char temp[3];
219       int len = kwsysBase64_Decode3(ptr, temp);
220       if (len > 0) {
221         optr[0] = temp[0];
222         optr += 1;
223       }
224     }
225   }
226 
227   return (size_t)(optr - output);
228 }
229