2 * This file is part of the OpenPTS project.
4 * The Initial Developer of the Original Code is International
5 * Business Machines Corporation. Portions created by IBM
6 * Corporation are Copyright (C) 2010 International Business
7 * Machines Corporation. All Rights Reserved.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the Common Public License as published by
11 * IBM Corporation; either version 1 of the License, or (at your option)
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * Common Public License for more details.
19 * You should have received a copy of the Common Public License
20 * along with this program; if not, a copy can be viewed at
21 * http://www.opensource.org/licenses/cpl1.0.php.
26 * \brief Base64 Encode/Decode
27 * @author Seiji Munetoh <munetoh@users.sourceforge.jp>
29 * cleanup 2012-01-05 SM
31 * http://en.wikipedia.org/wiki/Base64
33 * 2011-08-17 SM - encodebase64 & decodeBase64 - alloc output buffer
34 * 2011-08-21 SM - remove _removeCR() and malloc
35 * 2011-08-21 SM - check bad string in BASE64 msg.
48 * string(or binary data) => base64 string + 1
49 * Output is actual string size + 1 (for \0)
51 int _sizeofBase64Encode(int len) {
53 if (len < 0) return 0;
54 if (len == 0) return 1;
56 return (len + 2 - ((len + 2) % 3)) * 4 / 3 + 1;
59 int getDecodedBase64Size(unsigned char *in, int inLen) {
65 LOG(LOG_ERR, "null input");
73 outCount = inCount * 3;
76 if ( in[inCount+1] == '=' ) {
78 } else if ( in[inCount+2] == '=' ) {
80 } else if ( in[inCount+3] == '=' ) {
90 * calc original data size from base64 string size
92 * This is rough estimation.
93 * Output is actual string size (+1 or +2) + 1 (for \0)
96 int _sizeofBase64Decode(int len) {
98 if (len < 0) return 0;
99 if (len == 0) return 1;
101 return (len / 4 * 3) + 1;
105 * Encode BYTE[] to Base64 string
110 int _encodeBase64(char *out, unsigned char * in, int len) {
115 static unsigned char transTable[64] = {
117 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
119 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
121 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
123 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
124 /* 30h - 39h, 2Bh, 2Fh */
125 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
130 LOG(LOG_ERR, "null input\n");
138 LOG(LOG_ERR, "null input");
145 out[ptr2 ] = transTable[ in[ptr1 ] >>2];
146 out[ptr2+1] = transTable[ ((in[ptr1 ]&0x03) <<4 |
147 (in[ptr1+1]&0xF0) >> 4) ];
148 out[ptr2+2] = transTable[ ((in[ptr1+1]&0x0F) <<2 |
149 (in[ptr1+2]&0xC0) >> 6) ];
150 out[ptr2+3] = transTable[ (in[ptr1+2]&0x3F) ];
154 } else if ( len == 2 ) {
155 out[ptr2 ] = transTable[ in[ptr1 ] >>2];
156 out[ptr2+1] = transTable[ ((in[ptr1 ]&0x03) <<4 |
157 (in[ptr1+1]&0xF0) >> 4) ];
158 out[ptr2+2] = transTable[ (in[ptr1+1]&0x0F) <<2 ];
162 } else if ( len == 1 ) {
163 out[ptr2 ] = transTable[ in[ptr1 ] >>2];
164 out[ptr2+1] = transTable[ (in[ptr1 ]&0x03) <<4 ];
174 /* add \0 at the end of buffer */
180 * Encode BYTE[] to Base64 string
182 * @param *in buffer of input data
183 * @param inlen length
184 * @raram *outlen size of output
185 * @return *out Base64 string, malloc new buffer
187 char *encodeBase64(unsigned char * in, int inlen, int *outlen) {
193 LOG(LOG_ERR, "null input\n");
197 *outlen = _sizeofBase64Encode(inlen);
198 out = (char *) xmalloc_assert(*outlen);
200 LOG(LOG_ERR, "no memory");
204 memset(out, 0, *outlen);
206 len2 = _encodeBase64(out, in, inlen);
207 if (len2 > *outlen) {
208 LOG(LOG_ERR, "fatal error");
218 * trans (do not check the bad input)
220 unsigned char _b64trans(unsigned char in) {
221 if (in == '+') return 62;
222 if (in == '/') return 63;
223 if (in >= 'a') return (in-'a' + 26);
224 if (in >= 'A') return (in-'A');
225 if (in >= '0') return (in-'0' + 52);
230 * string length without space at the end
232 * 2011-11-30 Munetoh - fixed to skip the char in the middle of string
234 int _strippedlength(char * in, int len) {
240 LOG(LOG_ERR, "null input\n");
251 } else if (in[i] == ' ') {
264 * Decode Base64 string to BYTE[]
266 * caller must provide the buffer
268 * return size of BYTE[] array
270 int _decodeBase64(unsigned char *out, char * in, int len) {
281 LOG(LOG_ERR, "decodeBase64core - out is NULL\n");
286 LOG(LOG_ERR, "decodeBase64core - in is NULL\n");
289 /* in[0] => out[0]=\0 */
295 len2 = _strippedlength(in, len);
300 /* check remain buffer size >= 4 */
302 LOG(LOG_ERR, "bad base64 data size");
305 /* remove CR and Space and check bad string */
308 for (i = ptr1; j < 4 ; i++) {
309 if (in2[i] == '\n') {
312 } else if (in2[i] == ' ') {
316 if ((in2[i] == 0x2B) ||
319 ((0x30 <= in2[i]) && (in2[i] <= 0x39)) ||
320 ((0x41 <= in2[i]) && (in2[i] <= 0x5A)) ||
321 ((0x61 <= in2[i]) && (in2[i] <= 0x7A))) {
326 /* BAD BASE64 String */
327 LOG(LOG_ERR, "bad base64 data string, 0x%0x", in2[i]);
332 /* BASE64 -> Plain */
334 out[ptr2 ] = (_b64trans(inbuf[0]) << 2) |
335 (_b64trans(inbuf[1]) >> 4);
336 out[ptr2+1] = ((_b64trans(inbuf[1])&0x0F) << 4) |
337 (_b64trans(inbuf[2]) >> 2);
338 out[ptr2+2] = ((_b64trans(inbuf[2])&0x03) << 6) |
340 len2 -= 4; // skip chars has been removed in len2
343 } else if ( inbuf[1] == '=' ) {
344 out[ptr2 ] = _b64trans(inbuf[0]) << 2;
347 } else if ( inbuf[2] == '=' ) {
348 out[ptr2 ] = (_b64trans(inbuf[0]) << 2) |
349 (_b64trans(inbuf[1]) >> 4);
352 } else if ( inbuf[3] == '=' ) {
353 out[ptr2 ] = (_b64trans(inbuf[0]) << 2) |
354 (_b64trans(inbuf[1]) >> 4);
355 out[ptr2+1] = ((_b64trans(inbuf[1])&0x0F) << 4) |
356 (_b64trans(inbuf[2]) >> 2);
360 out[ptr2 ] = (_b64trans(inbuf[0]) << 2) |
361 (_b64trans(inbuf[1]) >> 4);
362 out[ptr2+1] = ((_b64trans(inbuf[1])&0x0F) << 4) |
363 (_b64trans(inbuf[2]) >> 2);
364 out[ptr2+2] = ((_b64trans(inbuf[2])&0x03) << 6) |
371 /* Anyway, add \0 at the end of buffer */
382 * Decode Base64(with CRLF) string to BYTE[]
384 * @param *in buffer of base64 string
385 * @param inlen length
386 * @raram *outlen size of BYTE[] array from base64 string, malloced size is bigger then this
387 * @return *out malloc new buffer
389 unsigned char *decodeBase64(char * in, int inlen, int *outlen) {
396 LOG(LOG_ERR, "null input\n");
400 len1 = _sizeofBase64Decode(inlen);
401 out = (unsigned char *) xmalloc_assert(len1);
403 LOG(LOG_ERR, "no memory");
407 memset(out, 0, len1);
409 len2 = _decodeBase64(out, in, inlen);
411 LOG(LOG_ERR, "fatal error");
417 /* return actial data size created from base64 */