1 /***************************************************************************
2 begin : Thu May 06 2004
3 copyright : (C) 2004 by Martin Preuss
4 email : martin@libchipcard.de
5
6 ***************************************************************************
7 * *
8 * This library is free software; you can redistribute it and/or *
9 * modify it under the terms of the GNU Lesser General Public *
10 * License as published by the Free Software Foundation; either *
11 * version 2.1 of the License, or (at your option) any later version. *
12 * *
13 * This library is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
16 * Lesser General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU Lesser General Public *
19 * License along with this library; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21 * MA 02111-1307 USA *
22 * *
23 ***************************************************************************/
24
25
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
29
30 #define DISABLE_DEBUGLOG
31
32
33 #include "base64.h"
34 #include <gwenhywfar/misc.h>
35 #include <gwenhywfar/debug.h>
36 #include <gwenhywfar/text.h>
37 #include <string.h>
38
39
40 static const char GWEN_Base64_Alphabet[]=
41 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
42
43
GWEN_Base64_Encode(const unsigned char * src,unsigned int size,GWEN_BUFFER * dst,unsigned int maxLineLength)44 int GWEN_Base64_Encode(const unsigned char *src, unsigned int size,
45 GWEN_BUFFER *dst,
46 unsigned int maxLineLength)
47 {
48 unsigned int by3;
49 unsigned int i;
50 unsigned int l;
51 uint32_t triplet;
52 unsigned char c1, c2, c3, c4;
53
54 if (maxLineLength) {
55 if (maxLineLength<4) {
56 DBG_ERROR(GWEN_LOGDOMAIN, "I need at least 4 bytes per line");
57 return -1;
58 }
59 }
60
61 by3=size/3;
62 /* first encode full triplets */
63 l=0;
64 for (i=0; i<by3; i++) {
65 triplet=(src[0]<<16)+(src[1]<<8)+src[2];
66 src+=3;
67 c4=triplet & 0x3f;
68 triplet>>=6;
69 c3=triplet & 0x3f;
70 triplet>>=6;
71 c2=triplet & 0x3f;
72 triplet>>=6;
73 c1=triplet & 0x3f;
74 if (maxLineLength) {
75 if (l+4>maxLineLength) {
76 GWEN_Buffer_AppendByte(dst, '\n');
77 l=0;
78 }
79 l+=4;
80 }
81 GWEN_Buffer_AppendByte(dst, GWEN_Base64_Alphabet[c1]);
82 GWEN_Buffer_AppendByte(dst, GWEN_Base64_Alphabet[c2]);
83 GWEN_Buffer_AppendByte(dst, GWEN_Base64_Alphabet[c3]);
84 GWEN_Buffer_AppendByte(dst, GWEN_Base64_Alphabet[c4]);
85 }
86 if (maxLineLength) {
87 if (l+4>=maxLineLength) {
88 GWEN_Buffer_AppendByte(dst, '\n');
89 l=0;
90 }
91 }
92
93 /* then encode remainder */
94 switch (size % 3) {
95 case 0:
96 /* no remainder */
97 break;
98
99 case 1:
100 /* 1 remainder, leads to two trailing "=" */
101 triplet=(src[0]<<4);
102 c2=triplet & 0x3f;
103 triplet>>=6;
104 c1=triplet & 0x3f;
105 GWEN_Buffer_AppendByte(dst, GWEN_Base64_Alphabet[c1]);
106 GWEN_Buffer_AppendByte(dst, GWEN_Base64_Alphabet[c2]);
107 GWEN_Buffer_AppendString(dst, "==");
108 break;
109
110 case 2:
111 /* 2 remainders, leads to one trailing "=" */
112 triplet=(src[0]<<10)+(src[1]<<2);
113 c3=triplet & 0x3f;
114 triplet>>=6;
115 c2=triplet & 0x3f;
116 triplet>>=6;
117 c1=triplet & 0x3f;
118 GWEN_Buffer_AppendByte(dst, GWEN_Base64_Alphabet[c1]);
119 GWEN_Buffer_AppendByte(dst, GWEN_Base64_Alphabet[c2]);
120 GWEN_Buffer_AppendByte(dst, GWEN_Base64_Alphabet[c3]);
121 GWEN_Buffer_AppendByte(dst, '=');
122 break;
123
124 default:
125 break;
126 }
127
128 return 0;
129 }
130
131
132
GWEN_Base64_Decode(const unsigned char * src,unsigned int size,GWEN_BUFFER * dst)133 int GWEN_Base64_Decode(const unsigned char *src, unsigned int size,
134 GWEN_BUFFER *dst)
135 {
136 unsigned int i;
137 const char *p = "0";
138 uint32_t v;
139 int lastWasEq;
140 int sizeGiven;
141
142 /* first decode full triplets */
143 sizeGiven=(size!=0);
144 lastWasEq=0;
145 for (;;) {
146 if ((sizeGiven && size==0) || lastWasEq || !*src)
147 break;
148 v=0;
149
150 while (*src && ((p=strchr(GWEN_Base64_Alphabet, *src))==0))
151 src++;
152 if (!*src)
153 break;
154 for (i=0; i<4; i++) {
155 /* get next valid character */
156 if (lastWasEq) {
157 while (*src && *src!='=')
158 src++;
159 }
160 else {
161 while (*src && ((p=strchr(GWEN_Base64_Alphabet, *src))==0))
162 src++;
163 }
164 if (!*src) {
165 if (i==0 && !sizeGiven) {
166 return 0;
167 }
168 else {
169 DBG_ERROR(GWEN_LOGDOMAIN, "Premature end reached (%d)", i);
170 return -1;
171 }
172 }
173 if (*src=='=')
174 lastWasEq++;
175 v<<=6;
176 v+=(p-GWEN_Base64_Alphabet) & 0x3f;
177 src++;
178 } /* for */
179
180 /* now we have a triplet */
181 if (sizeGiven) {
182 switch (size) {
183 case 1:
184 GWEN_Buffer_AppendByte(dst, (v>>16) & 0xff);
185 size--;
186 break;
187 case 2:
188 GWEN_Buffer_AppendByte(dst, (v>>16) & 0xff);
189 GWEN_Buffer_AppendByte(dst, (v>>8) & 0xff);
190 size-=2;
191 break;
192 default:
193 GWEN_Buffer_AppendByte(dst, (v>>16) & 0xff);
194 GWEN_Buffer_AppendByte(dst, (v>>8) & 0xff);
195 GWEN_Buffer_AppendByte(dst, v & 0xff);
196 size-=3;
197 break;
198 } /* switch */
199 }
200 else {
201 int bytes;
202
203 bytes=(24-(lastWasEq*6))/8;
204 if (bytes) {
205 GWEN_Buffer_AppendByte(dst, (v>>16) & 0xff);
206 if (bytes>1) {
207 GWEN_Buffer_AppendByte(dst, (v>>8) & 0xff);
208 if (bytes>2)
209 GWEN_Buffer_AppendByte(dst, v & 0xff);
210 }
211 }
212 }
213 } /* for full quadruplets */
214
215 return 0;
216 }
217
218
219
220
221
222