source: azure_iot_hub/trunk/wolfssl-3.15.7/wolfcrypt/src/coding.c@ 388

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

Azure IoT Hub Device C SDK を使ったサンプルの追加

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