MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
coding.cpp
1 /*
2  Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; see the file COPYING. If not, write to the
15  Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
16  MA 02110-1301 USA.
17 */
18 
19 /* coding.cpp implements hex and base64 encoding/decoing
20 */
21 
22 #include "runtime.hpp"
23 #include "coding.hpp"
24 #include "file.hpp"
25 
26 
27 namespace TaoCrypt {
28 
29 
30 namespace { // locals
31 
32 const byte bad = 0xFF; // invalid encoding
33 
34 const byte hexEncode[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
35  'A', 'B', 'C', 'D', 'E', 'F'
36  };
37 
38 const byte hexDecode[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
39  bad, bad, bad, bad, bad, bad, bad,
40  10, 11, 12, 13, 14, 15
41  }; // A starts at 0x41 not 0x3A
42 
43 
44 const byte base64Encode[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
45  'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
46  'U', 'V', 'W', 'X', 'Y', 'Z',
47  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
48  'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
49  'u', 'v', 'w', 'x', 'y', 'z',
50  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
51  '+', '/'
52  };
53 
54 const byte base64Decode[] = { 62, bad, bad, bad, 63, // + starts at 0x2B
55  52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
56  bad, bad, bad, bad, bad, bad, bad,
57  0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
58  10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
59  20, 21, 22, 23, 24, 25,
60  bad, bad, bad, bad, bad, bad,
61  26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
62  36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
63  46, 47, 48, 49, 50, 51
64  };
65 
66 const byte pad = '=';
67 const int pemLineSz = 64;
68 
69 } // local namespace
70 
71 
72 // Hex Encode
73 void HexEncoder::Encode()
74 {
75  word32 bytes = plain_.size();
76  encoded_.New(bytes * 2);
77 
78  word32 i = 0;
79 
80  while (bytes--) {
81  byte p = plain_.next();
82 
83  byte b = p >> 4;
84  byte b2 = p & 0xF;
85 
86  encoded_[i++] = hexEncode[b];
87  encoded_[i++] = hexEncode[b2];
88  }
89 
90  plain_.reset(encoded_);
91 }
92 
93 
94 // Hex Decode
95 void HexDecoder::Decode()
96 {
97  word32 bytes = coded_.size();
98  decoded_.New(bytes / 2);
99 
100  word32 i(0);
101 
102  while (bytes) {
103  byte b = coded_.next() - 0x30; // 0 starts at 0x30
104  byte b2 = coded_.next() - 0x30;
105 
106  // sanity checks
107  if (b >= sizeof(hexDecode)/sizeof(hexDecode[0])) {
108  coded_.SetError(PEM_E);
109  return;
110  }
111  if (b2 >= sizeof(hexDecode)/sizeof(hexDecode[0])) {
112  coded_.SetError(PEM_E);
113  return;
114  }
115 
116  b = hexDecode[b];
117  b2 = hexDecode[b2];
118 
119  decoded_[i++] = (b << 4) | b2;
120  bytes -= 2;
121  }
122 
123  coded_.reset(decoded_);
124 }
125 
126 
127 // Base 64 Encode
128 void Base64Encoder::Encode()
129 {
130  word32 bytes = plain_.size();
131  word32 outSz = (bytes + 3 - 1) / 3 * 4;
132 
133  outSz += (outSz + pemLineSz - 1) / pemLineSz; // new lines
134  encoded_.New(outSz);
135 
136  word32 i = 0;
137  word32 j = 0;
138 
139  while (bytes > 2) {
140  byte b1 = plain_.next();
141  byte b2 = plain_.next();
142  byte b3 = plain_.next();
143 
144  // encoded idx
145  byte e1 = b1 >> 2;
146  byte e2 = ((b1 & 0x3) << 4) | (b2 >> 4);
147  byte e3 = ((b2 & 0xF) << 2) | (b3 >> 6);
148  byte e4 = b3 & 0x3F;
149 
150  // store
151  encoded_[i++] = base64Encode[e1];
152  encoded_[i++] = base64Encode[e2];
153  encoded_[i++] = base64Encode[e3];
154  encoded_[i++] = base64Encode[e4];
155 
156  bytes -= 3;
157 
158  if ((++j % 16) == 0 && bytes)
159  encoded_[i++] = '\n';
160  }
161 
162  // last integral
163  if (bytes) {
164  bool twoBytes = (bytes == 2);
165 
166  byte b1 = plain_.next();
167  byte b2 = (twoBytes) ? plain_.next() : 0;
168 
169  byte e1 = b1 >> 2;
170  byte e2 = ((b1 & 0x3) << 4) | (b2 >> 4);
171  byte e3 = (b2 & 0xF) << 2;
172 
173  encoded_[i++] = base64Encode[e1];
174  encoded_[i++] = base64Encode[e2];
175  encoded_[i++] = (twoBytes) ? base64Encode[e3] : pad;
176  encoded_[i++] = pad;
177  }
178 
179  encoded_[i++] = '\n';
180 
181  if (i == outSz)
182  plain_.reset(encoded_);
183 }
184 
185 
186 // Base 64 Decode
187 void Base64Decoder::Decode()
188 {
189  word32 bytes = coded_.size();
190  word32 plainSz = bytes - ((bytes + (pemLineSz - 1)) / pemLineSz);
191  const byte maxIdx = (byte)sizeof(base64Decode) + 0x2B - 1;
192  plainSz = ((plainSz * 3) / 4) + 3;
193  decoded_.New(plainSz);
194 
195  word32 i = 0;
196  word32 j = 0;
197 
198  while (bytes > 3) {
199  byte e1 = coded_.next();
200  byte e2 = coded_.next();
201  byte e3 = coded_.next();
202  byte e4 = coded_.next();
203 
204  if (e1 == 0) // end file 0's
205  break;
206 
207  bool pad3 = false;
208  bool pad4 = false;
209  if (e3 == pad)
210  pad3 = true;
211  if (e4 == pad)
212  pad4 = true;
213 
214  if (e1 < 0x2B || e2 < 0x2B || e3 < 0x2B || e4 < 0x2B) {
215  coded_.SetError(PEM_E);
216  return;
217  }
218 
219  if (e1 > maxIdx || e2 > maxIdx || e3 > maxIdx || e4 > maxIdx) {
220  coded_.SetError(PEM_E);
221  return;
222  }
223 
224  e1 = base64Decode[e1 - 0x2B];
225  e2 = base64Decode[e2 - 0x2B];
226  e3 = (e3 == pad) ? 0 : base64Decode[e3 - 0x2B];
227  e4 = (e4 == pad) ? 0 : base64Decode[e4 - 0x2B];
228 
229  byte b1 = (e1 << 2) | (e2 >> 4);
230  byte b2 = ((e2 & 0xF) << 4) | (e3 >> 2);
231  byte b3 = ((e3 & 0x3) << 6) | e4;
232 
233  decoded_[i++] = b1;
234  if (!pad3)
235  decoded_[i++] = b2;
236  if (!pad4)
237  decoded_[i++] = b3;
238  else
239  break;
240 
241  bytes -= 4;
242  if ((++j % 16) == 0) {
243  byte endLine = coded_.next();
244  bytes--;
245  while (endLine == ' ') { // remove possible whitespace
246  endLine = coded_.next();
247  bytes--;
248  }
249  if (endLine == '\r') {
250  endLine = coded_.next();
251  bytes--;
252  }
253  if (endLine != '\n') {
254  coded_.SetError(PEM_E);
255  return;
256  }
257  }
258  }
259 
260  if (i != decoded_.size())
261  decoded_.resize(i);
262  coded_.reset(decoded_);
263 }
264 
265 
266 } // namespace