3 * Copyright (C) 2006-2014 wolfSSL Inc.
5 * This file is part of CyaSSL.
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.
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.
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
26 #include <cyassl/ctaocrypt/settings.h>
30 #include <cyassl/ctaocrypt/coding.h>
31 #include <cyassl/ctaocrypt/error-crypt.h>
32 #include <cyassl/ctaocrypt/logging.h>
36 BAD = 0xFF, /* invalid encoding */
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
56 int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
60 word32 plainSz = inLen - ((inLen + (PEM_LINE_SZ - 1)) / PEM_LINE_SZ );
61 const byte maxIdx = (byte)sizeof(base64Decode) + 0x2B - 1;
63 plainSz = (plainSz * 3 + 3) / 4;
64 if (plainSz > *outLen) return BAD_FUNC_ARG;
76 if (e1 == 0) /* end file 0's */
83 if (e1 < 0x2B || e2 < 0x2B || e3 < 0x2B || e4 < 0x2B) {
84 CYASSL_MSG("Bad Base64 Decode data, too small");
88 if (e1 > maxIdx || e2 > maxIdx || e3 > maxIdx || e4 > maxIdx) {
89 CYASSL_MSG("Bad Base64 Decode data, too big");
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];
98 b1 = (byte)((e1 << 2) | (e2 >> 4));
99 b2 = (byte)(((e2 & 0xF) << 4) | (e3 >> 2));
100 b3 = (byte)(((e3 & 0x3) << 6) | e4);
111 if (inLen && (in[j] == ' ' || in[j] == '\r' || in[j] == '\n')) {
112 byte endLine = in[j++];
114 while (inLen && endLine == ' ') { /* allow trailing whitespace */
118 if (endLine == '\r') {
124 if (endLine != '\n') {
125 CYASSL_MSG("Bad end of line in Base64 Decode");
136 #if defined(OPENSSL_EXTRA) || defined (SESSION_CERTS) || defined(CYASSL_KEY_GEN) || defined(CYASSL_CERT_GEN) || defined(HAVE_WEBSERVER)
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',
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,
167 basic = base64Encode[e];
169 /* check whether to escape */
171 switch ((char)basic) {
194 if ( (idx+needed) > max) {
195 CYASSL_MSG("Escape buffer max too small");
204 out[idx++] = '%'; /* start escape */
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)
233 n = 0; /* new line counter */
235 word32 outSz = (inLen + 3 - 1) / 3 * 4;
236 word32 addSz = (outSz + PEM_LINE_SZ - 1) / PEM_LINE_SZ; /* new lines */
239 addSz *= 3; /* instead of just \n, we're doing %0A triplet */
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;
254 byte e2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4));
255 byte e3 = (byte)(((b2 & 0xF) << 2) | (b3 >> 6));
259 ret = CEscape(escaped, e1, out, &i, *outLen, 0);
261 ret = CEscape(escaped, e2, out, &i, *outLen, 0);
263 ret = CEscape(escaped, e3, out, &i, *outLen, 0);
265 ret = CEscape(escaped, e4, out, &i, *outLen, 0);
270 if ((++n % (PEM_LINE_SZ / 4)) == 0 && inLen) {
271 ret = CEscape(escaped, '\n', out, &i, *outLen, 1);
277 if (inLen && ret == 0) {
278 int twoBytes = (inLen == 2);
281 byte b2 = (twoBytes) ? in[j++] : 0;
284 byte e2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4));
285 byte e3 = (byte)((b2 & 0xF) << 2);
287 ret = CEscape(escaped, e1, out, &i, *outLen, 0);
289 ret = CEscape(escaped, e2, out, &i, *outLen, 0);
293 ret = CEscape(escaped, e3, out, &i, *outLen, 0);
295 ret = CEscape(escaped, '=', out, &i, *outLen, 1);
297 /* fourth always pad */
299 ret = CEscape(escaped, '=', out, &i, *outLen, 1);
303 ret = CEscape(escaped, '\n', out, &i, *outLen, 1);
305 if (i != outSz && escaped == 0 && ret == 0)
313 /* Base64 Encode, PEM style, with \n line endings */
314 int Base64_Encode(const byte* in, word32 inLen, byte* out, word32* outLen)
316 return DoBase64_Encode(in, inLen, out, outLen, 0);
320 /* Base64 Encode, with %0A esacped line endings instead of \n */
321 int Base64_EncodeEsc(const byte* in, word32 inLen, byte* out, word32* outLen)
323 return DoBase64_Encode(in, inLen, out, outLen, 1);
327 #endif /* defined(OPENSSL_EXTRA) || defined (SESSION_CERTS) || defined(CYASSL_KEY_GEN) || defined(CYASSL_CERT_GEN) || defined(HAVE_WEBSERVER) */
330 #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(HAVE_FIPS)
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 */
343 int Base16_Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
348 if (inLen == 1 && *outLen && in) {
349 byte b = in[inIdx++] - 0x30; /* 0 starts at 0x30 */
352 if (b >= sizeof(hexDecode)/sizeof(hexDecode[0]))
369 if (*outLen < (inLen / 2))
373 byte b = in[inIdx++] - 0x30; /* 0 starts at 0x30 */
374 byte b2 = in[inIdx++] - 0x30;
377 if (b >= sizeof(hexDecode)/sizeof(hexDecode[0]))
379 if (b2 >= sizeof(hexDecode)/sizeof(hexDecode[0]))
385 if (b == BAD || b2 == BAD)
388 out[outIdx++] = (byte)((b << 4) | b2);
397 #endif /* (OPENSSL_EXTRA) || (HAVE_WEBSERVER) || (HAVE_FIPS) */
399 #endif /* NO_CODING */