3 * Copyright (C) 2006-2012 Sawtooth Consulting Ltd.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
26 #include <cyassl/ctaocrypt/coding.h>
27 #include <cyassl/ctaocrypt/error.h>
28 #include <cyassl/ctaocrypt/logging.h>
32 BAD = 0xFF, /* invalid encoding */
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
52 int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
56 word32 plainSz = inLen - ((inLen + (PEM_LINE_SZ - 1)) / PEM_LINE_SZ );
57 const byte maxIdx = (byte)sizeof(base64Decode) + 0x2B - 1;
59 plainSz = (plainSz * 3 + 3) / 4;
60 if (plainSz > *outLen) return BAD_FUNC_ARG;
72 if (e1 == 0) /* end file 0's */
79 if (e1 < 0x2B || e2 < 0x2B || e3 < 0x2B || e4 < 0x2B) {
80 CYASSL_MSG("Bad Base64 Decode data, too small");
84 if (e1 > maxIdx || e2 > maxIdx || e3 > maxIdx || e4 > maxIdx) {
85 CYASSL_MSG("Bad Base64 Decode data, too big");
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];
94 b1 = (e1 << 2) | (e2 >> 4);
95 b2 = ((e2 & 0xF) << 4) | (e3 >> 2);
96 b3 = ((e3 & 0x3) << 6) | e4;
107 if (in[j] == ' ' || in[j] == '\r' || in[j] == '\n') {
108 byte endLine = in[j++];
110 while (endLine == ' ') { /* allow trailing whitespace */
114 if (endLine == '\r') {
118 if (endLine != '\n') {
119 CYASSL_MSG("Bad end of line in Base64 Decode");
130 #if defined(OPENSSL_EXTRA) || defined (SESSION_CERTS) || defined(CYASSL_KEY_GEN) || defined(CYASSL_CERT_GEN) || defined(HAVE_WEBSERVER)
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',
144 /* porting assistance from yaSSL by Raphael HUCK */
145 int Base64_Encode(const byte* in, word32 inLen, byte* out, word32* outLen)
149 n = 0; /* new line counter */
151 word32 outSz = (inLen + 3 - 1) / 3 * 4;
152 outSz += (outSz + PEM_LINE_SZ - 1) / PEM_LINE_SZ; /* new lines */
154 if (outSz > *outLen) return BAD_FUNC_ARG;
163 byte e2 = ((b1 & 0x3) << 4) | (b2 >> 4);
164 byte e3 = ((b2 & 0xF) << 2) | (b3 >> 6);
168 out[i++] = base64Encode[e1];
169 out[i++] = base64Encode[e2];
170 out[i++] = base64Encode[e3];
171 out[i++] = base64Encode[e4];
175 if ((++n % (PEM_LINE_SZ / 4)) == 0 && inLen)
181 int twoBytes = (inLen == 2);
184 byte b2 = (twoBytes) ? in[j++] : 0;
187 byte e2 = ((b1 & 0x3) << 4) | (b2 >> 4);
188 byte e3 = (b2 & 0xF) << 2;
190 out[i++] = base64Encode[e1];
191 out[i++] = base64Encode[e2];
192 out[i++] = (twoBytes) ? base64Encode[e3] : PAD;
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 */
211 int Base16_Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
216 if (inLen == 1 && *outLen && in) {
217 byte b = in[inIdx++] - 0x30; /* 0 starts at 0x30 */
220 if (b >= sizeof(hexDecode)/sizeof(hexDecode[0]))
237 if (*outLen < (inLen / 2))
241 byte b = in[inIdx++] - 0x30; /* 0 starts at 0x30 */
242 byte b2 = in[inIdx++] - 0x30;
245 if (b >= sizeof(hexDecode)/sizeof(hexDecode[0]))
247 if (b2 >= sizeof(hexDecode)/sizeof(hexDecode[0]))
253 if (b == BAD || b2 == BAD)
256 out[outIdx++] = (b << 4) | b2;
265 #endif /* OPENSSL_EXTRA */