source: UsbWattMeter/trunk/wolfssl-3.7.0/wolfcrypt/src/coding.c@ 164

Last change on this file since 164 was 164, checked in by coas-nagasima, 8 years ago

TOPPERS/ECNLサンプルアプリ「USB充電器電力計」を追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 12.6 KB
Line 
1/* coding.c
2 *
3 * Copyright (C) 2006-2015 wolfSSL Inc.
4 *
5 * This file is part of wolfSSL. (formerly known as CyaSSL)
6 *
7 * wolfSSL is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * wolfSSL is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22#ifdef HAVE_CONFIG_H
23 #include <config.h>
24#endif
25
26#include <wolfssl/wolfcrypt/settings.h>
27
28#ifndef NO_CODING
29
30#include <wolfssl/wolfcrypt/coding.h>
31#include <wolfssl/wolfcrypt/error-crypt.h>
32#include <wolfssl/wolfcrypt/logging.h>
33
34
35enum {
36 BAD = 0xFF, /* invalid encoding */
37 PAD = '=',
38 PEM_LINE_SZ = 64
39};
40
41
42static
43const byte base64Decode[] = { 62, BAD, BAD, BAD, 63, /* + starts at 0x2B */
44 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
45 BAD, BAD, BAD, BAD, BAD, BAD, BAD,
46 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
47 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
48 20, 21, 22, 23, 24, 25,
49 BAD, BAD, BAD, BAD, BAD, BAD,
50 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
51 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
52 46, 47, 48, 49, 50, 51
53 };
54
55
56int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
57{
58 word32 i = 0;
59 word32 j = 0;
60 word32 plainSz = inLen - ((inLen + (PEM_LINE_SZ - 1)) / PEM_LINE_SZ );
61 const byte maxIdx = (byte)sizeof(base64Decode) + 0x2B - 1;
62
63 plainSz = (plainSz * 3 + 3) / 4;
64 if (plainSz > *outLen) return BAD_FUNC_ARG;
65
66 while (inLen > 3) {
67 byte b1, b2, b3;
68 byte e1 = in[j++];
69 byte e2 = in[j++];
70 byte e3 = in[j++];
71 byte e4 = in[j++];
72
73 int pad3 = 0;
74 int pad4 = 0;
75
76 if (e1 == 0) /* end file 0's */
77 break;
78 if (e3 == PAD)
79 pad3 = 1;
80 if (e4 == PAD)
81 pad4 = 1;
82
83 if (e1 < 0x2B || e2 < 0x2B || e3 < 0x2B || e4 < 0x2B) {
84 WOLFSSL_MSG("Bad Base64 Decode data, too small");
85 return ASN_INPUT_E;
86 }
87
88 if (e1 > maxIdx || e2 > maxIdx || e3 > maxIdx || e4 > maxIdx) {
89 WOLFSSL_MSG("Bad Base64 Decode data, too big");
90 return ASN_INPUT_E;
91 }
92
93 e1 = base64Decode[e1 - 0x2B];
94 e2 = base64Decode[e2 - 0x2B];
95 e3 = (e3 == PAD) ? 0 : base64Decode[e3 - 0x2B];
96 e4 = (e4 == PAD) ? 0 : base64Decode[e4 - 0x2B];
97
98 b1 = (byte)((e1 << 2) | (e2 >> 4));
99 b2 = (byte)(((e2 & 0xF) << 4) | (e3 >> 2));
100 b3 = (byte)(((e3 & 0x3) << 6) | e4);
101
102 out[i++] = b1;
103 if (!pad3)
104 out[i++] = b2;
105 if (!pad4)
106 out[i++] = b3;
107 else
108 break;
109
110 inLen -= 4;
111 if (inLen && (in[j] == ' ' || in[j] == '\r' || in[j] == '\n')) {
112 byte endLine = in[j++];
113 inLen--;
114 while (inLen && endLine == ' ') { /* allow trailing whitespace */
115 endLine = in[j++];
116 inLen--;
117 }
118 if (endLine == '\r') {
119 if (inLen) {
120 endLine = in[j++];
121 inLen--;
122 }
123 }
124 if (endLine != '\n') {
125 WOLFSSL_MSG("Bad end of line in Base64 Decode");
126 return ASN_INPUT_E;
127 }
128 }
129 }
130 *outLen = i;
131
132 return 0;
133}
134
135
136#if defined(WOLFSSL_BASE64_ENCODE)
137
138static
139const byte base64Encode[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
140 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
141 'U', 'V', 'W', 'X', 'Y', 'Z',
142 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
143 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
144 'u', 'v', 'w', 'x', 'y', 'z',
145 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
146 '+', '/'
147 };
148
149
150/* make sure *i (idx) won't exceed max, store and possibly escape to out,
151 * raw means use e w/o decode, 0 on success */
152static int CEscape(int escaped, byte e, byte* out, word32* i, word32 max,
153 int raw, int getSzOnly)
154{
155 int doEscape = 0;
156 word32 needed = 1;
157 word32 idx = *i;
158
159 byte basic;
160 byte plus = 0;
161 byte equals = 0;
162 byte newline = 0;
163
164 if (raw)
165 basic = e;
166 else
167 basic = base64Encode[e];
168
169 /* check whether to escape. Only escape for EncodeEsc */
170 if (escaped == WC_ESC_NL_ENC) {
171 switch ((char)basic) {
172 case '+' :
173 plus = 1;
174 doEscape = 1;
175 needed += 2;
176 break;
177 case '=' :
178 equals = 1;
179 doEscape = 1;
180 needed += 2;
181 break;
182 case '\n' :
183 newline = 1;
184 doEscape = 1;
185 needed += 2;
186 break;
187 default:
188 /* do nothing */
189 break;
190 }
191 }
192
193 /* check size */
194 if ( (idx+needed) > max && !getSzOnly) {
195 WOLFSSL_MSG("Escape buffer max too small");
196 return BUFFER_E;
197 }
198
199 /* store it */
200 if (doEscape == 0) {
201 if(getSzOnly)
202 idx++;
203 else
204 out[idx++] = basic;
205 }
206 else {
207 if(getSzOnly)
208 idx+=3;
209 else {
210 out[idx++] = '%'; /* start escape */
211
212 if (plus) {
213 out[idx++] = '2';
214 out[idx++] = 'B';
215 }
216 else if (equals) {
217 out[idx++] = '3';
218 out[idx++] = 'D';
219 }
220 else if (newline) {
221 out[idx++] = '0';
222 out[idx++] = 'A';
223 }
224 }
225 }
226 *i = idx;
227
228 return 0;
229}
230
231
232/* internal worker, handles both escaped and normal line endings.
233 If out buffer is NULL, will return sz needed in outLen */
234static int DoBase64_Encode(const byte* in, word32 inLen, byte* out,
235 word32* outLen, int escaped)
236{
237 int ret = 0;
238 word32 i = 0,
239 j = 0,
240 n = 0; /* new line counter */
241
242 int getSzOnly = (out == NULL);
243
244 word32 outSz = (inLen + 3 - 1) / 3 * 4;
245 word32 addSz = (outSz + PEM_LINE_SZ - 1) / PEM_LINE_SZ; /* new lines */
246
247 if (escaped == WC_ESC_NL_ENC)
248 addSz *= 3; /* instead of just \n, we're doing %0A triplet */
249 else if (escaped == WC_NO_NL_ENC)
250 addSz = 0; /* encode without \n */
251
252 outSz += addSz;
253
254 /* if escaped we can't predetermine size for one pass encoding, but
255 * make sure we have enough if no escapes are in input
256 * Also need to ensure outLen valid before dereference */
257 if (!outLen || (outSz > *outLen && !getSzOnly)) return BAD_FUNC_ARG;
258
259 while (inLen > 2) {
260 byte b1 = in[j++];
261 byte b2 = in[j++];
262 byte b3 = in[j++];
263
264 /* encoded idx */
265 byte e1 = b1 >> 2;
266 byte e2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4));
267 byte e3 = (byte)(((b2 & 0xF) << 2) | (b3 >> 6));
268 byte e4 = b3 & 0x3F;
269
270 /* store */
271 ret = CEscape(escaped, e1, out, &i, *outLen, 0, getSzOnly);
272 if (ret != 0) break;
273 ret = CEscape(escaped, e2, out, &i, *outLen, 0, getSzOnly);
274 if (ret != 0) break;
275 ret = CEscape(escaped, e3, out, &i, *outLen, 0, getSzOnly);
276 if (ret != 0) break;
277 ret = CEscape(escaped, e4, out, &i, *outLen, 0, getSzOnly);
278 if (ret != 0) break;
279
280 inLen -= 3;
281
282 /* Insert newline after PEM_LINE_SZ, unless no \n requested */
283 if (escaped != WC_NO_NL_ENC && (++n % (PEM_LINE_SZ/4)) == 0 && inLen){
284 ret = CEscape(escaped, '\n', out, &i, *outLen, 1, getSzOnly);
285 if (ret != 0) break;
286 }
287 }
288
289 /* last integral */
290 if (inLen && ret == 0) {
291 int twoBytes = (inLen == 2);
292
293 byte b1 = in[j++];
294 byte b2 = (twoBytes) ? in[j++] : 0;
295
296 byte e1 = b1 >> 2;
297 byte e2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4));
298 byte e3 = (byte)((b2 & 0xF) << 2);
299
300 ret = CEscape(escaped, e1, out, &i, *outLen, 0, getSzOnly);
301 if (ret == 0)
302 ret = CEscape(escaped, e2, out, &i, *outLen, 0, getSzOnly);
303 if (ret == 0) {
304 /* third */
305 if (twoBytes)
306 ret = CEscape(escaped, e3, out, &i, *outLen, 0, getSzOnly);
307 else
308 ret = CEscape(escaped, '=', out, &i, *outLen, 1, getSzOnly);
309 }
310 /* fourth always pad */
311 if (ret == 0)
312 ret = CEscape(escaped, '=', out, &i, *outLen, 1, getSzOnly);
313 }
314
315 if (ret == 0 && escaped != WC_NO_NL_ENC)
316 ret = CEscape(escaped, '\n', out, &i, *outLen, 1, getSzOnly);
317
318 if (i != outSz && escaped != 1 && ret == 0)
319 return ASN_INPUT_E;
320
321 *outLen = i;
322 if(ret == 0)
323 return getSzOnly ? LENGTH_ONLY_E : 0;
324 return ret;
325}
326
327
328/* Base64 Encode, PEM style, with \n line endings */
329int Base64_Encode(const byte* in, word32 inLen, byte* out, word32* outLen)
330{
331 return DoBase64_Encode(in, inLen, out, outLen, WC_STD_ENC);
332}
333
334
335/* Base64 Encode, with %0A esacped line endings instead of \n */
336int Base64_EncodeEsc(const byte* in, word32 inLen, byte* out, word32* outLen)
337{
338 return DoBase64_Encode(in, inLen, out, outLen, WC_ESC_NL_ENC);
339}
340
341int Base64_Encode_NoNl(const byte* in, word32 inLen, byte* out, word32* outLen)
342{
343 return DoBase64_Encode(in, inLen, out, outLen, WC_NO_NL_ENC);
344}
345
346#endif /* defined(WOLFSSL_BASE64_ENCODE) */
347
348
349#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(HAVE_FIPS)
350
351static
352const byte hexDecode[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
353 BAD, BAD, BAD, BAD, BAD, BAD, BAD,
354 10, 11, 12, 13, 14, 15, /* upper case A-F */
355 BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
356 BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
357 BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
358 BAD, BAD, /* G - ` */
359 10, 11, 12, 13, 14, 15 /* lower case a-f */
360 }; /* A starts at 0x41 not 0x3A */
361
362int Base16_Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
363{
364 word32 inIdx = 0;
365 word32 outIdx = 0;
366
367 if (inLen == 1 && *outLen && in) {
368 byte b = in[inIdx++] - 0x30; /* 0 starts at 0x30 */
369
370 /* sanity check */
371 if (b >= sizeof(hexDecode)/sizeof(hexDecode[0]))
372 return ASN_INPUT_E;
373
374 b = hexDecode[b];
375
376 if (b == BAD)
377 return ASN_INPUT_E;
378
379 out[outIdx++] = b;
380
381 *outLen = outIdx;
382 return 0;
383 }
384
385 if (inLen % 2)
386 return BAD_FUNC_ARG;
387
388 if (*outLen < (inLen / 2))
389 return BAD_FUNC_ARG;
390
391 while (inLen) {
392 byte b = in[inIdx++] - 0x30; /* 0 starts at 0x30 */
393 byte b2 = in[inIdx++] - 0x30;
394
395 /* sanity checks */
396 if (b >= sizeof(hexDecode)/sizeof(hexDecode[0]))
397 return ASN_INPUT_E;
398 if (b2 >= sizeof(hexDecode)/sizeof(hexDecode[0]))
399 return ASN_INPUT_E;
400
401 b = hexDecode[b];
402 b2 = hexDecode[b2];
403
404 if (b == BAD || b2 == BAD)
405 return ASN_INPUT_E;
406
407 out[outIdx++] = (byte)((b << 4) | b2);
408 inLen -= 2;
409 }
410
411 *outLen = outIdx;
412 return 0;
413}
414
415int Base16_Encode(const byte* in, word32 inLen, byte* out, word32* outLen)
416{
417 word32 outIdx = 0;
418 word32 i;
419 byte hb, lb;
420
421 if (*outLen < (2 * inLen + 1))
422 return BAD_FUNC_ARG;
423
424 for (i = 0; i < inLen; i++) {
425 hb = in[i] >> 4;
426 lb = in[i] & 0x0f;
427
428 /* ASCII value */
429 hb += '0';
430 if (hb > '9')
431 hb += 7;
432
433 /* ASCII value */
434 lb += '0';
435 if (lb>'9')
436 lb += 7;
437
438 out[outIdx++] = hb;
439 out[outIdx++] = lb;
440 }
441
442 /* force 0 at this end */
443 out[outIdx++] = 0;
444
445 *outLen = outIdx;
446 return 0;
447}
448
449#endif /* (OPENSSL_EXTRA) || (HAVE_WEBSERVER) || (HAVE_FIPS) */
450
451#endif /* NO_CODING */
Note: See TracBrowser for help on using the repository browser.