]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/CyaSSL/ctaocrypt/src/coding.c
Prepare for V7.2.0 release.
[freertos] / FreeRTOS-Plus / CyaSSL / ctaocrypt / src / coding.c
1 /* coding.c
2  *
3  * Copyright (C) 2006-2012 Sawtooth Consulting Ltd.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20  */
21
22 #ifdef HAVE_CONFIG_H
23     #include <config.h>
24 #endif
25
26 #include <cyassl/ctaocrypt/coding.h>
27 #include <cyassl/ctaocrypt/error.h>
28 #include <cyassl/ctaocrypt/logging.h>
29
30
31 enum {
32     BAD         = 0xFF,  /* invalid encoding */
33     PAD         = '=',
34     PEM_LINE_SZ = 64
35 };
36
37
38 static
39 const byte base64Decode[] = { 62, BAD, BAD, BAD, 63,   /* + starts at 0x2B */
40                               52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
41                               BAD, BAD, BAD, BAD, BAD, BAD, BAD,
42                               0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
43                               10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
44                               20, 21, 22, 23, 24, 25,
45                               BAD, BAD, BAD, BAD, BAD, BAD,
46                               26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
47                               36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
48                               46, 47, 48, 49, 50, 51
49                             };
50
51
52 int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
53 {
54     word32 i = 0;
55     word32 j = 0;
56     word32 plainSz = inLen - ((inLen + (PEM_LINE_SZ - 1)) / PEM_LINE_SZ );
57     const byte maxIdx = (byte)sizeof(base64Decode) + 0x2B - 1;
58
59     plainSz = (plainSz * 3 + 3) / 4;
60     if (plainSz > *outLen) return BAD_FUNC_ARG;
61
62     while (inLen > 3) {
63         byte b1, b2, b3;
64         byte e1 = in[j++];
65         byte e2 = in[j++];
66         byte e3 = in[j++];
67         byte e4 = in[j++];
68
69         int pad3 = 0;
70         int pad4 = 0;
71
72         if (e1 == 0)            /* end file 0's */
73             break;
74         if (e3 == PAD)
75             pad3 = 1;
76         if (e4 == PAD)
77             pad4 = 1;
78
79         if (e1 < 0x2B || e2 < 0x2B || e3 < 0x2B || e4 < 0x2B) {
80             CYASSL_MSG("Bad Base64 Decode data, too small");
81             return ASN_INPUT_E;
82         }
83
84         if (e1 > maxIdx || e2 > maxIdx || e3 > maxIdx || e4 > maxIdx) {
85             CYASSL_MSG("Bad Base64 Decode data, too big");
86             return ASN_INPUT_E;
87         }
88
89         e1 = base64Decode[e1 - 0x2B];
90         e2 = base64Decode[e2 - 0x2B];
91         e3 = (e3 == PAD) ? 0 : base64Decode[e3 - 0x2B];
92         e4 = (e4 == PAD) ? 0 : base64Decode[e4 - 0x2B];
93
94         b1 = (e1 << 2) | (e2 >> 4);
95         b2 = ((e2 & 0xF) << 4) | (e3 >> 2);
96         b3 = ((e3 & 0x3) << 6) | e4;
97
98         out[i++] = b1;
99         if (!pad3)
100             out[i++] = b2;
101         if (!pad4)
102             out[i++] = b3;
103         else
104             break;
105         
106         inLen -= 4;
107         if (in[j] == ' ' || in[j] == '\r' || in[j] == '\n') {
108             byte endLine = in[j++];
109             inLen--;
110             while (endLine == ' ') {   /* allow trailing whitespace */
111                 endLine = in[j++];
112                 inLen--;
113             }
114             if (endLine == '\r') {
115                 endLine = in[j++];
116                 inLen--;
117             }
118             if (endLine != '\n') {
119                 CYASSL_MSG("Bad end of line in Base64 Decode");
120                 return ASN_INPUT_E;
121             }
122         }
123     }
124     *outLen = i;
125
126     return 0;
127 }
128
129
130 #if defined(OPENSSL_EXTRA) || defined (SESSION_CERTS) || defined(CYASSL_KEY_GEN) || defined(CYASSL_CERT_GEN) || defined(HAVE_WEBSERVER)
131
132 static
133 const byte base64Encode[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
134                               'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
135                               'U', 'V', 'W', 'X', 'Y', 'Z',
136                               'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
137                               'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
138                               'u', 'v', 'w', 'x', 'y', 'z',
139                               '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
140                               '+', '/'
141                             };
142
143
144 /* porting assistance from yaSSL by Raphael HUCK */
145 int Base64_Encode(const byte* in, word32 inLen, byte* out, word32* outLen)
146 {
147     word32 i = 0,
148            j = 0,
149            n = 0;   /* new line counter */
150
151     word32 outSz = (inLen + 3 - 1) / 3 * 4;
152     outSz += (outSz + PEM_LINE_SZ - 1) / PEM_LINE_SZ;  /* new lines */
153
154     if (outSz > *outLen) return BAD_FUNC_ARG;
155     
156     while (inLen > 2) {
157         byte b1 = in[j++];
158         byte b2 = in[j++];
159         byte b3 = in[j++];
160
161         /* encoded idx */
162         byte e1 = b1 >> 2;
163         byte e2 = ((b1 & 0x3) << 4) | (b2 >> 4);
164         byte e3 = ((b2 & 0xF) << 2) | (b3 >> 6);
165         byte e4 = b3 & 0x3F;
166
167         /* store */
168         out[i++] = base64Encode[e1];
169         out[i++] = base64Encode[e2];
170         out[i++] = base64Encode[e3];
171         out[i++] = base64Encode[e4];
172
173         inLen -= 3;
174
175         if ((++n % (PEM_LINE_SZ / 4)) == 0 && inLen)
176             out[i++] = '\n';
177     }
178
179     /* last integral */
180     if (inLen) {
181         int twoBytes = (inLen == 2);
182
183         byte b1 = in[j++];
184         byte b2 = (twoBytes) ? in[j++] : 0;
185
186         byte e1 = b1 >> 2;
187         byte e2 = ((b1 & 0x3) << 4) | (b2 >> 4);
188         byte e3 =  (b2 & 0xF) << 2;
189
190         out[i++] = base64Encode[e1];
191         out[i++] = base64Encode[e2];
192         out[i++] = (twoBytes) ? base64Encode[e3] : PAD;
193         out[i++] = PAD;
194     } 
195
196     out[i++] = '\n';
197     if (i != outSz)
198         return ASN_INPUT_E; 
199     *outLen = outSz;
200
201     return 0; 
202 }
203
204
205 static
206 const byte hexDecode[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
207                            BAD, BAD, BAD, BAD, BAD, BAD, BAD,
208                            10, 11, 12, 13, 14, 15 
209                          };  /* A starts at 0x41 not 0x3A */
210
211 int Base16_Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
212 {
213     word32 inIdx  = 0;
214     word32 outIdx = 0;
215
216     if (inLen == 1 && *outLen && in) {
217         byte b = in[inIdx++] - 0x30;  /* 0 starts at 0x30 */
218
219         /* sanity check */
220         if (b >=  sizeof(hexDecode)/sizeof(hexDecode[0]))
221             return ASN_INPUT_E;
222
223         b  = hexDecode[b];
224
225         if (b == BAD)
226             return ASN_INPUT_E;
227         
228         out[outIdx++] = b;
229
230         *outLen = outIdx;
231         return 0;
232     }
233
234     if (inLen % 2)
235         return BAD_FUNC_ARG;
236
237     if (*outLen < (inLen / 2))
238         return BAD_FUNC_ARG;
239
240     while (inLen) {
241         byte b  = in[inIdx++] - 0x30;  /* 0 starts at 0x30 */
242         byte b2 = in[inIdx++] - 0x30;
243
244         /* sanity checks */
245         if (b >=  sizeof(hexDecode)/sizeof(hexDecode[0]))
246             return ASN_INPUT_E;
247         if (b2 >= sizeof(hexDecode)/sizeof(hexDecode[0]))
248             return ASN_INPUT_E;
249
250         b  = hexDecode[b];
251         b2 = hexDecode[b2];
252
253         if (b == BAD || b2 == BAD)
254             return ASN_INPUT_E;
255         
256         out[outIdx++] = (b << 4) | b2;
257         inLen -= 2;
258     }
259
260     *outLen = outIdx;
261     return 0;
262 }
263
264
265 #endif  /* OPENSSL_EXTRA */