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