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