xref: /minix3/crypto/external/bsd/netpgp/dist/src/netpgpverify/b64.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*********************************************************************\
2*0a6a1f1dSLionel Sambuc 
3*0a6a1f1dSLionel Sambuc MODULE NAME:    b64.c
4*0a6a1f1dSLionel Sambuc 
5*0a6a1f1dSLionel Sambuc AUTHOR:         Bob Trower 08/04/01
6*0a6a1f1dSLionel Sambuc 
7*0a6a1f1dSLionel Sambuc PROJECT:        Crypt Data Packaging
8*0a6a1f1dSLionel Sambuc 
9*0a6a1f1dSLionel Sambuc COPYRIGHT:      Copyright (c) Trantor Standard Systems Inc., 2001
10*0a6a1f1dSLionel Sambuc 
11*0a6a1f1dSLionel Sambuc NOTE:           This source code may be used as you wish, subject to
12*0a6a1f1dSLionel Sambuc                 the MIT license.  See the LICENCE section below.
13*0a6a1f1dSLionel Sambuc 
14*0a6a1f1dSLionel Sambuc DESCRIPTION:
15*0a6a1f1dSLionel Sambuc                 This little utility implements the Base64
16*0a6a1f1dSLionel Sambuc                 Content-Transfer-Encoding standard described in
17*0a6a1f1dSLionel Sambuc                 RFC1113 (http://www.faqs.org/rfcs/rfc1113.html).
18*0a6a1f1dSLionel Sambuc 
19*0a6a1f1dSLionel Sambuc                 This is the coding scheme used by MIME to allow
20*0a6a1f1dSLionel Sambuc                 binary data to be transferred by SMTP mail.
21*0a6a1f1dSLionel Sambuc 
22*0a6a1f1dSLionel Sambuc                 Groups of 3 bytes from a binary stream are coded as
23*0a6a1f1dSLionel Sambuc                 groups of 4 bytes in a text stream.
24*0a6a1f1dSLionel Sambuc 
25*0a6a1f1dSLionel Sambuc                 The input stream is 'padded' with zeros to create
26*0a6a1f1dSLionel Sambuc                 an input that is an even multiple of 3.
27*0a6a1f1dSLionel Sambuc 
28*0a6a1f1dSLionel Sambuc                 A special character ('=') is used to denote padding so
29*0a6a1f1dSLionel Sambuc                 that the stream can be decoded back to its exact size.
30*0a6a1f1dSLionel Sambuc 
31*0a6a1f1dSLionel Sambuc                 Encoded output is formatted in lines which should
32*0a6a1f1dSLionel Sambuc                 be a maximum of 72 characters to conform to the
33*0a6a1f1dSLionel Sambuc                 specification.  This program defaults to 72 characters,
34*0a6a1f1dSLionel Sambuc                 but will allow more or less through the use of a
35*0a6a1f1dSLionel Sambuc                 switch.  The program enforces a minimum line size
36*0a6a1f1dSLionel Sambuc                 of 4 characters.
37*0a6a1f1dSLionel Sambuc 
38*0a6a1f1dSLionel Sambuc                 Example encoding:
39*0a6a1f1dSLionel Sambuc 
40*0a6a1f1dSLionel Sambuc                 The stream 'ABCD' is 32 bits long.  It is mapped as
41*0a6a1f1dSLionel Sambuc                 follows:
42*0a6a1f1dSLionel Sambuc 
43*0a6a1f1dSLionel Sambuc                 ABCD
44*0a6a1f1dSLionel Sambuc 
45*0a6a1f1dSLionel Sambuc                  A (65)     B (66)     C (67)     D (68)   (None) (None)
46*0a6a1f1dSLionel Sambuc                 01000001   01000010   01000011   01000100
47*0a6a1f1dSLionel Sambuc 
48*0a6a1f1dSLionel Sambuc                 16 (Q)  20 (U)  9 (J)   3 (D)    17 (R) 0 (A)  NA (=) NA (=)
49*0a6a1f1dSLionel Sambuc                 010000  010100  001001  000011   010001 000000 000000 000000
50*0a6a1f1dSLionel Sambuc 
51*0a6a1f1dSLionel Sambuc 
52*0a6a1f1dSLionel Sambuc                 QUJDRA==
53*0a6a1f1dSLionel Sambuc 
54*0a6a1f1dSLionel Sambuc                 Decoding is the process in reverse.  A 'decode' lookup
55*0a6a1f1dSLionel Sambuc                 table has been created to avoid string scans.
56*0a6a1f1dSLionel Sambuc 
57*0a6a1f1dSLionel Sambuc DESIGN GOALS:	Specifically:
58*0a6a1f1dSLionel Sambuc 		Code is a stand-alone utility to perform base64
59*0a6a1f1dSLionel Sambuc 		encoding/decoding. It should be genuinely useful
60*0a6a1f1dSLionel Sambuc 		when the need arises and it meets a need that is
61*0a6a1f1dSLionel Sambuc 		likely to occur for some users.
62*0a6a1f1dSLionel Sambuc 		Code acts as sample code to show the author's
63*0a6a1f1dSLionel Sambuc 		design and coding style.
64*0a6a1f1dSLionel Sambuc 
65*0a6a1f1dSLionel Sambuc 		Generally:
66*0a6a1f1dSLionel Sambuc 		This program is designed to survive:
67*0a6a1f1dSLionel Sambuc 		Everything you need is in a single source file.
68*0a6a1f1dSLionel Sambuc 		It compiles cleanly using a vanilla ANSI C compiler.
69*0a6a1f1dSLionel Sambuc 		It does its job correctly with a minimum of fuss.
70*0a6a1f1dSLionel Sambuc 		The code is not overly clever, not overly simplistic
71*0a6a1f1dSLionel Sambuc 		and not overly verbose.
72*0a6a1f1dSLionel Sambuc 		Access is 'cut and paste' from a web page.
73*0a6a1f1dSLionel Sambuc 		Terms of use are reasonable.
74*0a6a1f1dSLionel Sambuc 
75*0a6a1f1dSLionel Sambuc VALIDATION:     Non-trivial code is never without errors.  This
76*0a6a1f1dSLionel Sambuc                 file likely has some problems, since it has only
77*0a6a1f1dSLionel Sambuc                 been tested by the author.  It is expected with most
78*0a6a1f1dSLionel Sambuc                 source code that there is a period of 'burn-in' when
79*0a6a1f1dSLionel Sambuc                 problems are identified and corrected.  That being
80*0a6a1f1dSLionel Sambuc                 said, it is possible to have 'reasonably correct'
81*0a6a1f1dSLionel Sambuc                 code by following a regime of unit test that covers
82*0a6a1f1dSLionel Sambuc                 the most likely cases and regression testing prior
83*0a6a1f1dSLionel Sambuc                 to release.  This has been done with this code and
84*0a6a1f1dSLionel Sambuc                 it has a good probability of performing as expected.
85*0a6a1f1dSLionel Sambuc 
86*0a6a1f1dSLionel Sambuc                 Unit Test Cases:
87*0a6a1f1dSLionel Sambuc 
88*0a6a1f1dSLionel Sambuc                 case 0:empty file:
89*0a6a1f1dSLionel Sambuc                     CASE0.DAT  ->  ->
90*0a6a1f1dSLionel Sambuc                     (Zero length target file created
91*0a6a1f1dSLionel Sambuc                     on both encode and decode.)
92*0a6a1f1dSLionel Sambuc 
93*0a6a1f1dSLionel Sambuc                 case 1:One input character:
94*0a6a1f1dSLionel Sambuc                     CASE1.DAT A -> QQ== -> A
95*0a6a1f1dSLionel Sambuc 
96*0a6a1f1dSLionel Sambuc                 case 2:Two input characters:
97*0a6a1f1dSLionel Sambuc                     CASE2.DAT AB -> QUJD -> AB
98*0a6a1f1dSLionel Sambuc 
99*0a6a1f1dSLionel Sambuc                 case 3:Three input characters:
100*0a6a1f1dSLionel Sambuc                     CASE3.DAT ABC -> QUJD -> ABC
101*0a6a1f1dSLionel Sambuc 
102*0a6a1f1dSLionel Sambuc                 case 4:Four input characters:
103*0a6a1f1dSLionel Sambuc                     case4.dat ABCD -> QUJDRA== -> ABCD
104*0a6a1f1dSLionel Sambuc 
105*0a6a1f1dSLionel Sambuc                 case 5:All chars from 0 to ff, linesize set to 50:
106*0a6a1f1dSLionel Sambuc 
107*0a6a1f1dSLionel Sambuc                     AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIj
108*0a6a1f1dSLionel Sambuc                     JCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZH
109*0a6a1f1dSLionel Sambuc                     SElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWpr
110*0a6a1f1dSLionel Sambuc                     bG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6P
111*0a6a1f1dSLionel Sambuc                     kJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKz
112*0a6a1f1dSLionel Sambuc                     tLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX
113*0a6a1f1dSLionel Sambuc                     2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7
114*0a6a1f1dSLionel Sambuc                     /P3+/w==
115*0a6a1f1dSLionel Sambuc 
116*0a6a1f1dSLionel Sambuc                 case 6:Mime Block from e-mail:
117*0a6a1f1dSLionel Sambuc                     (Data same as test case 5)
118*0a6a1f1dSLionel Sambuc 
119*0a6a1f1dSLionel Sambuc                 case 7: Large files:
120*0a6a1f1dSLionel Sambuc                     Tested 28 MB file in/out.
121*0a6a1f1dSLionel Sambuc 
122*0a6a1f1dSLionel Sambuc                 case 8: Random Binary Integrity:
123*0a6a1f1dSLionel Sambuc                     This binary program (b64.exe) was encoded to base64,
124*0a6a1f1dSLionel Sambuc                     back to binary and then executed.
125*0a6a1f1dSLionel Sambuc 
126*0a6a1f1dSLionel Sambuc                 case 9 Stress:
127*0a6a1f1dSLionel Sambuc                     All files in a working directory encoded/decoded
128*0a6a1f1dSLionel Sambuc                     and compared with file comparison utility to
129*0a6a1f1dSLionel Sambuc                     ensure that multiple runs do not cause problems
130*0a6a1f1dSLionel Sambuc                     such as exhausting file handles, tmp storage, etc.
131*0a6a1f1dSLionel Sambuc 
132*0a6a1f1dSLionel Sambuc                 -------------
133*0a6a1f1dSLionel Sambuc 
134*0a6a1f1dSLionel Sambuc                 Syntax, operation and failure:
135*0a6a1f1dSLionel Sambuc                     All options/switches tested.  Performs as
136*0a6a1f1dSLionel Sambuc                     expected.
137*0a6a1f1dSLionel Sambuc 
138*0a6a1f1dSLionel Sambuc                 case 10:
139*0a6a1f1dSLionel Sambuc                     No Args -- Shows Usage Screen
140*0a6a1f1dSLionel Sambuc                     Return Code 1 (Invalid Syntax)
141*0a6a1f1dSLionel Sambuc                 case 11:
142*0a6a1f1dSLionel Sambuc                     One Arg (invalid) -- Shows Usage Screen
143*0a6a1f1dSLionel Sambuc                     Return Code 1 (Invalid Syntax)
144*0a6a1f1dSLionel Sambuc                 case 12:
145*0a6a1f1dSLionel Sambuc                     One Arg Help (-?) -- Shows detailed Usage Screen.
146*0a6a1f1dSLionel Sambuc                     Return Code 0 (Success -- help request is valid).
147*0a6a1f1dSLionel Sambuc                 case 13:
148*0a6a1f1dSLionel Sambuc                     One Arg Help (-h) -- Shows detailed Usage Screen.
149*0a6a1f1dSLionel Sambuc                     Return Code 0 (Success -- help request is valid).
150*0a6a1f1dSLionel Sambuc                 case 14:
151*0a6a1f1dSLionel Sambuc                     One Arg (valid) -- Uses stdin/stdout (filter)
152*0a6a1f1dSLionel Sambuc                     Return Code 0 (Sucess)
153*0a6a1f1dSLionel Sambuc                 case 15:
154*0a6a1f1dSLionel Sambuc                     Two Args (invalid file) -- shows system error.
155*0a6a1f1dSLionel Sambuc                     Return Code 2 (File Error)
156*0a6a1f1dSLionel Sambuc                 case 16:
157*0a6a1f1dSLionel Sambuc                     Encode non-existent file -- shows system error.
158*0a6a1f1dSLionel Sambuc                     Return Code 2 (File Error)
159*0a6a1f1dSLionel Sambuc                 case 17:
160*0a6a1f1dSLionel Sambuc                     Out of disk space -- shows system error.
161*0a6a1f1dSLionel Sambuc                     Return Code 3 (File I/O Error)
162*0a6a1f1dSLionel Sambuc 
163*0a6a1f1dSLionel Sambuc                 -------------
164*0a6a1f1dSLionel Sambuc 
165*0a6a1f1dSLionel Sambuc                 Compile/Regression test:
166*0a6a1f1dSLionel Sambuc                     gcc compiled binary under Cygwin
167*0a6a1f1dSLionel Sambuc                     Microsoft Visual Studio under Windows 2000
168*0a6a1f1dSLionel Sambuc                     Microsoft Version 6.0 C under Windows 2000
169*0a6a1f1dSLionel Sambuc 
170*0a6a1f1dSLionel Sambuc DEPENDENCIES:   None
171*0a6a1f1dSLionel Sambuc 
172*0a6a1f1dSLionel Sambuc LICENCE:        Copyright (c) 2001 Bob Trower, Trantor Standard Systems Inc.
173*0a6a1f1dSLionel Sambuc 
174*0a6a1f1dSLionel Sambuc                 Permission is hereby granted, free of charge, to any person
175*0a6a1f1dSLionel Sambuc                 obtaining a copy of this software and associated
176*0a6a1f1dSLionel Sambuc                 documentation files (the "Software"), to deal in the
177*0a6a1f1dSLionel Sambuc                 Software without restriction, including without limitation
178*0a6a1f1dSLionel Sambuc                 the rights to use, copy, modify, merge, publish, distribute,
179*0a6a1f1dSLionel Sambuc                 sublicense, and/or sell copies of the Software, and to
180*0a6a1f1dSLionel Sambuc                 permit persons to whom the Software is furnished to do so,
181*0a6a1f1dSLionel Sambuc                 subject to the following conditions:
182*0a6a1f1dSLionel Sambuc 
183*0a6a1f1dSLionel Sambuc                 The above copyright notice and this permission notice shall
184*0a6a1f1dSLionel Sambuc                 be included in all copies or substantial portions of the
185*0a6a1f1dSLionel Sambuc                 Software.
186*0a6a1f1dSLionel Sambuc 
187*0a6a1f1dSLionel Sambuc                 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
188*0a6a1f1dSLionel Sambuc                 KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
189*0a6a1f1dSLionel Sambuc                 WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
190*0a6a1f1dSLionel Sambuc                 PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
191*0a6a1f1dSLionel Sambuc                 OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
192*0a6a1f1dSLionel Sambuc                 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
193*0a6a1f1dSLionel Sambuc                 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
194*0a6a1f1dSLionel Sambuc                 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
195*0a6a1f1dSLionel Sambuc 
196*0a6a1f1dSLionel Sambuc VERSION HISTORY:
197*0a6a1f1dSLionel Sambuc                 Bob Trower 08/04/01 -- Create Version 0.00.00B
198*0a6a1f1dSLionel Sambuc 
199*0a6a1f1dSLionel Sambuc \******************************************************************* */
200*0a6a1f1dSLionel Sambuc 
201*0a6a1f1dSLionel Sambuc #include <inttypes.h>
202*0a6a1f1dSLionel Sambuc #include <stdio.h>
203*0a6a1f1dSLionel Sambuc #include <stdlib.h>
204*0a6a1f1dSLionel Sambuc 
205*0a6a1f1dSLionel Sambuc #include "b64.h"
206*0a6a1f1dSLionel Sambuc 
207*0a6a1f1dSLionel Sambuc /*
208*0a6a1f1dSLionel Sambuc ** Translation Table as described in RFC1113
209*0a6a1f1dSLionel Sambuc */
210*0a6a1f1dSLionel Sambuc static const char cb64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
211*0a6a1f1dSLionel Sambuc 
212*0a6a1f1dSLionel Sambuc /*
213*0a6a1f1dSLionel Sambuc ** Translation Table to decode (created by author)
214*0a6a1f1dSLionel Sambuc */
215*0a6a1f1dSLionel Sambuc static const char cd64[] = "|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq";
216*0a6a1f1dSLionel Sambuc 
217*0a6a1f1dSLionel Sambuc /*
218*0a6a1f1dSLionel Sambuc ** encodeblock
219*0a6a1f1dSLionel Sambuc **
220*0a6a1f1dSLionel Sambuc ** encode 3 8-bit binary bytes as 4 '6-bit' characters
221*0a6a1f1dSLionel Sambuc */
222*0a6a1f1dSLionel Sambuc static void
encodeblock(uint8_t * wordin,uint8_t * wordout,int wordlen)223*0a6a1f1dSLionel Sambuc encodeblock(uint8_t *wordin, uint8_t *wordout, int wordlen)
224*0a6a1f1dSLionel Sambuc {
225*0a6a1f1dSLionel Sambuc 	wordout[0] = cb64[(unsigned)wordin[0] >> 2];
226*0a6a1f1dSLionel Sambuc 	wordout[1] = cb64[((unsigned)(wordin[0] & 0x03) << 4) | ((unsigned)(wordin[1] & 0xf0) >> 4)];
227*0a6a1f1dSLionel Sambuc 	wordout[2] = (uint8_t)(wordlen > 1) ?
228*0a6a1f1dSLionel Sambuc 		cb64[((unsigned)(wordin[1] & 0x0f) << 2) | ((unsigned)(wordin[2] & 0xc0) >> 6)] : '=';
229*0a6a1f1dSLionel Sambuc 	wordout[3] = (uint8_t)(wordlen > 2) ? cb64[wordin[2] & 0x3f] : '=';
230*0a6a1f1dSLionel Sambuc }
231*0a6a1f1dSLionel Sambuc 
232*0a6a1f1dSLionel Sambuc /*
233*0a6a1f1dSLionel Sambuc ** encode
234*0a6a1f1dSLionel Sambuc **
235*0a6a1f1dSLionel Sambuc ** base64 encode a stream adding padding and line breaks as per spec.
236*0a6a1f1dSLionel Sambuc */
237*0a6a1f1dSLionel Sambuc int
b64encode(const char * in,const size_t insize,void * vp,size_t outsize,int linesize)238*0a6a1f1dSLionel Sambuc b64encode(const char *in, const size_t insize, void *vp, size_t outsize, int linesize)
239*0a6a1f1dSLionel Sambuc {
240*0a6a1f1dSLionel Sambuc 	const char	*inp;
241*0a6a1f1dSLionel Sambuc 	unsigned	 i;
242*0a6a1f1dSLionel Sambuc 	uint8_t		 wordout[4];
243*0a6a1f1dSLionel Sambuc 	uint8_t		 wordin[3];
244*0a6a1f1dSLionel Sambuc 	char		*out = vp;
245*0a6a1f1dSLionel Sambuc 	char		*outp;
246*0a6a1f1dSLionel Sambuc 	int              blocksout;
247*0a6a1f1dSLionel Sambuc 	int              wordlen;
248*0a6a1f1dSLionel Sambuc 
249*0a6a1f1dSLionel Sambuc 	if (in == NULL || vp == NULL) {
250*0a6a1f1dSLionel Sambuc 		return 0;
251*0a6a1f1dSLionel Sambuc 	}
252*0a6a1f1dSLionel Sambuc 	wordlen = 0;
253*0a6a1f1dSLionel Sambuc 	for (blocksout = 0, inp = in, outp = out; (size_t)(inp - in) < insize && (size_t)(outp - out) < outsize;) {
254*0a6a1f1dSLionel Sambuc 		for (wordlen = 0, i = 0; i < sizeof(wordin); i++) {
255*0a6a1f1dSLionel Sambuc 			wordin[i] = (uint8_t) *inp++;
256*0a6a1f1dSLionel Sambuc 			if ((size_t)(inp - in) <= insize) {
257*0a6a1f1dSLionel Sambuc 				wordlen++;
258*0a6a1f1dSLionel Sambuc 			} else {
259*0a6a1f1dSLionel Sambuc 				wordin[i] = 0x0;
260*0a6a1f1dSLionel Sambuc 			}
261*0a6a1f1dSLionel Sambuc 		}
262*0a6a1f1dSLionel Sambuc 		if (wordlen > 0) {
263*0a6a1f1dSLionel Sambuc 			encodeblock(wordin, wordout, wordlen);
264*0a6a1f1dSLionel Sambuc 			for (i = 0; i < sizeof(wordout) ; i++) {
265*0a6a1f1dSLionel Sambuc 				*outp++ = wordout[i];
266*0a6a1f1dSLionel Sambuc 			}
267*0a6a1f1dSLionel Sambuc 			blocksout++;
268*0a6a1f1dSLionel Sambuc 		}
269*0a6a1f1dSLionel Sambuc 		if (linesize > 0) {
270*0a6a1f1dSLionel Sambuc 			if (blocksout >= (int)(linesize / sizeof(wordout)) ||
271*0a6a1f1dSLionel Sambuc 			    (size_t)(inp - in) >= insize) {
272*0a6a1f1dSLionel Sambuc 				if (blocksout) {
273*0a6a1f1dSLionel Sambuc 					*outp++ = '\r';
274*0a6a1f1dSLionel Sambuc 					*outp++ = '\n';
275*0a6a1f1dSLionel Sambuc 				}
276*0a6a1f1dSLionel Sambuc 				blocksout = 0;
277*0a6a1f1dSLionel Sambuc 			}
278*0a6a1f1dSLionel Sambuc 		}
279*0a6a1f1dSLionel Sambuc 	}
280*0a6a1f1dSLionel Sambuc 	return (int)(outp - out);
281*0a6a1f1dSLionel Sambuc }
282*0a6a1f1dSLionel Sambuc 
283*0a6a1f1dSLionel Sambuc /*
284*0a6a1f1dSLionel Sambuc ** decodeblock
285*0a6a1f1dSLionel Sambuc **
286*0a6a1f1dSLionel Sambuc ** decode 4 '6-bit' characters into 3 8-bit binary bytes
287*0a6a1f1dSLionel Sambuc */
288*0a6a1f1dSLionel Sambuc static void
decodeblock(uint8_t wordin[4],uint8_t wordout[3])289*0a6a1f1dSLionel Sambuc decodeblock(uint8_t wordin[4], uint8_t wordout[3])
290*0a6a1f1dSLionel Sambuc {
291*0a6a1f1dSLionel Sambuc 	wordout[0] = (uint8_t) ((unsigned)wordin[0] << 2 | (unsigned)wordin[1] >> 4);
292*0a6a1f1dSLionel Sambuc 	wordout[1] = (uint8_t) ((unsigned)wordin[1] << 4 | (unsigned)wordin[2] >> 2);
293*0a6a1f1dSLionel Sambuc 	wordout[2] = (uint8_t) (((wordin[2] << 6) & 0xc0) | wordin[3]);
294*0a6a1f1dSLionel Sambuc }
295*0a6a1f1dSLionel Sambuc 
296*0a6a1f1dSLionel Sambuc /*
297*0a6a1f1dSLionel Sambuc ** decode
298*0a6a1f1dSLionel Sambuc **
299*0a6a1f1dSLionel Sambuc ** decode a base64 encoded stream discarding padding, line breaks and noise
300*0a6a1f1dSLionel Sambuc */
301*0a6a1f1dSLionel Sambuc int
b64decode(const char * in,const size_t insize,void * vp,size_t outsize)302*0a6a1f1dSLionel Sambuc b64decode(const char *in, const size_t insize, void *vp, size_t outsize)
303*0a6a1f1dSLionel Sambuc {
304*0a6a1f1dSLionel Sambuc 	const char	*inp;
305*0a6a1f1dSLionel Sambuc 	unsigned	 wordlen;
306*0a6a1f1dSLionel Sambuc 	unsigned	 i;
307*0a6a1f1dSLionel Sambuc 	uint8_t    	 wordout[3];
308*0a6a1f1dSLionel Sambuc 	uint8_t    	 wordin[4];
309*0a6a1f1dSLionel Sambuc 	uint8_t    	 v;
310*0a6a1f1dSLionel Sambuc 	char		*out = vp;
311*0a6a1f1dSLionel Sambuc 	char		*outp;
312*0a6a1f1dSLionel Sambuc 
313*0a6a1f1dSLionel Sambuc 	if (in == NULL || vp == NULL) {
314*0a6a1f1dSLionel Sambuc 		return 0;
315*0a6a1f1dSLionel Sambuc 	}
316*0a6a1f1dSLionel Sambuc 	for (inp = in, outp = out ; (size_t)(inp - in) < insize && (size_t)(outp - out) < outsize ; ) {
317*0a6a1f1dSLionel Sambuc 		for (wordlen = 0, i = 0 ; i < sizeof(wordin) && (size_t)(inp - in) < insize ; i++) {
318*0a6a1f1dSLionel Sambuc 			/* get a single character */
319*0a6a1f1dSLionel Sambuc 			for (v = 0; (size_t)(inp - in) <= insize && v == 0 ; ) {
320*0a6a1f1dSLionel Sambuc 				if (*inp == '\r' && *(inp + 1) == '\n') {
321*0a6a1f1dSLionel Sambuc 					inp += 2;
322*0a6a1f1dSLionel Sambuc 				} else {
323*0a6a1f1dSLionel Sambuc 					v = (uint8_t) *inp++;
324*0a6a1f1dSLionel Sambuc 					v = (uint8_t) ((v < 43 || v > 122) ? 0 : cd64[v - 43]);
325*0a6a1f1dSLionel Sambuc 					if (v) {
326*0a6a1f1dSLionel Sambuc 						v = (uint8_t) ((v == '$') ? 0 : v - 61);
327*0a6a1f1dSLionel Sambuc 					}
328*0a6a1f1dSLionel Sambuc 				}
329*0a6a1f1dSLionel Sambuc 			}
330*0a6a1f1dSLionel Sambuc 			/* perhaps 0x0 pad */
331*0a6a1f1dSLionel Sambuc 			if ((size_t)(inp - in) <= insize) {
332*0a6a1f1dSLionel Sambuc 				wordlen += 1;
333*0a6a1f1dSLionel Sambuc 				if (v) {
334*0a6a1f1dSLionel Sambuc 					wordin[i] = (uint8_t) (v - 1);
335*0a6a1f1dSLionel Sambuc 				}
336*0a6a1f1dSLionel Sambuc 			} else {
337*0a6a1f1dSLionel Sambuc 				wordin[i] = 0x0;
338*0a6a1f1dSLionel Sambuc 			}
339*0a6a1f1dSLionel Sambuc 		}
340*0a6a1f1dSLionel Sambuc 		if (wordlen > 0) {
341*0a6a1f1dSLionel Sambuc 			decodeblock(wordin, wordout);
342*0a6a1f1dSLionel Sambuc 			for (i = 0; i < wordlen - 1 ; i++) {
343*0a6a1f1dSLionel Sambuc 				*outp++ = wordout[i];
344*0a6a1f1dSLionel Sambuc 			}
345*0a6a1f1dSLionel Sambuc 		}
346*0a6a1f1dSLionel Sambuc 	}
347*0a6a1f1dSLionel Sambuc 	return (int)(outp - out);
348*0a6a1f1dSLionel Sambuc }
349*0a6a1f1dSLionel Sambuc 
350*0a6a1f1dSLionel Sambuc /* return the encoded size for n bytes input */
351*0a6a1f1dSLionel Sambuc int
b64_encsize(unsigned n)352*0a6a1f1dSLionel Sambuc b64_encsize(unsigned n)
353*0a6a1f1dSLionel Sambuc {
354*0a6a1f1dSLionel Sambuc 	return ((4 * n) / 3) + 4;
355*0a6a1f1dSLionel Sambuc }
356