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