1 /* crypto/evp/encode.c */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  *
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  *
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  *
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  *
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58 
59 #include <stdio.h>
60 #include "cryptlib.h"
61 #include <openssl/evp.h>
62 
63 __RCSID("$MirOS: src/lib/libssl/src/crypto/evp/encode.c,v 1.2 2014/06/05 13:26:38 tg Exp $");
64 
65 #ifndef CHARSET_EBCDIC
66 #define conv_bin2ascii(a)	(data_bin2ascii[(a)&0x3f])
67 #define conv_ascii2bin(a)	(data_ascii2bin[(a)&0x7f])
68 #else
69 /* We assume that PEM encoded files are EBCDIC files
70  * (i.e., printable text files). Convert them here while decoding.
71  * When encoding, output is EBCDIC (text) format again.
72  * (No need for conversion in the conv_bin2ascii macro, as the
73  * underlying textstring data_bin2ascii[] is already EBCDIC)
74  */
75 #define conv_bin2ascii(a)	(data_bin2ascii[(a)&0x3f])
76 #define conv_ascii2bin(a)	(data_ascii2bin[os_toascii[a]&0x7f])
77 #endif
78 
79 /* 64 char lines
80  * pad input with 0
81  * left over chars are set to =
82  * 1 byte  => xx==
83  * 2 bytes => xxx=
84  * 3 bytes => xxxx
85  */
86 #define BIN_PER_LINE    (64/4*3)
87 #define CHUNKS_PER_LINE (64/4)
88 #define CHAR_PER_LINE   (64+1)
89 
90 static unsigned char data_bin2ascii[65]="ABCDEFGHIJKLMNOPQRSTUVWXYZ\
91 abcdefghijklmnopqrstuvwxyz0123456789+/";
92 
93 /* 0xF0 is a EOLN
94  * 0xF1 is ignore but next needs to be 0xF0 (for \r\n processing).
95  * 0xF2 is EOF
96  * 0xE0 is ignore at start of line.
97  * 0xFF is error
98  */
99 
100 #define B64_EOLN		0xF0
101 #define B64_CR			0xF1
102 #define B64_EOF			0xF2
103 #define B64_WS			0xE0
104 #define B64_ERROR       	0xFF
105 #define B64_NOT_BASE64(a)	(((a)|0x13) == 0xF3)
106 
107 static unsigned char data_ascii2bin[128]={
108 	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
109 	0xFF,0xE0,0xF0,0xFF,0xFF,0xF1,0xFF,0xFF,
110 	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
111 	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
112 	0xE0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
113 	0xFF,0xFF,0xFF,0x3E,0xFF,0xF2,0xFF,0x3F,
114 	0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,
115 	0x3C,0x3D,0xFF,0xFF,0xFF,0x00,0xFF,0xFF,
116 	0xFF,0x00,0x01,0x02,0x03,0x04,0x05,0x06,
117 	0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,
118 	0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,
119 	0x17,0x18,0x19,0xFF,0xFF,0xFF,0xFF,0xFF,
120 	0xFF,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,
121 	0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,
122 	0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30,
123 	0x31,0x32,0x33,0xFF,0xFF,0xFF,0xFF,0xFF,
124 	};
125 
EVP_EncodeInit(EVP_ENCODE_CTX * ctx)126 void EVP_EncodeInit(EVP_ENCODE_CTX *ctx)
127 	{
128 	ctx->length=48;
129 	ctx->num=0;
130 	ctx->line_num=0;
131 	}
132 
EVP_EncodeUpdate(EVP_ENCODE_CTX * ctx,unsigned char * out,int * outl,unsigned char * in,int inl)133 void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
134 	     unsigned char *in, int inl)
135 	{
136 	int i,j;
137 	unsigned int total=0;
138 
139 	*outl=0;
140 	if (inl == 0) return;
141 	OPENSSL_assert(ctx->length <= sizeof ctx->enc_data);
142 	if ((ctx->num+inl) < ctx->length)
143 		{
144 		memcpy(&(ctx->enc_data[ctx->num]),in,inl);
145 		ctx->num+=inl;
146 		return;
147 		}
148 	if (ctx->num != 0)
149 		{
150 		i=ctx->length-ctx->num;
151 		memcpy(&(ctx->enc_data[ctx->num]),in,i);
152 		in+=i;
153 		inl-=i;
154 		j=EVP_EncodeBlock(out,ctx->enc_data,ctx->length);
155 		ctx->num=0;
156 		out+=j;
157 		*(out++)='\n';
158 		*out='\0';
159 		total=j+1;
160 		}
161 	while (inl >= ctx->length)
162 		{
163 		j=EVP_EncodeBlock(out,in,ctx->length);
164 		in+=ctx->length;
165 		inl-=ctx->length;
166 		out+=j;
167 		*(out++)='\n';
168 		*out='\0';
169 		total+=j+1;
170 		}
171 	if (inl != 0)
172 		memcpy(&(ctx->enc_data[0]),in,inl);
173 	ctx->num=inl;
174 	*outl=total;
175 	}
176 
EVP_EncodeFinal(EVP_ENCODE_CTX * ctx,unsigned char * out,int * outl)177 void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
178 	{
179 	unsigned int ret=0;
180 
181 	if (ctx->num != 0)
182 		{
183 		ret=EVP_EncodeBlock(out,ctx->enc_data,ctx->num);
184 		out[ret++]='\n';
185 		out[ret]='\0';
186 		ctx->num=0;
187 		}
188 	*outl=ret;
189 	}
190 
EVP_EncodeBlock(unsigned char * t,const unsigned char * f,int dlen)191 int EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int dlen)
192 	{
193 	int i,ret=0;
194 	unsigned long l;
195 
196 	for (i=dlen; i > 0; i-=3)
197 		{
198 		if (i >= 3)
199 			{
200 			l=	(((unsigned long)f[0])<<16L)|
201 				(((unsigned long)f[1])<< 8L)|f[2];
202 			*(t++)=conv_bin2ascii(l>>18L);
203 			*(t++)=conv_bin2ascii(l>>12L);
204 			*(t++)=conv_bin2ascii(l>> 6L);
205 			*(t++)=conv_bin2ascii(l     );
206 			}
207 		else
208 			{
209 			l=((unsigned long)f[0])<<16L;
210 			if (i == 2) l|=((unsigned long)f[1]<<8L);
211 
212 			*(t++)=conv_bin2ascii(l>>18L);
213 			*(t++)=conv_bin2ascii(l>>12L);
214 			*(t++)=(i == 1)?'=':conv_bin2ascii(l>> 6L);
215 			*(t++)='=';
216 			}
217 		ret+=4;
218 		f+=3;
219 		}
220 
221 	*t='\0';
222 	return(ret);
223 	}
224 
EVP_DecodeInit(EVP_ENCODE_CTX * ctx)225 void EVP_DecodeInit(EVP_ENCODE_CTX *ctx)
226 	{
227 	ctx->length=30;
228 	ctx->num=0;
229 	ctx->line_num=0;
230 	ctx->expect_nl=0;
231 	}
232 
233 /* -1 for error
234  *  0 for last line
235  *  1 for full line
236  */
EVP_DecodeUpdate(EVP_ENCODE_CTX * ctx,unsigned char * out,int * outl,unsigned char * in,int inl)237 int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
238 	     unsigned char *in, int inl)
239 	{
240 	int seof= -1,eof=0,rv= -1,ret=0,i,v,tmp,n,ln,tmp2,exp_nl;
241 	unsigned char *d;
242 
243 	n=ctx->num;
244 	d=ctx->enc_data;
245 	ln=ctx->line_num;
246 	exp_nl=ctx->expect_nl;
247 
248 	/* last line of input. */
249 	if ((inl == 0) || ((n == 0) && (conv_ascii2bin(in[0]) == B64_EOF)))
250 		{ rv=0; goto end; }
251 
252 	/* We parse the input data */
253 	for (i=0; i<inl; i++)
254 		{
255 		/* If the current line is > 80 characters, scream alot */
256 		if (ln >= 80) { rv= -1; goto end; }
257 
258 		/* Get char and put it into the buffer */
259 		tmp= *(in++);
260 		v=conv_ascii2bin(tmp);
261 		/* only save the good data :-) */
262 		if (!B64_NOT_BASE64(v))
263 			{
264 			OPENSSL_assert(n < sizeof ctx->enc_data);
265 			d[n++]=tmp;
266 			ln++;
267 			}
268 		else if (v == B64_ERROR)
269 			{
270 			rv= -1;
271 			goto end;
272 			}
273 
274 		/* have we seen a '=' which is 'definitly' the last
275 		 * input line.  seof will point to the character that
276 		 * holds it. and eof will hold how many characters to
277 		 * chop off. */
278 		if (tmp == '=')
279 			{
280 			if (seof == -1) seof=n;
281 			eof++;
282 			}
283 
284 		if (v == B64_CR)
285 			{
286 			ln = 0;
287 			if (exp_nl)
288 				continue;
289 			}
290 
291 		/* eoln */
292 		if (v == B64_EOLN)
293 			{
294 			ln=0;
295 			if (exp_nl)
296 				{
297 				exp_nl=0;
298 				continue;
299 				}
300 			}
301 		exp_nl=0;
302 
303 		/* If we are at the end of input and it looks like a
304 		 * line, process it. */
305 		if (((i+1) == inl) && (((n&3) == 0) || eof))
306 			{
307 			v=B64_EOF;
308 			/* In case things were given us in really small
309 			   records (so two '=' were given in separate
310 			   updates), eof may contain the incorrect number
311 			   of ending bytes to skip, so let's redo the count */
312 			eof = 0;
313 			if (d[n-1] == '=') eof++;
314 			if (d[n-2] == '=') eof++;
315 			/* There will never be more than two '=' */
316 			}
317 
318 		if ((v == B64_EOF && (n&3) == 0) || (n >= 64))
319 			{
320 			/* This is needed to work correctly on 64 byte input
321 			 * lines.  We process the line and then need to
322 			 * accept the '\n' */
323 			if ((v != B64_EOF) && (n >= 64)) exp_nl=1;
324 			tmp2=v;
325 			if (n > 0)
326 				{
327 				v=EVP_DecodeBlock(out,d,n);
328 				if (v < 0) { rv=0; goto end; }
329 				if (eof > v) { rv=-1; goto end; }
330 				n=0;
331 				ret+=(v-eof);
332 				}
333 			else
334 				{
335 				eof=1;
336 				v=0;
337 				}
338 
339 			/* This is the case where we have had a short
340 			 * but valid input line */
341 			if ((v < ctx->length) && eof)
342 				{
343 				rv=0;
344 				goto end;
345 				}
346 			else
347 				ctx->length=v;
348 
349 			if (seof >= 0) { rv=0; goto end; }
350 			out+=v;
351 			}
352 		}
353 	rv=1;
354 end:
355 	*outl=ret;
356 	ctx->num=n;
357 	ctx->line_num=ln;
358 	ctx->expect_nl=exp_nl;
359 	return(rv);
360 	}
361 
EVP_DecodeBlock(unsigned char * t,const unsigned char * f,int n)362 int EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n)
363 	{
364 	int i,ret=0,a,b,c,d;
365 	unsigned long l;
366 
367 	/* trim white space from the start of the line. */
368 	while ((conv_ascii2bin(*f) == B64_WS) && (n > 0))
369 		{
370 		f++;
371 		n--;
372 		}
373 
374 	/* strip off stuff at the end of the line
375 	 * ascii2bin values B64_WS, B64_EOLN, B64_EOLN and B64_EOF */
376 	while ((n > 3) && (B64_NOT_BASE64(conv_ascii2bin(f[n-1]))))
377 		n--;
378 
379 	if (n%4 != 0) return(-1);
380 
381 	for (i=0; i<n; i+=4)
382 		{
383 		a=conv_ascii2bin(*(f++));
384 		b=conv_ascii2bin(*(f++));
385 		c=conv_ascii2bin(*(f++));
386 		d=conv_ascii2bin(*(f++));
387 		if (	(a & 0x80) || (b & 0x80) ||
388 			(c & 0x80) || (d & 0x80))
389 			return(-1);
390 		l=(	(((unsigned long)a)<<18L)|
391 			(((unsigned long)b)<<12L)|
392 			(((unsigned long)c)<< 6L)|
393 			(((unsigned long)d)     ));
394 		*(t++)=(unsigned char)(l>>16L)&0xff;
395 		*(t++)=(unsigned char)(l>> 8L)&0xff;
396 		*(t++)=(unsigned char)(l     )&0xff;
397 		ret+=3;
398 		}
399 	return(ret);
400 	}
401 
EVP_DecodeFinal(EVP_ENCODE_CTX * ctx,unsigned char * out,int * outl)402 int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
403 	{
404 	int i;
405 
406 	*outl=0;
407 	if (ctx->num != 0)
408 		{
409 		i=EVP_DecodeBlock(out,ctx->enc_data,ctx->num);
410 		if (i < 0) return(-1);
411 		ctx->num=0;
412 		*outl=i;
413 		return(1);
414 		}
415 	else
416 		return(1);
417 	}
418 
419 #ifdef undef
EVP_DecodeValid(unsigned char * buf,int len)420 int EVP_DecodeValid(unsigned char *buf, int len)
421 	{
422 	int i,num=0,bad=0;
423 
424 	if (len == 0) return(-1);
425 	while (conv_ascii2bin(*buf) == B64_WS)
426 		{
427 		buf++;
428 		len--;
429 		if (len == 0) return(-1);
430 		}
431 
432 	for (i=len; i >= 4; i-=4)
433 		{
434 		if (	(conv_ascii2bin(buf[0]) >= 0x40) ||
435 			(conv_ascii2bin(buf[1]) >= 0x40) ||
436 			(conv_ascii2bin(buf[2]) >= 0x40) ||
437 			(conv_ascii2bin(buf[3]) >= 0x40))
438 			return(-1);
439 		buf+=4;
440 		num+=1+(buf[2] != '=')+(buf[3] != '=');
441 		}
442 	if ((i == 1) && (conv_ascii2bin(buf[0]) == B64_EOLN))
443 		return(num);
444 	if ((i == 2) && (conv_ascii2bin(buf[0]) == B64_EOLN) &&
445 		(conv_ascii2bin(buf[0]) == B64_EOLN))
446 		return(num);
447 	return(1);
448 	}
449 #endif
450