]> www.average.org Git - pam_pcsc_cr.git/blob - base64.c
3ef6bb2bd8539995441b34e678982fd9cc7aad1a
[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         case step_B:
95                         if (plainchar == plaintextend)
96                         {
97                                 state_in->result = result;
98                                 state_in->step = step_B;
99                                 return codechar - code_out;
100                         }
101                         fragment = *plainchar++;
102                         result |= (fragment & 0x0f0) >> 4;
103                         *codechar++ = base64_encode_value(result);
104                         result = (fragment & 0x00f) << 2;
105         case step_C:
106                         if (plainchar == plaintextend)
107                         {
108                                 state_in->result = result;
109                                 state_in->step = step_C;
110                                 return codechar - code_out;
111                         }
112                         fragment = *plainchar++;
113                         result |= (fragment & 0x0c0) >> 6;
114                         *codechar++ = base64_encode_value(result);
115                         result  = (fragment & 0x03f) >> 0;
116                         *codechar++ = base64_encode_value(result);
117                         
118                         ++(state_in->stepcount);
119                 }
120         }
121         /* control should not reach here */
122         return codechar - code_out;
123 }
124
125 static int base64_encode_blockend(char* code_out, base64_encodestate* state_in)
126 {
127         char* codechar = code_out;
128         
129         switch (state_in->step)
130         {
131         case step_B:
132                 *codechar++ = base64_encode_value(state_in->result);
133                 *codechar++ = '=';
134                 *codechar++ = '=';
135                 break;
136         case step_C:
137                 *codechar++ = base64_encode_value(state_in->result);
138                 *codechar++ = '=';
139                 break;
140         case step_A:
141                 break;
142         }
143         
144         return codechar - code_out;
145 }
146
147 /*
148 cdecoder.c - c source to a base64 decoding algorithm implementation
149
150 This is part of the libb64 project, and has been placed in the public domain.
151 For details, see http://sourceforge.net/projects/libb64
152 */
153
154 static int base64_decode_value(char value_in)
155 {
156         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};
157         static const char decoding_size = sizeof(decoding);
158         value_in -= 43;
159         if (value_in < 0 || value_in >= decoding_size) return -1;
160         return decoding[(int)value_in];
161 }
162
163 static void base64_init_decodestate(base64_decodestate* state_in)
164 {
165         state_in->step = step_a;
166         state_in->plainchar = 0;
167 }
168
169 static int base64_decode_block(const char* code_in, const int length_in, unsigned char* plaintext_out, base64_decodestate* state_in)
170 {
171         const char* codechar = code_in;
172         unsigned char* plainchar = plaintext_out;
173         char fragment;
174         
175         *plainchar = state_in->plainchar;
176         
177         switch (state_in->step)
178         {
179                 while (1)
180                 {
181         case step_a:
182                         do {
183                                 if (codechar == code_in+length_in)
184                                 {
185                                         state_in->step = step_a;
186                                         state_in->plainchar = *plainchar;
187                                         return plainchar - plaintext_out;
188                                 }
189                                 fragment = (char)base64_decode_value(*codechar++);
190                         } while (fragment < 0);
191                         *plainchar    = (fragment & 0x03f) << 2;
192         case step_b:
193                         do {
194                                 if (codechar == code_in+length_in)
195                                 {
196                                         state_in->step = step_b;
197                                         state_in->plainchar = *plainchar;
198                                         return plainchar - plaintext_out;
199                                 }
200                                 fragment = (char)base64_decode_value(*codechar++);
201                         } while (fragment < 0);
202                         *plainchar++ |= (fragment & 0x030) >> 4;
203                         *plainchar    = (fragment & 0x00f) << 4;
204         case step_c:
205                         do {
206                                 if (codechar == code_in+length_in)
207                                 {
208                                         state_in->step = step_c;
209                                         state_in->plainchar = *plainchar;
210                                         return plainchar - plaintext_out;
211                                 }
212                                 fragment = (char)base64_decode_value(*codechar++);
213                         } while (fragment < 0);
214                         *plainchar++ |= (fragment & 0x03c) >> 2;
215                         *plainchar    = (fragment & 0x003) << 6;
216         case step_d:
217                         do {
218                                 if (codechar == code_in+length_in)
219                                 {
220                                         state_in->step = step_d;
221                                         state_in->plainchar = *plainchar;
222                                         return plainchar - plaintext_out;
223                                 }
224                                 fragment = (char)base64_decode_value(*codechar++);
225                         } while (fragment < 0);
226                         *plainchar++   |= (fragment & 0x03f);
227                 }
228         }
229         /* control should not reach here */
230         return plainchar - plaintext_out;
231 }
232
233 int b64_encode(const unsigned char *src, const int ssize,
234                 char *const b64, int *const bsize)
235 {
236         base64_encodestate s;
237         int cnt1, cnt2;
238         char *c = b64;
239
240         if (*bsize < ((ssize-1)/3+1)*4+1) return 1;
241         base64_init_encodestate(&s);
242         cnt1 = base64_encode_block(src, ssize, c, &s);
243         c += cnt1;
244         cnt2 = base64_encode_blockend(c, &s);
245         c += cnt2;
246         *c = 0;
247         *bsize = cnt1 + cnt2;
248         return 0;
249 }
250
251 int b64_decode(const char *b64, unsigned char *const dst, int *const dsize)
252 {
253         base64_decodestate s;
254         int cnt;
255         int bsize = strlen(b64);
256
257         if (*dsize < (bsize*3/4)) return 1;
258         base64_init_decodestate(&s);
259         cnt = base64_decode_block(b64, bsize, dst, &s);
260         *dsize = cnt;
261         return 0;
262 }