source: asp3_tinet_ecnl_rx/trunk/wolfssl-3.12.2/wolfcrypt/src/coding.c@ 337

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

ASP3版ECNLを追加

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