]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/WolfSSL/ctaocrypt/src/coding.c
Rename the CyaSSL directory to WolfSSL
[freertos] / FreeRTOS-Plus / Source / WolfSSL / ctaocrypt / src / coding.c
1 /* coding.c
2  *
3  * Copyright (C) 2006-2014 wolfSSL Inc.
4  *
5  * This file is part of CyaSSL.
6  *
7  * CyaSSL 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  * CyaSSL 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 <cyassl/ctaocrypt/settings.h>
27
28 #ifndef NO_CODING
29
30 #include <cyassl/ctaocrypt/coding.h>
31 #include <cyassl/ctaocrypt/error-crypt.h>
32 #include <cyassl/ctaocrypt/logging.h>
33
34
35 enum {
36     BAD         = 0xFF,  /* invalid encoding */
37     PAD         = '=',
38     PEM_LINE_SZ = 64
39 };
40
41
42 static
43 const 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
56 int 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             CYASSL_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             CYASSL_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                 CYASSL_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(OPENSSL_EXTRA) || defined (SESSION_CERTS) || defined(CYASSL_KEY_GEN) || defined(CYASSL_CERT_GEN) || defined(HAVE_WEBSERVER)
137
138 static
139 const 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 */
152 static int CEscape(int escaped, byte e, byte* out, word32* i, word32 max,
153                   int raw)
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 */
170     if (escaped) {
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) {
195         CYASSL_MSG("Escape buffer max too small");
196         return BUFFER_E;
197     }
198
199     /* store it */
200     if (doEscape == 0) {
201         out[idx++] = basic;
202     }
203     else {
204         out[idx++] = '%';  /* start escape */
205
206         if (plus) {
207             out[idx++] = '2';
208             out[idx++] = 'B';
209         }
210         else if (equals) {
211             out[idx++] = '3';
212             out[idx++] = 'D';
213         }
214         else if (newline) {
215             out[idx++] = '0';
216             out[idx++] = 'A';
217         }
218
219     }
220     *i = idx;
221
222     return 0;
223 }
224
225
226 /* internal worker, handles both escaped and normal line endings */
227 static int DoBase64_Encode(const byte* in, word32 inLen, byte* out,
228                            word32* outLen, int escaped)
229 {
230     int    ret = 0;
231     word32 i = 0,
232            j = 0,
233            n = 0;   /* new line counter */
234
235     word32 outSz = (inLen + 3 - 1) / 3 * 4;
236     word32 addSz = (outSz + PEM_LINE_SZ - 1) / PEM_LINE_SZ;  /* new lines */
237
238     if (escaped)
239         addSz *= 3;   /* instead of just \n, we're doing %0A triplet */
240
241     outSz += addSz;
242
243     /* if escaped we can't predetermine size for one pass encoding, but
244      * make sure we have enough if no escapes are in input */
245     if (outSz > *outLen) return BAD_FUNC_ARG;
246     
247     while (inLen > 2) {
248         byte b1 = in[j++];
249         byte b2 = in[j++];
250         byte b3 = in[j++];
251
252         /* encoded idx */
253         byte e1 = b1 >> 2;
254         byte e2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4));
255         byte e3 = (byte)(((b2 & 0xF) << 2) | (b3 >> 6));
256         byte e4 = b3 & 0x3F;
257
258         /* store */
259         ret = CEscape(escaped, e1, out, &i, *outLen, 0);
260         if (ret != 0) break;
261         ret = CEscape(escaped, e2, out, &i, *outLen, 0);
262         if (ret != 0) break;
263         ret = CEscape(escaped, e3, out, &i, *outLen, 0);
264         if (ret != 0) break;
265         ret = CEscape(escaped, e4, out, &i, *outLen, 0);
266         if (ret != 0) break;
267
268         inLen -= 3;
269
270         if ((++n % (PEM_LINE_SZ / 4)) == 0 && inLen) {
271             ret = CEscape(escaped, '\n', out, &i, *outLen, 1);
272             if (ret != 0) break;
273         }
274     }
275
276     /* last integral */
277     if (inLen && ret == 0) {
278         int twoBytes = (inLen == 2);
279
280         byte b1 = in[j++];
281         byte b2 = (twoBytes) ? in[j++] : 0;
282
283         byte e1 = b1 >> 2;
284         byte e2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4));
285         byte e3 = (byte)((b2 & 0xF) << 2);
286
287         ret = CEscape(escaped, e1, out, &i, *outLen, 0);
288         if (ret == 0) 
289             ret = CEscape(escaped, e2, out, &i, *outLen, 0);
290         if (ret == 0) {
291             /* third */
292             if (twoBytes)
293                 ret = CEscape(escaped, e3, out, &i, *outLen, 0);
294             else 
295                 ret = CEscape(escaped, '=', out, &i, *outLen, 1);
296         }
297         /* fourth always pad */
298         if (ret == 0)
299             ret = CEscape(escaped, '=', out, &i, *outLen, 1);
300     } 
301
302     if (ret == 0) 
303         ret = CEscape(escaped, '\n', out, &i, *outLen, 1);
304
305     if (i != outSz && escaped == 0 && ret == 0)
306         return ASN_INPUT_E; 
307
308     *outLen = i;
309     return ret; 
310 }
311
312
313 /* Base64 Encode, PEM style, with \n line endings */
314 int Base64_Encode(const byte* in, word32 inLen, byte* out, word32* outLen)
315 {
316     return DoBase64_Encode(in, inLen, out, outLen, 0);
317 }
318
319
320 /* Base64 Encode, with %0A esacped line endings instead of \n */
321 int Base64_EncodeEsc(const byte* in, word32 inLen, byte* out, word32* outLen)
322 {
323     return DoBase64_Encode(in, inLen, out, outLen, 1);
324 }
325
326
327 #endif  /* defined(OPENSSL_EXTRA) || defined (SESSION_CERTS) || defined(CYASSL_KEY_GEN) || defined(CYASSL_CERT_GEN) || defined(HAVE_WEBSERVER) */
328
329
330 #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(HAVE_FIPS)
331
332 static
333 const byte hexDecode[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
334                            BAD, BAD, BAD, BAD, BAD, BAD, BAD,
335                            10, 11, 12, 13, 14, 15,  /* upper case A-F */
336                            BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
337                            BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
338                            BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
339                            BAD, BAD,  /* G - ` */
340                            10, 11, 12, 13, 14, 15   /* lower case a-f */
341                          };  /* A starts at 0x41 not 0x3A */
342
343 int Base16_Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
344 {
345     word32 inIdx  = 0;
346     word32 outIdx = 0;
347
348     if (inLen == 1 && *outLen && in) {
349         byte b = in[inIdx++] - 0x30;  /* 0 starts at 0x30 */
350
351         /* sanity check */
352         if (b >=  sizeof(hexDecode)/sizeof(hexDecode[0]))
353             return ASN_INPUT_E;
354
355         b  = hexDecode[b];
356
357         if (b == BAD)
358             return ASN_INPUT_E;
359         
360         out[outIdx++] = b;
361
362         *outLen = outIdx;
363         return 0;
364     }
365
366     if (inLen % 2)
367         return BAD_FUNC_ARG;
368
369     if (*outLen < (inLen / 2))
370         return BAD_FUNC_ARG;
371
372     while (inLen) {
373         byte b  = in[inIdx++] - 0x30;  /* 0 starts at 0x30 */
374         byte b2 = in[inIdx++] - 0x30;
375
376         /* sanity checks */
377         if (b >=  sizeof(hexDecode)/sizeof(hexDecode[0]))
378             return ASN_INPUT_E;
379         if (b2 >= sizeof(hexDecode)/sizeof(hexDecode[0]))
380             return ASN_INPUT_E;
381
382         b  = hexDecode[b];
383         b2 = hexDecode[b2];
384
385         if (b == BAD || b2 == BAD)
386             return ASN_INPUT_E;
387         
388         out[outIdx++] = (byte)((b << 4) | b2);
389         inLen -= 2;
390     }
391
392     *outLen = outIdx;
393     return 0;
394 }
395
396
397 #endif /* (OPENSSL_EXTRA) || (HAVE_WEBSERVER) || (HAVE_FIPS) */
398
399 #endif /* NO_CODING */