]> www.average.org Git - pam_pcsc_cr.git/blob - base64.c
configure.ac: remove sanitizer by default
[pam_pcsc_cr.git] / base64.c
1 /*
2 cencoder.c - c source to a base64 encoding algorithm implementation
3
4 This is part of the libb64 project, and has been placed in the public domain.
5 For details, see http://sourceforge.net/projects/libb64
6 */
7
8 /*
9   Modified by Eugene Crosser to fit pam_pcsc_cr project, 2013
10 */
11
12 #include <string.h>
13 #include <base64.h>
14 /*
15 cencode.h - c header for a base64 encoding algorithm
16
17 This is part of the libb64 project, and has been placed in the public domain.
18 For details, see http://sourceforge.net/projects/libb64
19 */
20
21 /*
22   Modified by Eugene Crosser to fit pam_pcsc_cr project, 2013
23 */
24
25 typedef enum
26 {
27         step_A, step_B, step_C
28 } base64_encodestep;
29
30 typedef struct
31 {
32         base64_encodestep step;
33         char result;
34         int stepcount;
35 } base64_encodestate;
36
37 /*
38 cdecode.h - c header for a base64 decoding algorithm
39
40 This is part of the libb64 project, and has been placed in the public domain.
41 For details, see http://sourceforge.net/projects/libb64
42 */
43
44 typedef enum
45 {
46         step_a, step_b, step_c, step_d
47 } base64_decodestep;
48
49 typedef struct
50 {
51         base64_decodestep step;
52         char plainchar;
53 } base64_decodestate;
54
55 static void base64_init_encodestate(base64_encodestate* state_in)
56 {
57         state_in->step = step_A;
58         state_in->result = 0;
59         state_in->stepcount = 0;
60 }
61
62 static char base64_encode_value(char value_in)
63 {
64         static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
65         if (value_in > 63) return '=';
66         return encoding[(int)value_in];
67 }
68
69 static int base64_encode_block(const unsigned char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in)
70 {
71         const unsigned char* plainchar = plaintext_in;
72         const unsigned char* const plaintextend = plaintext_in + length_in;
73         char* codechar = code_out;
74         char result;
75         char fragment;
76         
77         result = state_in->result;
78         
79         switch (state_in->step)
80         {
81                 while (1)
82                 {
83         case step_A:
84                         if (plainchar == plaintextend)
85                         {
86                                 state_in->result = result;
87                                 state_in->step = step_A;
88                                 return codechar - code_out;
89                         }
90                         fragment = *plainchar++;
91                         result = (fragment & 0x0fc) >> 2;
92                         *codechar++ = base64_encode_value(result);
93                         result = (fragment & 0x003) << 4;
94                         /* fallthrough */
95         case step_B:
96                         if (plainchar == plaintextend)
97                         {
98                                 state_in->result = result;
99                                 state_in->step = step_B;
100                                 return codechar - code_out;
101                         }
102                         fragment = *plainchar++;
103                         result |= (fragment & 0x0f0) >> 4;
104                         *codechar++ = base64_encode_value(result);
105                         result = (fragment & 0x00f) << 2;
106                         /* fallthrough */
107         case step_C:
108                         if (plainchar == plaintextend)
109                         {
110                                 state_in->result = result;
111                                 state_in->step = step_C;
112                                 return codechar - code_out;
113                         }
114                         fragment = *plainchar++;
115                         result |= (fragment & 0x0c0) >> 6;
116                         *codechar++ = base64_encode_value(result);
117                         result  = (fragment & 0x03f) >> 0;
118                         *codechar++ = base64_encode_value(result);
119                         
120                         ++(state_in->stepcount);
121                 }
122         }
123         /* control should not reach here */
124         return codechar - code_out;
125 }
126
127 static int base64_encode_blockend(char* code_out, base64_encodestate* state_in)
128 {
129         char* codechar = code_out;
130         
131         switch (state_in->step)
132         {
133         case step_B:
134                 *codechar++ = base64_encode_value(state_in->result);
135                 *codechar++ = '=';
136                 *codechar++ = '=';
137                 break;
138         case step_C:
139                 *codechar++ = base64_encode_value(state_in->result);
140                 *codechar++ = '=';
141                 break;
142         case step_A:
143                 break;
144         }
145         
146         return codechar - code_out;
147 }
148
149 /*
150 cdecoder.c - c source to a base64 decoding algorithm implementation
151
152 This is part of the libb64 project, and has been placed in the public domain.
153 For details, see http://sourceforge.net/projects/libb64
154 */
155
156 static int base64_decode_value(char value_in)
157 {
158         static const char decoding[] = {62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51};
159         static const char decoding_size = sizeof(decoding);
160         value_in -= 43;
161         if (value_in < 0 || value_in >= decoding_size) return -1;
162         return decoding[(int)value_in];
163 }
164
165 static void base64_init_decodestate(base64_decodestate* state_in)
166 {
167         state_in->step = step_a;
168         state_in->plainchar = 0;
169 }
170
171 static int base64_decode_block(const char* code_in, const int length_in, unsigned char* plaintext_out, base64_decodestate* state_in)
172 {
173         const char* codechar = code_in;
174         unsigned char* plainchar = plaintext_out;
175         char fragment;
176         
177         *plainchar = state_in->plainchar;
178         
179         switch (state_in->step)
180         {
181                 while (1)
182                 {
183         case step_a:
184                         do {
185                                 if (codechar == code_in+length_in)
186                                 {
187                                         state_in->step = step_a;
188                                         state_in->plainchar = *plainchar;
189                                         return plainchar - plaintext_out;
190                                 }
191                                 fragment = (char)base64_decode_value(*codechar++);
192                         } while (fragment < 0);
193                         *plainchar    = (fragment & 0x03f) << 2;
194                         /* fallthrough */
195         case step_b:
196                         do {
197                                 if (codechar == code_in+length_in)
198                                 {
199                                         state_in->step = step_b;
200                                         state_in->plainchar = *plainchar;
201                                         return plainchar - plaintext_out;
202                                 }
203                                 fragment = (char)base64_decode_value(*codechar++);
204                         } while (fragment < 0);
205                         *plainchar++ |= (fragment & 0x030) >> 4;
206                         *plainchar    = (fragment & 0x00f) << 4;
207                         /* fallthrough */
208         case step_c:
209                         do {
210                                 if (codechar == code_in+length_in)
211                                 {
212                                         state_in->step = step_c;
213                                         state_in->plainchar = *plainchar;
214                                         return plainchar - plaintext_out;
215                                 }
216                                 fragment = (char)base64_decode_value(*codechar++);
217                         } while (fragment < 0);
218                         *plainchar++ |= (fragment & 0x03c) >> 2;
219                         *plainchar    = (fragment & 0x003) << 6;
220                         /* fallthrough */
221         case step_d:
222                         do {
223                                 if (codechar == code_in+length_in)
224                                 {
225                                         state_in->step = step_d;
226                                         state_in->plainchar = *plainchar;
227                                         return plainchar - plaintext_out;
228                                 }
229                                 fragment = (char)base64_decode_value(*codechar++);
230                         } while (fragment < 0);
231                         *plainchar++   |= (fragment & 0x03f);
232                 }
233         }
234         /* control should not reach here */
235         return plainchar - plaintext_out;
236 }
237
238 int b64_encode(const unsigned char *src, const int ssize,
239                 char *const b64, int *const bsize)
240 {
241         base64_encodestate s;
242         int cnt1, cnt2;
243         char *c = b64;
244
245         if (*bsize < ((ssize-1)/3+1)*4+1) return 1;
246         base64_init_encodestate(&s);
247         cnt1 = base64_encode_block(src, ssize, c, &s);
248         c += cnt1;
249         cnt2 = base64_encode_blockend(c, &s);
250         c += cnt2;
251         *c = 0;
252         *bsize = cnt1 + cnt2;
253         return 0;
254 }
255
256 int b64_decode(const char *b64, unsigned char *const dst, int *const dsize)
257 {
258         base64_decodestate s;
259         int cnt;
260         int bsize = strlen(b64);
261
262         if (*dsize < (bsize*3/4)) return 1;
263         base64_init_decodestate(&s);
264         cnt = base64_decode_block(b64, bsize, dst, &s);
265         *dsize = cnt;
266         return 0;
267 }