/src/nss/lib/util/nssb64d.c
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /* This Source Code Form is subject to the terms of the Mozilla Public  | 
2  |  |  * License, v. 2.0. If a copy of the MPL was not distributed with this  | 
3  |  |  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */  | 
4  |  |  | 
5  |  | /*  | 
6  |  |  * Base64 decoding (ascii to binary).  | 
7  |  |  */  | 
8  |  |  | 
9  |  | #include "nssb64.h"  | 
10  |  | #include "nspr.h"  | 
11  |  | #include "secitem.h"  | 
12  |  | #include "secerr.h"  | 
13  |  |  | 
14  |  | /*  | 
15  |  |  * XXX We want this basic support to go into NSPR (the PL part).  | 
16  |  |  * Until that can happen, the PL interface is going to be kept entirely  | 
17  |  |  * internal here -- all static functions and opaque data structures.  | 
18  |  |  * When someone can get it moved over into NSPR, that should be done:  | 
19  |  |  *    - giving everything names that are accepted by the NSPR module owners  | 
20  |  |  *  (though I tried to choose ones that would work without modification)  | 
21  |  |  *    - exporting the functions (remove static declarations and add  | 
22  |  |  *  to nssutil.def as necessary)  | 
23  |  |  *    - put prototypes into appropriate header file (probably replacing  | 
24  |  |  *  the entire current lib/libc/include/plbase64.h in NSPR)  | 
25  |  |  *  along with a typedef for the context structure (which should be  | 
26  |  |  *  kept opaque -- definition in the source file only, but typedef  | 
27  |  |  *  ala "typedef struct PLBase64FooStr PLBase64Foo;" in header file)  | 
28  |  |  *    - modify anything else as necessary to conform to NSPR required style  | 
29  |  |  *  (I looked but found no formatting guide to follow)  | 
30  |  |  *  | 
31  |  |  * You will want to move over everything from here down to the comment  | 
32  |  |  * which says "XXX End of base64 decoding code to be moved into NSPR",  | 
33  |  |  * into a new file in NSPR.  | 
34  |  |  */  | 
35  |  |  | 
36  |  | /*  | 
37  |  |  **************************************************************  | 
38  |  |  * XXX Beginning of base64 decoding code to be moved into NSPR.  | 
39  |  |  */  | 
40  |  |  | 
41  |  | /*  | 
42  |  |  * This typedef would belong in the NSPR header file (i.e. plbase64.h).  | 
43  |  |  */  | 
44  |  | typedef struct PLBase64DecoderStr PLBase64Decoder;  | 
45  |  |  | 
46  |  | /*  | 
47  |  |  * The following implementation of base64 decoding was based on code  | 
48  |  |  * found in libmime (specifically, in mimeenc.c).  It has been adapted to  | 
49  |  |  * use PR types and naming as well as to provide other necessary semantics  | 
50  |  |  * (like buffer-in/buffer-out in addition to "streaming" without undue  | 
51  |  |  * performance hit of extra copying if you made the buffer versions  | 
52  |  |  * use the output_fn).  It also incorporates some aspects of the current  | 
53  |  |  * NSPR base64 decoding code.  As such, you may find similarities to  | 
54  |  |  * both of those implementations.  I tried to use names that reflected  | 
55  |  |  * the original code when possible.  For this reason you may find some  | 
56  |  |  * inconsistencies -- libmime used lots of "in" and "out" whereas the  | 
57  |  |  * NSPR version uses "src" and "dest"; sometimes I changed one to the other  | 
58  |  |  * and sometimes I left them when I thought the subroutines were at least  | 
59  |  |  * self-consistent.  | 
60  |  |  */  | 
61  |  |  | 
62  |  | PR_BEGIN_EXTERN_C  | 
63  |  |  | 
64  |  | /*  | 
65  |  |  * Opaque object used by the decoder to store state.  | 
66  |  |  */  | 
67  |  | struct PLBase64DecoderStr { | 
68  |  |     /* Current token (or portion, if token_size < 4) being decoded. */  | 
69  |  |     unsigned char token[4];  | 
70  |  |     int token_size;  | 
71  |  |  | 
72  |  |     /*  | 
73  |  |      * Where to write the decoded data (used when streaming, not when  | 
74  |  |      * doing all in-memory (buffer) operations).  | 
75  |  |      *  | 
76  |  |      * Note that this definition is chosen to be compatible with PR_Write.  | 
77  |  |      */  | 
78  |  |     PRInt32 (*output_fn)(void *output_arg, const unsigned char *buf,  | 
79  |  |                          PRInt32 size);  | 
80  |  |     void *output_arg;  | 
81  |  |  | 
82  |  |     /*  | 
83  |  |      * Where the decoded output goes -- either temporarily (in the streaming  | 
84  |  |      * case, staged here before it goes to the output function) or what will  | 
85  |  |      * be the entire buffered result for users of the buffer version.  | 
86  |  |      */  | 
87  |  |     unsigned char *output_buffer;  | 
88  |  |     PRUint32 output_buflen; /* the total length of allocated buffer */  | 
89  |  |     PRUint32 output_length; /* the length that is currently populated */  | 
90  |  | };  | 
91  |  |  | 
92  |  | PR_END_EXTERN_C  | 
93  |  |  | 
94  |  | /* A constant time range check for unsigned chars.  | 
95  |  |  * Returns 255 if a <= x <= b and 0 otherwise.  | 
96  |  |  */  | 
97  |  | static inline unsigned char  | 
98  |  | ct_u8_in_range(unsigned char x, unsigned char a, unsigned char b)  | 
99  | 0  | { | 
100  |  |     /*  Let x, a, b be ints in {0, 1, ... 255}. | 
101  |  |      *  The value (a - x - 1) is in {-256, ..., 254}, so the low | 
102  |  |      *  8 bits of  | 
103  |  |      *      (a - x - 1) >> 8  | 
104  |  |      *  are all 1 if a <= x and all 0 if a > x.  | 
105  |  |      *  | 
106  |  |      *  Likewise the low 8 bits of  | 
107  |  |      *      ((a - x - 1) >> 8) & ((x - c - 1) >> 8)  | 
108  |  |      *  are all 1 if a <= x <= c and all 0 otherwise.  | 
109  |  |      *  | 
110  |  |      *  The same is true if we perform the shift after the AND  | 
111  |  |      *      ((a - x - 1) & (x - b - 1)) >> 8.  | 
112  |  |      */  | 
113  | 0  |     return (unsigned char)(((a - x - 1) & (x - b - 1)) >> 8);  | 
114  | 0  | }  | 
115  |  |  | 
116  |  | /* Convert a base64 code [A-Za-z0-9+/] to its value in {1, 2, ..., 64}. | 
117  |  |  * The use of 1-64 instead of 0-63 is so that the special value of zero can  | 
118  |  |  * denote an invalid mapping; that was much easier than trying to fill in the  | 
119  |  |  * other values with some value other than zero, and to check for it.  | 
120  |  |  * Just remember to SUBTRACT ONE when using the value retrieved.  | 
121  |  |  */  | 
122  |  | static unsigned char  | 
123  |  | pl_base64_codetovaluep1(unsigned char code)  | 
124  | 0  | { | 
125  | 0  |     unsigned char mask;  | 
126  | 0  |     unsigned char res = 0;  | 
127  |  |  | 
128  |  |     /* The range 'A' to 'Z' is mapped to 1 to 26 */  | 
129  | 0  |     mask = ct_u8_in_range(code, 'A', 'Z');  | 
130  | 0  |     res |= mask & (code - 'A' + 1);  | 
131  |  |  | 
132  |  |     /* The range 'a' to 'z' is mapped to 27 to 52 */  | 
133  | 0  |     mask = ct_u8_in_range(code, 'a', 'z');  | 
134  | 0  |     res |= mask & (code - 'a' + 27);  | 
135  |  |  | 
136  |  |     /* The range '0' to '9' is mapped to 53 to 62 */  | 
137  | 0  |     mask = ct_u8_in_range(code, '0', '9');  | 
138  | 0  |     res |= mask & (code - '0' + 53);  | 
139  |  |  | 
140  |  |     /* The code '+' is mapped to 63 */  | 
141  | 0  |     mask = ct_u8_in_range(code, '+', '+');  | 
142  | 0  |     res |= mask & 63;  | 
143  |  |  | 
144  |  |     /* The code '/' is mapped to 64 */  | 
145  | 0  |     mask = ct_u8_in_range(code, '/', '/');  | 
146  | 0  |     res |= mask & 64;  | 
147  |  |  | 
148  |  |     /* All other characters, including '=' are mapped to 0. */  | 
149  | 0  |     return res;  | 
150  | 0  | }  | 
151  |  |  | 
152  | 0  | #define B64_PAD '='  | 
153  |  |  | 
154  |  | /*  | 
155  |  |  * Reads 4; writes 3 (known, or expected, to have no trailing padding).  | 
156  |  |  * Returns bytes written; -1 on error (unexpected character).  | 
157  |  |  */  | 
158  |  | static int  | 
159  |  | pl_base64_decode_4to3(const unsigned char *in, unsigned char *out)  | 
160  | 0  | { | 
161  | 0  |     int j;  | 
162  | 0  |     PRUint32 num = 0;  | 
163  | 0  |     unsigned char bits;  | 
164  |  | 
  | 
165  | 0  |     for (j = 0; j < 4; j++) { | 
166  | 0  |         bits = pl_base64_codetovaluep1(in[j]);  | 
167  | 0  |         if (bits == 0)  | 
168  | 0  |             return -1;  | 
169  | 0  |         num = (num << 6) | (bits - 1);  | 
170  | 0  |     }  | 
171  |  |  | 
172  | 0  |     out[0] = (unsigned char)(num >> 16);  | 
173  | 0  |     out[1] = (unsigned char)((num >> 8) & 0xFF);  | 
174  | 0  |     out[2] = (unsigned char)(num & 0xFF);  | 
175  |  | 
  | 
176  | 0  |     return 3;  | 
177  | 0  | }  | 
178  |  |  | 
179  |  | /*  | 
180  |  |  * Reads 3; writes 2 (caller already confirmed EOF or trailing padding).  | 
181  |  |  * Returns bytes written; -1 on error (unexpected character).  | 
182  |  |  */  | 
183  |  | static int  | 
184  |  | pl_base64_decode_3to2(const unsigned char *in, unsigned char *out)  | 
185  | 0  | { | 
186  | 0  |     PRUint32 num = 0;  | 
187  | 0  |     unsigned char bits1, bits2, bits3;  | 
188  |  | 
  | 
189  | 0  |     bits1 = pl_base64_codetovaluep1(in[0]);  | 
190  | 0  |     bits2 = pl_base64_codetovaluep1(in[1]);  | 
191  | 0  |     bits3 = pl_base64_codetovaluep1(in[2]);  | 
192  |  | 
  | 
193  | 0  |     if ((bits1 == 0) || (bits2 == 0) || (bits3 == 0))  | 
194  | 0  |         return -1;  | 
195  |  |  | 
196  | 0  |     num = ((PRUint32)(bits1 - 1)) << 10;  | 
197  | 0  |     num |= ((PRUint32)(bits2 - 1)) << 4;  | 
198  | 0  |     num |= ((PRUint32)(bits3 - 1)) >> 2;  | 
199  |  | 
  | 
200  | 0  |     out[0] = (unsigned char)(num >> 8);  | 
201  | 0  |     out[1] = (unsigned char)(num & 0xFF);  | 
202  |  | 
  | 
203  | 0  |     return 2;  | 
204  | 0  | }  | 
205  |  |  | 
206  |  | /*  | 
207  |  |  * Reads 2; writes 1 (caller already confirmed EOF or trailing padding).  | 
208  |  |  * Returns bytes written; -1 on error (unexpected character).  | 
209  |  |  */  | 
210  |  | static int  | 
211  |  | pl_base64_decode_2to1(const unsigned char *in, unsigned char *out)  | 
212  | 0  | { | 
213  | 0  |     PRUint32 num = 0;  | 
214  | 0  |     unsigned char bits1, bits2;  | 
215  |  | 
  | 
216  | 0  |     bits1 = pl_base64_codetovaluep1(in[0]);  | 
217  | 0  |     bits2 = pl_base64_codetovaluep1(in[1]);  | 
218  |  | 
  | 
219  | 0  |     if ((bits1 == 0) || (bits2 == 0))  | 
220  | 0  |         return -1;  | 
221  |  |  | 
222  | 0  |     num = ((PRUint32)(bits1 - 1)) << 2;  | 
223  | 0  |     num |= ((PRUint32)(bits2 - 1)) >> 4;  | 
224  |  | 
  | 
225  | 0  |     out[0] = (unsigned char)num;  | 
226  |  | 
  | 
227  | 0  |     return 1;  | 
228  | 0  | }  | 
229  |  |  | 
230  |  | /*  | 
231  |  |  * Reads 4; writes 0-3.  Returns bytes written or -1 on error.  | 
232  |  |  * (Writes less than 3 only at (presumed) EOF.)  | 
233  |  |  */  | 
234  |  | static int  | 
235  |  | pl_base64_decode_token(const unsigned char *in, unsigned char *out)  | 
236  | 0  | { | 
237  | 0  |     if (in[3] != B64_PAD)  | 
238  | 0  |         return pl_base64_decode_4to3(in, out);  | 
239  |  |  | 
240  | 0  |     if (in[2] == B64_PAD)  | 
241  | 0  |         return pl_base64_decode_2to1(in, out);  | 
242  |  |  | 
243  | 0  |     return pl_base64_decode_3to2(in, out);  | 
244  | 0  | }  | 
245  |  |  | 
246  |  | static PRStatus  | 
247  |  | pl_base64_decode_buffer(PLBase64Decoder *data, const unsigned char *in,  | 
248  |  |                         PRUint32 length)  | 
249  | 0  | { | 
250  | 0  |     unsigned char *out = data->output_buffer;  | 
251  | 0  |     unsigned char *token = data->token;  | 
252  | 0  |     int i, n = 0;  | 
253  |  | 
  | 
254  | 0  |     i = data->token_size;  | 
255  | 0  |     data->token_size = 0;  | 
256  |  | 
  | 
257  | 0  |     while (length > 0) { | 
258  | 0  |         while (i < 4 && length > 0) { | 
259  |  |             /*  | 
260  |  |              * XXX Note that the following simply ignores any unexpected  | 
261  |  |              * characters.  This is exactly what the original code in  | 
262  |  |              * libmime did, and I am leaving it.  We certainly want to skip  | 
263  |  |              * over whitespace (we must); this does much more than that.  | 
264  |  |              * I am not confident changing it, and I don't want to slow  | 
265  |  |              * the processing down doing more complicated checking, but  | 
266  |  |              * someone else might have different ideas in the future.  | 
267  |  |              */  | 
268  | 0  |             if (pl_base64_codetovaluep1(*in) > 0 || *in == B64_PAD)  | 
269  | 0  |                 token[i++] = *in;  | 
270  | 0  |             in++;  | 
271  | 0  |             length--;  | 
272  | 0  |         }  | 
273  |  | 
  | 
274  | 0  |         if (i < 4) { | 
275  |  |             /* Didn't get enough for a complete token. */  | 
276  | 0  |             data->token_size = i;  | 
277  | 0  |             break;  | 
278  | 0  |         }  | 
279  | 0  |         i = 0;  | 
280  |  | 
  | 
281  | 0  |         PR_ASSERT((PRUint32)(out - data->output_buffer + 3) <= data->output_buflen);  | 
282  |  |  | 
283  |  |         /*  | 
284  |  |          * Assume we are not at the end; the following function only works  | 
285  |  |          * for an internal token (no trailing padding characters) but is  | 
286  |  |          * faster that way.  If it hits an invalid character (padding) it  | 
287  |  |          * will return an error; we break out of the loop and try again  | 
288  |  |          * calling the routine that will handle a final token.  | 
289  |  |          * Note that we intentionally do it this way rather than explicitly  | 
290  |  |          * add a check for padding here (because that would just slow down  | 
291  |  |          * the normal case) nor do we rely on checking whether we have more  | 
292  |  |          * input to process (because that would also slow it down but also  | 
293  |  |          * because we want to allow trailing garbage, especially white space  | 
294  |  |          * and cannot tell that without read-ahead, also a slow proposition).  | 
295  |  |          * Whew.  Understand?  | 
296  |  |          */  | 
297  | 0  |         n = pl_base64_decode_4to3(token, out);  | 
298  | 0  |         if (n < 0)  | 
299  | 0  |             break;  | 
300  |  |  | 
301  |  |         /* Advance "out" by the number of bytes just written to it. */  | 
302  | 0  |         out += n;  | 
303  | 0  |         n = 0;  | 
304  | 0  |     }  | 
305  |  |  | 
306  |  |     /*  | 
307  |  |      * See big comment above, before call to pl_base64_decode_4to3.  | 
308  |  |      * Here we check if we error'd out of loop, and allow for the case  | 
309  |  |      * that we are processing the last interesting token.  If the routine  | 
310  |  |      * which should handle padding characters also fails, then we just  | 
311  |  |      * have bad input and give up.  | 
312  |  |      */  | 
313  | 0  |     if (n < 0) { | 
314  | 0  |         n = pl_base64_decode_token(token, out);  | 
315  | 0  |         if (n < 0)  | 
316  | 0  |             return PR_FAILURE;  | 
317  |  |  | 
318  | 0  |         out += n;  | 
319  | 0  |     }  | 
320  |  |  | 
321  |  |     /*  | 
322  |  |      * As explained above, we can get here with more input remaining, but  | 
323  |  |      * it should be all characters we do not care about (i.e. would be  | 
324  |  |      * ignored when transferring from "in" to "token" in loop above,  | 
325  |  |      * except here we choose to ignore extraneous pad characters, too).  | 
326  |  |      * Swallow it, performing that check.  If we find more characters that  | 
327  |  |      * we would expect to decode, something is wrong.  | 
328  |  |      */  | 
329  | 0  |     while (length > 0) { | 
330  | 0  |         if (pl_base64_codetovaluep1(*in) > 0)  | 
331  | 0  |             return PR_FAILURE;  | 
332  | 0  |         in++;  | 
333  | 0  |         length--;  | 
334  | 0  |     }  | 
335  |  |  | 
336  |  |     /* Record the length of decoded data we have left in output_buffer. */  | 
337  | 0  |     data->output_length = (PRUint32)(out - data->output_buffer);  | 
338  | 0  |     return PR_SUCCESS;  | 
339  | 0  | }  | 
340  |  |  | 
341  |  | /*  | 
342  |  |  * Flush any remaining buffered characters.  Given well-formed input,  | 
343  |  |  * this will have nothing to do.  If the input was missing the padding  | 
344  |  |  * characters at the end, though, there could be 1-3 characters left  | 
345  |  |  * behind -- we will tolerate that by adding the padding for them.  | 
346  |  |  */  | 
347  |  | static PRStatus  | 
348  |  | pl_base64_decode_flush(PLBase64Decoder *data)  | 
349  | 0  | { | 
350  | 0  |     int count;  | 
351  |  |  | 
352  |  |     /*  | 
353  |  |      * If no remaining characters, or all are padding (also not well-formed  | 
354  |  |      * input, but again, be tolerant), then nothing more to do.  (And, that  | 
355  |  |      * is considered successful.)  | 
356  |  |      */  | 
357  | 0  |     if (data->token_size == 0 || data->token[0] == B64_PAD)  | 
358  | 0  |         return PR_SUCCESS;  | 
359  |  |  | 
360  |  |     /*  | 
361  |  |      * Assume we have all the interesting input except for some expected  | 
362  |  |      * padding characters.  Add them and decode the resulting token.  | 
363  |  |      */  | 
364  | 0  |     while (data->token_size < 4)  | 
365  | 0  |         data->token[data->token_size++] = B64_PAD;  | 
366  |  | 
  | 
367  | 0  |     data->token_size = 0; /* so a subsequent flush call is a no-op */  | 
368  |  | 
  | 
369  | 0  |     count = pl_base64_decode_token(data->token,  | 
370  | 0  |                                    data->output_buffer + data->output_length);  | 
371  | 0  |     if (count < 0)  | 
372  | 0  |         return PR_FAILURE;  | 
373  |  |  | 
374  |  |     /*  | 
375  |  |      * If there is an output function, call it with this last bit of data.  | 
376  |  |      * Otherwise we are doing all buffered output, and the decoded bytes  | 
377  |  |      * are now there, we just need to reflect that in the length.  | 
378  |  |      */  | 
379  | 0  |     if (data->output_fn != NULL) { | 
380  | 0  |         PRInt32 output_result;  | 
381  |  | 
  | 
382  | 0  |         PR_ASSERT(data->output_length == 0);  | 
383  | 0  |         output_result = data->output_fn(data->output_arg,  | 
384  | 0  |                                         data->output_buffer,  | 
385  | 0  |                                         (PRInt32)count);  | 
386  | 0  |         if (output_result < 0)  | 
387  | 0  |             return PR_FAILURE;  | 
388  | 0  |     } else { | 
389  | 0  |         data->output_length += count;  | 
390  | 0  |     }  | 
391  |  |  | 
392  | 0  |     return PR_SUCCESS;  | 
393  | 0  | }  | 
394  |  |  | 
395  |  | /*  | 
396  |  |  * The maximum space needed to hold the output of the decoder given  | 
397  |  |  * input data of length "size".  | 
398  |  |  */  | 
399  |  | static PRUint32  | 
400  |  | PL_Base64MaxDecodedLength(PRUint32 size)  | 
401  | 0  | { | 
402  | 0  |     return size * 0.75;  | 
403  | 0  | }  | 
404  |  |  | 
405  |  | /*  | 
406  |  |  * A distinct internal creation function for the buffer version to use.  | 
407  |  |  * (It does not want to specify an output_fn, and we want the normal  | 
408  |  |  * Create function to require that.)  If more common initialization  | 
409  |  |  * of the decoding context needs to be done, it should be done *here*.  | 
410  |  |  */  | 
411  |  | static PLBase64Decoder *  | 
412  |  | pl_base64_create_decoder(void)  | 
413  | 0  | { | 
414  | 0  |     return PR_NEWZAP(PLBase64Decoder);  | 
415  | 0  | }  | 
416  |  |  | 
417  |  | /*  | 
418  |  |  * Function to start a base64 decoding context.  | 
419  |  |  * An "output_fn" is required; the "output_arg" parameter to that is optional.  | 
420  |  |  */  | 
421  |  | static PLBase64Decoder *  | 
422  |  | PL_CreateBase64Decoder(PRInt32 (*output_fn)(void *, const unsigned char *,  | 
423  |  |                                             PRInt32),  | 
424  |  |                        void *output_arg)  | 
425  | 0  | { | 
426  | 0  |     PLBase64Decoder *data;  | 
427  |  | 
  | 
428  | 0  |     if (output_fn == NULL) { | 
429  | 0  |         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);  | 
430  | 0  |         return NULL;  | 
431  | 0  |     }  | 
432  |  |  | 
433  | 0  |     data = pl_base64_create_decoder();  | 
434  | 0  |     if (data != NULL) { | 
435  | 0  |         data->output_fn = output_fn;  | 
436  | 0  |         data->output_arg = output_arg;  | 
437  | 0  |     }  | 
438  | 0  |     return data;  | 
439  | 0  | }  | 
440  |  |  | 
441  |  | /*  | 
442  |  |  * Push data through the decoder, causing the output_fn (provided to Create)  | 
443  |  |  * to be called with the decoded data.  | 
444  |  |  */  | 
445  |  | static PRStatus  | 
446  |  | PL_UpdateBase64Decoder(PLBase64Decoder *data, const char *buffer,  | 
447  |  |                        PRUint32 size)  | 
448  | 0  | { | 
449  | 0  |     PRUint32 need_length;  | 
450  | 0  |     PRStatus status;  | 
451  |  |  | 
452  |  |     /* XXX Should we do argument checking only in debug build? */  | 
453  | 0  |     if (data == NULL || buffer == NULL || size == 0) { | 
454  | 0  |         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);  | 
455  | 0  |         return PR_FAILURE;  | 
456  | 0  |     }  | 
457  |  |  | 
458  |  |     /*  | 
459  |  |      * How much space could this update need for decoding?  | 
460  |  |      */  | 
461  | 0  |     need_length = PL_Base64MaxDecodedLength(size + data->token_size);  | 
462  |  |  | 
463  |  |     /*  | 
464  |  |      * Make sure we have at least that much.  If not, (re-)allocate.  | 
465  |  |      */  | 
466  | 0  |     if (need_length > data->output_buflen) { | 
467  | 0  |         unsigned char *output_buffer = data->output_buffer;  | 
468  |  | 
  | 
469  | 0  |         if (output_buffer != NULL)  | 
470  | 0  |             output_buffer = (unsigned char *)PR_Realloc(output_buffer,  | 
471  | 0  |                                                         need_length);  | 
472  | 0  |         else  | 
473  | 0  |             output_buffer = (unsigned char *)PR_Malloc(need_length);  | 
474  |  | 
  | 
475  | 0  |         if (output_buffer == NULL)  | 
476  | 0  |             return PR_FAILURE;  | 
477  |  |  | 
478  | 0  |         data->output_buffer = output_buffer;  | 
479  | 0  |         data->output_buflen = need_length;  | 
480  | 0  |     }  | 
481  |  |  | 
482  |  |     /* There should not have been any leftover output data in the buffer. */  | 
483  | 0  |     PR_ASSERT(data->output_length == 0);  | 
484  | 0  |     data->output_length = 0;  | 
485  |  | 
  | 
486  | 0  |     status = pl_base64_decode_buffer(data, (const unsigned char *)buffer,  | 
487  | 0  |                                      size);  | 
488  |  |  | 
489  |  |     /* Now that we have some decoded data, write it. */  | 
490  | 0  |     if (status == PR_SUCCESS && data->output_length > 0) { | 
491  | 0  |         PRInt32 output_result;  | 
492  |  | 
  | 
493  | 0  |         PR_ASSERT(data->output_fn != NULL);  | 
494  | 0  |         output_result = data->output_fn(data->output_arg,  | 
495  | 0  |                                         data->output_buffer,  | 
496  | 0  |                                         (PRInt32)data->output_length);  | 
497  | 0  |         if (output_result < 0)  | 
498  | 0  |             status = PR_FAILURE;  | 
499  | 0  |     }  | 
500  |  | 
  | 
501  | 0  |     data->output_length = 0;  | 
502  | 0  |     return status;  | 
503  | 0  | }  | 
504  |  |  | 
505  |  | /*  | 
506  |  |  * When you're done decoding, call this to free the data.  If "abort_p"  | 
507  |  |  * is false, then calling this may cause the output_fn to be called  | 
508  |  |  * one last time (as the last buffered data is flushed out).  | 
509  |  |  */  | 
510  |  | static PRStatus  | 
511  |  | PL_DestroyBase64Decoder(PLBase64Decoder *data, PRBool abort_p)  | 
512  | 0  | { | 
513  | 0  |     PRStatus status = PR_SUCCESS;  | 
514  |  |  | 
515  |  |     /* XXX Should we do argument checking only in debug build? */  | 
516  | 0  |     if (data == NULL) { | 
517  | 0  |         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);  | 
518  | 0  |         return PR_FAILURE;  | 
519  | 0  |     }  | 
520  |  |  | 
521  |  |     /* Flush out the last few buffered characters. */  | 
522  | 0  |     if (!abort_p)  | 
523  | 0  |         status = pl_base64_decode_flush(data);  | 
524  |  | 
  | 
525  | 0  |     if (data->output_buffer != NULL)  | 
526  | 0  |         PR_Free(data->output_buffer);  | 
527  | 0  |     PR_Free(data);  | 
528  |  | 
  | 
529  | 0  |     return status;  | 
530  | 0  | }  | 
531  |  |  | 
532  |  | /*  | 
533  |  |  * Perform base64 decoding from an input buffer to an output buffer.  | 
534  |  |  * The output buffer can be provided (as "dest"); you can also pass in  | 
535  |  |  * a NULL and this function will allocate a buffer large enough for you,  | 
536  |  |  * and return it.  If you do provide the output buffer, you must also  | 
537  |  |  * provide the maximum length of that buffer (as "maxdestlen").  | 
538  |  |  * The actual decoded length of output will be returned to you in  | 
539  |  |  * "output_destlen".  | 
540  |  |  *  | 
541  |  |  * Return value is NULL on error, the output buffer (allocated or provided)  | 
542  |  |  * otherwise.  | 
543  |  |  */  | 
544  |  | static unsigned char *  | 
545  |  | PL_Base64DecodeBuffer(const char *src, PRUint32 srclen, unsigned char *dest,  | 
546  |  |                       PRUint32 maxdestlen, PRUint32 *output_destlen)  | 
547  | 0  | { | 
548  | 0  |     PRUint32 need_length;  | 
549  | 0  |     unsigned char *output_buffer = NULL;  | 
550  | 0  |     PLBase64Decoder *data = NULL;  | 
551  | 0  |     PRStatus status;  | 
552  |  | 
  | 
553  | 0  |     PR_ASSERT(srclen > 0);  | 
554  | 0  |     if (srclen == 0) { | 
555  | 0  |         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);  | 
556  | 0  |         return NULL;  | 
557  | 0  |     }  | 
558  |  |  | 
559  |  |     /*  | 
560  |  |      * How much space could we possibly need for decoding this input?  | 
561  |  |      */  | 
562  | 0  |     need_length = PL_Base64MaxDecodedLength(srclen);  | 
563  |  |  | 
564  |  |     /*  | 
565  |  |      * Make sure we have at least that much, if output buffer provided.  | 
566  |  |      * If no output buffer provided, then we allocate that much.  | 
567  |  |      */  | 
568  | 0  |     if (dest != NULL) { | 
569  | 0  |         PR_ASSERT(maxdestlen >= need_length);  | 
570  | 0  |         if (maxdestlen < need_length) { | 
571  | 0  |             PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0);  | 
572  | 0  |             goto loser;  | 
573  | 0  |         }  | 
574  | 0  |         output_buffer = dest;  | 
575  | 0  |     } else { | 
576  | 0  |         output_buffer = (unsigned char *)PR_Malloc(need_length);  | 
577  | 0  |         if (output_buffer == NULL)  | 
578  | 0  |             goto loser;  | 
579  | 0  |         maxdestlen = need_length;  | 
580  | 0  |     }  | 
581  |  |  | 
582  | 0  |     data = pl_base64_create_decoder();  | 
583  | 0  |     if (data == NULL)  | 
584  | 0  |         goto loser;  | 
585  |  |  | 
586  | 0  |     data->output_buflen = maxdestlen;  | 
587  | 0  |     data->output_buffer = output_buffer;  | 
588  |  | 
  | 
589  | 0  |     status = pl_base64_decode_buffer(data, (const unsigned char *)src,  | 
590  | 0  |                                      srclen);  | 
591  |  |  | 
592  |  |     /*  | 
593  |  |      * We do not wait for Destroy to flush, because Destroy will also  | 
594  |  |      * get rid of our decoder context, which we need to look at first!  | 
595  |  |      */  | 
596  | 0  |     if (status == PR_SUCCESS)  | 
597  | 0  |         status = pl_base64_decode_flush(data);  | 
598  |  |  | 
599  |  |     /* Must clear this or Destroy will free it. */  | 
600  | 0  |     data->output_buffer = NULL;  | 
601  |  | 
  | 
602  | 0  |     if (status == PR_SUCCESS) { | 
603  | 0  |         *output_destlen = data->output_length;  | 
604  | 0  |         status = PL_DestroyBase64Decoder(data, PR_FALSE);  | 
605  | 0  |         data = NULL;  | 
606  | 0  |         if (status == PR_FAILURE)  | 
607  | 0  |             goto loser;  | 
608  | 0  |         return output_buffer;  | 
609  | 0  |     }  | 
610  |  |  | 
611  | 0  | loser:  | 
612  | 0  |     if (dest == NULL && output_buffer != NULL)  | 
613  | 0  |         PR_Free(output_buffer);  | 
614  | 0  |     if (data != NULL)  | 
615  | 0  |         (void)PL_DestroyBase64Decoder(data, PR_TRUE);  | 
616  | 0  |     return NULL;  | 
617  | 0  | }  | 
618  |  |  | 
619  |  | /*  | 
620  |  |  * XXX End of base64 decoding code to be moved into NSPR.  | 
621  |  |  ********************************************************  | 
622  |  |  */  | 
623  |  |  | 
624  |  | /*  | 
625  |  |  * This is the beginning of the NSS cover functions.  These will  | 
626  |  |  * provide the interface we want to expose as NSS-ish.  For example,  | 
627  |  |  * they will operate on our Items, do any special handling or checking  | 
628  |  |  * we want to do, etc.  | 
629  |  |  */  | 
630  |  |  | 
631  |  | PR_BEGIN_EXTERN_C  | 
632  |  |  | 
633  |  | /*  | 
634  |  |  * A boring cover structure for now.  Perhaps someday it will include  | 
635  |  |  * some more interesting fields.  | 
636  |  |  */  | 
637  |  | struct NSSBase64DecoderStr { | 
638  |  |     PLBase64Decoder *pl_data;  | 
639  |  | };  | 
640  |  |  | 
641  |  | PR_END_EXTERN_C  | 
642  |  |  | 
643  |  | /*  | 
644  |  |  * Function to start a base64 decoding context.  | 
645  |  |  */  | 
646  |  | NSSBase64Decoder *  | 
647  |  | NSSBase64Decoder_Create(PRInt32 (*output_fn)(void *, const unsigned char *,  | 
648  |  |                                              PRInt32),  | 
649  |  |                         void *output_arg)  | 
650  | 0  | { | 
651  | 0  |     PLBase64Decoder *pl_data;  | 
652  | 0  |     NSSBase64Decoder *nss_data;  | 
653  |  | 
  | 
654  | 0  |     nss_data = PORT_ZNew(NSSBase64Decoder);  | 
655  | 0  |     if (nss_data == NULL)  | 
656  | 0  |         return NULL;  | 
657  |  |  | 
658  | 0  |     pl_data = PL_CreateBase64Decoder(output_fn, output_arg);  | 
659  | 0  |     if (pl_data == NULL) { | 
660  | 0  |         PORT_Free(nss_data);  | 
661  | 0  |         return NULL;  | 
662  | 0  |     }  | 
663  |  |  | 
664  | 0  |     nss_data->pl_data = pl_data;  | 
665  | 0  |     return nss_data;  | 
666  | 0  | }  | 
667  |  |  | 
668  |  | /*  | 
669  |  |  * Push data through the decoder, causing the output_fn (provided to Create)  | 
670  |  |  * to be called with the decoded data.  | 
671  |  |  */  | 
672  |  | SECStatus  | 
673  |  | NSSBase64Decoder_Update(NSSBase64Decoder *data, const char *buffer,  | 
674  |  |                         PRUint32 size)  | 
675  | 0  | { | 
676  | 0  |     PRStatus pr_status;  | 
677  |  |  | 
678  |  |     /* XXX Should we do argument checking only in debug build? */  | 
679  | 0  |     if (data == NULL) { | 
680  | 0  |         PORT_SetError(SEC_ERROR_INVALID_ARGS);  | 
681  | 0  |         return SECFailure;  | 
682  | 0  |     }  | 
683  |  |  | 
684  | 0  |     pr_status = PL_UpdateBase64Decoder(data->pl_data, buffer, size);  | 
685  | 0  |     if (pr_status == PR_FAILURE)  | 
686  | 0  |         return SECFailure;  | 
687  |  |  | 
688  | 0  |     return SECSuccess;  | 
689  | 0  | }  | 
690  |  |  | 
691  |  | /*  | 
692  |  |  * When you're done decoding, call this to free the data.  If "abort_p"  | 
693  |  |  * is false, then calling this may cause the output_fn to be called  | 
694  |  |  * one last time (as the last buffered data is flushed out).  | 
695  |  |  */  | 
696  |  | SECStatus  | 
697  |  | NSSBase64Decoder_Destroy(NSSBase64Decoder *data, PRBool abort_p)  | 
698  | 0  | { | 
699  | 0  |     PRStatus pr_status;  | 
700  |  |  | 
701  |  |     /* XXX Should we do argument checking only in debug build? */  | 
702  | 0  |     if (data == NULL) { | 
703  | 0  |         PORT_SetError(SEC_ERROR_INVALID_ARGS);  | 
704  | 0  |         return SECFailure;  | 
705  | 0  |     }  | 
706  |  |  | 
707  | 0  |     pr_status = PL_DestroyBase64Decoder(data->pl_data, abort_p);  | 
708  |  | 
  | 
709  | 0  |     PORT_Free(data);  | 
710  |  | 
  | 
711  | 0  |     if (pr_status == PR_FAILURE)  | 
712  | 0  |         return SECFailure;  | 
713  |  |  | 
714  | 0  |     return SECSuccess;  | 
715  | 0  | }  | 
716  |  |  | 
717  |  | /*  | 
718  |  |  * Perform base64 decoding from an ascii string "inStr" to an Item.  | 
719  |  |  * The length of the input must be provided as "inLen".  The Item  | 
720  |  |  * may be provided (as "outItemOpt"); you can also pass in a NULL  | 
721  |  |  * and the Item will be allocated for you.  | 
722  |  |  *  | 
723  |  |  * In any case, the data within the Item will be allocated for you.  | 
724  |  |  * All allocation will happen out of the passed-in "arenaOpt", if non-NULL.  | 
725  |  |  * If "arenaOpt" is NULL, standard allocation (heap) will be used and  | 
726  |  |  * you will want to free the result via SECITEM_FreeItem.  | 
727  |  |  *  | 
728  |  |  * Return value is NULL on error, the Item (allocated or provided) otherwise.  | 
729  |  |  */  | 
730  |  | SECItem *  | 
731  |  | NSSBase64_DecodeBuffer(PLArenaPool *arenaOpt, SECItem *outItemOpt,  | 
732  |  |                        const char *inStr, unsigned int inLen)  | 
733  | 0  | { | 
734  | 0  |     SECItem *out_item = NULL;  | 
735  | 0  |     PRUint32 max_out_len = 0;  | 
736  | 0  |     void *mark = NULL;  | 
737  | 0  |     unsigned char *dummy = NULL;  | 
738  |  | 
  | 
739  | 0  |     if ((outItemOpt != NULL && outItemOpt->data != NULL) || inLen == 0) { | 
740  | 0  |         PORT_SetError(SEC_ERROR_INVALID_ARGS);  | 
741  | 0  |         return NULL;  | 
742  | 0  |     }  | 
743  |  |  | 
744  | 0  |     if (arenaOpt != NULL)  | 
745  | 0  |         mark = PORT_ArenaMark(arenaOpt);  | 
746  |  | 
  | 
747  | 0  |     max_out_len = PL_Base64MaxDecodedLength(inLen);  | 
748  | 0  |     if (max_out_len == 0) { | 
749  | 0  |         goto loser;  | 
750  | 0  |     }  | 
751  | 0  |     out_item = SECITEM_AllocItem(arenaOpt, outItemOpt, max_out_len);  | 
752  | 0  |     if (out_item == NULL) { | 
753  | 0  |         goto loser;  | 
754  | 0  |     }  | 
755  |  |  | 
756  | 0  |     dummy = PL_Base64DecodeBuffer(inStr, inLen, out_item->data,  | 
757  | 0  |                                   max_out_len, &out_item->len);  | 
758  | 0  |     if (dummy == NULL) { | 
759  | 0  |         goto loser;  | 
760  | 0  |     }  | 
761  | 0  |     if (arenaOpt != NULL) { | 
762  | 0  |         PORT_ArenaUnmark(arenaOpt, mark);  | 
763  | 0  |     }  | 
764  | 0  |     return out_item;  | 
765  |  |  | 
766  | 0  | loser:  | 
767  | 0  |     if (arenaOpt != NULL) { | 
768  | 0  |         PORT_ArenaRelease(arenaOpt, mark);  | 
769  | 0  |         if (outItemOpt != NULL) { | 
770  | 0  |             outItemOpt->data = NULL;  | 
771  | 0  |             outItemOpt->len = 0;  | 
772  | 0  |         }  | 
773  | 0  |     } else if (dummy == NULL) { | 
774  | 0  |         SECITEM_FreeItem(out_item, (PRBool)(outItemOpt == NULL));  | 
775  | 0  |     }  | 
776  | 0  |     return NULL;  | 
777  | 0  | }  | 
778  |  |  | 
779  |  | /*  | 
780  |  |  * XXX Everything below is deprecated.  If you add new stuff, put it  | 
781  |  |  * *above*, not below.  | 
782  |  |  */  | 
783  |  |  | 
784  |  | /*  | 
785  |  |  * XXX The following "ATOB" functions are provided for backward compatibility  | 
786  |  |  * with current code.  They should be considered strongly deprecated.  | 
787  |  |  * When we can convert all our code over to using the new NSSBase64Decoder_  | 
788  |  |  * functions defined above, we should get rid of these altogether.  (Remove  | 
789  |  |  * protoypes from base64.h as well -- actually, remove that file completely).  | 
790  |  |  * If someone thinks either of these functions provides such a very useful  | 
791  |  |  * interface (though, as shown, the same functionality can already be  | 
792  |  |  * obtained by calling NSSBase64_DecodeBuffer directly), fine -- but then  | 
793  |  |  * that API should be provided with a nice new NSSFoo name and using  | 
794  |  |  * appropriate types, etc.  | 
795  |  |  */  | 
796  |  |  | 
797  |  | #include "base64.h"  | 
798  |  |  | 
799  |  | /*  | 
800  |  | ** Return an PORT_Alloc'd string which is the base64 decoded version  | 
801  |  | ** of the input string; set *lenp to the length of the returned data.  | 
802  |  | */  | 
803  |  | unsigned char *  | 
804  |  | ATOB_AsciiToData(const char *string, unsigned int *lenp)  | 
805  | 0  | { | 
806  | 0  |     SECItem binary_item, *dummy;  | 
807  |  | 
  | 
808  | 0  |     binary_item.data = NULL;  | 
809  | 0  |     binary_item.len = 0;  | 
810  |  | 
  | 
811  | 0  |     dummy = NSSBase64_DecodeBuffer(NULL, &binary_item, string,  | 
812  | 0  |                                    (PRUint32)PORT_Strlen(string));  | 
813  | 0  |     if (dummy == NULL)  | 
814  | 0  |         return NULL;  | 
815  |  |  | 
816  | 0  |     PORT_Assert(dummy == &binary_item);  | 
817  |  | 
  | 
818  | 0  |     *lenp = dummy->len;  | 
819  | 0  |     return dummy->data;  | 
820  | 0  | }  | 
821  |  |  | 
822  |  | /*  | 
823  |  | ** Convert from ascii to binary encoding of an item.  | 
824  |  | */  | 
825  |  | SECStatus  | 
826  |  | ATOB_ConvertAsciiToItem(SECItem *binary_item, const char *ascii)  | 
827  | 0  | { | 
828  | 0  |     SECItem *dummy;  | 
829  |  | 
  | 
830  | 0  |     if (binary_item == NULL) { | 
831  | 0  |         PORT_SetError(SEC_ERROR_INVALID_ARGS);  | 
832  | 0  |         return SECFailure;  | 
833  | 0  |     }  | 
834  |  |  | 
835  |  |     /*  | 
836  |  |      * XXX Would prefer to assert here if data is non-null (actually,  | 
837  |  |      * don't need to, just let NSSBase64_DecodeBuffer do it), so as to  | 
838  |  |      * to catch unintended memory leaks, but callers are not clean in  | 
839  |  |      * this respect so we need to explicitly clear here to avoid the  | 
840  |  |      * assert in NSSBase64_DecodeBuffer.  | 
841  |  |      */  | 
842  | 0  |     binary_item->data = NULL;  | 
843  | 0  |     binary_item->len = 0;  | 
844  |  | 
  | 
845  | 0  |     dummy = NSSBase64_DecodeBuffer(NULL, binary_item, ascii,  | 
846  | 0  |                                    (PRUint32)PORT_Strlen(ascii));  | 
847  |  | 
  | 
848  | 0  |     if (dummy == NULL)  | 
849  | 0  |         return SECFailure;  | 
850  |  |  | 
851  | 0  |     return SECSuccess;  | 
852  | 0  | }  |