ssl/libcrypto/src/crypto/evp/encode.c
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     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  © Portions copyright (c) 2006 Nokia Corporation.  All rights reserved.
       
    60  */
       
    61 
       
    62 
       
    63 #include <stdio.h>
       
    64 #include "cryptlib.h"
       
    65 #include <openssl/evp.h>
       
    66 #if (defined(SYMBIAN) && (defined(__WINSCW__) || defined(__WINS__)))
       
    67 #include "libcrypto_wsd_macros.h"
       
    68 #include "libcrypto_wsd.h"
       
    69 #endif
       
    70 
       
    71 #ifndef CHARSET_EBCDIC
       
    72 #define conv_bin2ascii(a)	(data_bin2ascii[(a)&0x3f])
       
    73 #define conv_ascii2bin(a)	(data_ascii2bin[(a)&0x7f])
       
    74 #else
       
    75 /* We assume that PEM encoded files are EBCDIC files
       
    76  * (i.e., printable text files). Convert them here while decoding.
       
    77  * When encoding, output is EBCDIC (text) format again.
       
    78  * (No need for conversion in the conv_bin2ascii macro, as the
       
    79  * underlying textstring data_bin2ascii[] is already EBCDIC)
       
    80  */
       
    81 #define conv_bin2ascii(a)	(data_bin2ascii[(a)&0x3f])
       
    82 #define conv_ascii2bin(a)	(data_ascii2bin[os_toascii[a]&0x7f])
       
    83 #endif
       
    84 
       
    85 /* 64 char lines
       
    86  * pad input with 0
       
    87  * left over chars are set to =
       
    88  * 1 byte  => xx==
       
    89  * 2 bytes => xxx=
       
    90  * 3 bytes => xxxx
       
    91  */
       
    92 #define BIN_PER_LINE    (64/4*3)
       
    93 #define CHUNKS_PER_LINE (64/4)
       
    94 #define CHAR_PER_LINE   (64+1)
       
    95 
       
    96 #ifndef EMULATOR
       
    97 static unsigned char data_bin2ascii[65]="ABCDEFGHIJKLMNOPQRSTUVWXYZ\
       
    98 abcdefghijklmnopqrstuvwxyz0123456789+/";
       
    99 #else
       
   100 static const unsigned char data_bin2ascii[65]="ABCDEFGHIJKLMNOPQRSTUVWXYZ\
       
   101 abcdefghijklmnopqrstuvwxyz0123456789+/";
       
   102 #endif
       
   103 
       
   104 /* 0xF0 is a EOLN
       
   105  * 0xF1 is ignore but next needs to be 0xF0 (for \r\n processing).
       
   106  * 0xF2 is EOF
       
   107  * 0xE0 is ignore at start of line.
       
   108  * 0xFF is error
       
   109  */
       
   110 
       
   111 #define B64_EOLN		0xF0
       
   112 #define B64_CR			0xF1
       
   113 #define B64_EOF			0xF2
       
   114 #define B64_WS			0xE0
       
   115 #define B64_ERROR       	0xFF
       
   116 #define B64_NOT_BASE64(a)	(((a)|0x13) == 0xF3)
       
   117 
       
   118 #ifndef EMULATOR
       
   119 static unsigned char data_ascii2bin[128]={
       
   120 	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
       
   121 	0xFF,0xE0,0xF0,0xFF,0xFF,0xF1,0xFF,0xFF,
       
   122 	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
       
   123 	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
       
   124 	0xE0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
       
   125 	0xFF,0xFF,0xFF,0x3E,0xFF,0xF2,0xFF,0x3F,
       
   126 	0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,
       
   127 	0x3C,0x3D,0xFF,0xFF,0xFF,0x00,0xFF,0xFF,
       
   128 	0xFF,0x00,0x01,0x02,0x03,0x04,0x05,0x06,
       
   129 	0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,
       
   130 	0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,
       
   131 	0x17,0x18,0x19,0xFF,0xFF,0xFF,0xFF,0xFF,
       
   132 	0xFF,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,
       
   133 	0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,
       
   134 	0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30,
       
   135 	0x31,0x32,0x33,0xFF,0xFF,0xFF,0xFF,0xFF,
       
   136 	};
       
   137 
       
   138 #else
       
   139 static const unsigned char data_ascii2bin[128]={
       
   140 	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
       
   141 	0xFF,0xE0,0xF0,0xFF,0xFF,0xF1,0xFF,0xFF,
       
   142 	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
       
   143 	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
       
   144 	0xE0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
       
   145 	0xFF,0xFF,0xFF,0x3E,0xFF,0xF2,0xFF,0x3F,
       
   146 	0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,
       
   147 	0x3C,0x3D,0xFF,0xFF,0xFF,0x00,0xFF,0xFF,
       
   148 	0xFF,0x00,0x01,0x02,0x03,0x04,0x05,0x06,
       
   149 	0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,
       
   150 	0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,
       
   151 	0x17,0x18,0x19,0xFF,0xFF,0xFF,0xFF,0xFF,
       
   152 	0xFF,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,
       
   153 	0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,
       
   154 	0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30,
       
   155 	0x31,0x32,0x33,0xFF,0xFF,0xFF,0xFF,0xFF,
       
   156 	};
       
   157 #endif	
       
   158 
       
   159 EXPORT_C void EVP_EncodeInit(EVP_ENCODE_CTX *ctx)
       
   160 	{
       
   161 	ctx->length=48;
       
   162 	ctx->num=0;
       
   163 	ctx->line_num=0;
       
   164 	}
       
   165 
       
   166 EXPORT_C void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
       
   167 	     const unsigned char *in, int inl)
       
   168 	{
       
   169 	int i,j;
       
   170 	unsigned int total=0;
       
   171 
       
   172 	*outl=0;
       
   173 	if (inl == 0) return;
       
   174 	OPENSSL_assert(ctx->length <= (int)sizeof(ctx->enc_data));
       
   175 	if ((ctx->num+inl) < ctx->length)
       
   176 		{
       
   177 		memcpy(&(ctx->enc_data[ctx->num]),in,inl);
       
   178 		ctx->num+=inl;
       
   179 		return;
       
   180 		}
       
   181 	if (ctx->num != 0)
       
   182 		{
       
   183 		i=ctx->length-ctx->num;
       
   184 		memcpy(&(ctx->enc_data[ctx->num]),in,i);
       
   185 		in+=i;
       
   186 		inl-=i;
       
   187 		j=EVP_EncodeBlock(out,ctx->enc_data,ctx->length);
       
   188 		ctx->num=0;
       
   189 		out+=j;
       
   190 		*(out++)='\n';
       
   191 		*out='\0';
       
   192 		total=j+1;
       
   193 		}
       
   194 	while (inl >= ctx->length)
       
   195 		{
       
   196 		j=EVP_EncodeBlock(out,in,ctx->length);
       
   197 		in+=ctx->length;
       
   198 		inl-=ctx->length;
       
   199 		out+=j;
       
   200 		*(out++)='\n';
       
   201 		*out='\0';
       
   202 		total+=j+1;
       
   203 		}
       
   204 	if (inl != 0)
       
   205 		memcpy(&(ctx->enc_data[0]),in,inl);
       
   206 	ctx->num=inl;
       
   207 	*outl=total;
       
   208 	}
       
   209 
       
   210 EXPORT_C void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
       
   211 	{
       
   212 	unsigned int ret=0;
       
   213 
       
   214 	if (ctx->num != 0)
       
   215 		{
       
   216 		ret=EVP_EncodeBlock(out,ctx->enc_data,ctx->num);
       
   217 		out[ret++]='\n';
       
   218 		out[ret]='\0';
       
   219 		ctx->num=0;
       
   220 		}
       
   221 	*outl=ret;
       
   222 	}
       
   223 
       
   224 EXPORT_C int EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int dlen)
       
   225 	{
       
   226 	int i,ret=0;
       
   227 	unsigned long l;
       
   228 
       
   229 	for (i=dlen; i > 0; i-=3)
       
   230 		{
       
   231 		if (i >= 3)
       
   232 			{
       
   233 			l=	(((unsigned long)f[0])<<16L)|
       
   234 				(((unsigned long)f[1])<< 8L)|f[2];
       
   235 			*(t++)=conv_bin2ascii(l>>18L);
       
   236 			*(t++)=conv_bin2ascii(l>>12L);
       
   237 			*(t++)=conv_bin2ascii(l>> 6L);
       
   238 			*(t++)=conv_bin2ascii(l     );
       
   239 			}
       
   240 		else
       
   241 			{
       
   242 			l=((unsigned long)f[0])<<16L;
       
   243 			if (i == 2) l|=((unsigned long)f[1]<<8L);
       
   244 
       
   245 			*(t++)=conv_bin2ascii(l>>18L);
       
   246 			*(t++)=conv_bin2ascii(l>>12L);
       
   247 			*(t++)=(i == 1)?'=':conv_bin2ascii(l>> 6L);
       
   248 			*(t++)='=';
       
   249 			}
       
   250 		ret+=4;
       
   251 		f+=3;
       
   252 		}
       
   253 
       
   254 	*t='\0';
       
   255 	return(ret);
       
   256 	}
       
   257 
       
   258 EXPORT_C void EVP_DecodeInit(EVP_ENCODE_CTX *ctx)
       
   259 	{
       
   260 	ctx->length=30;
       
   261 	ctx->num=0;
       
   262 	ctx->line_num=0;
       
   263 	ctx->expect_nl=0;
       
   264 	}
       
   265 
       
   266 /* -1 for error
       
   267  *  0 for last line
       
   268  *  1 for full line
       
   269  */
       
   270 EXPORT_C int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
       
   271 	     const unsigned char *in, int inl)
       
   272 	{
       
   273 	int seof= -1,eof=0,rv= -1,ret=0,i,v,tmp,n,ln,tmp2,exp_nl;
       
   274 	unsigned char *d;
       
   275 
       
   276 	n=ctx->num;
       
   277 	d=ctx->enc_data;
       
   278 	ln=ctx->line_num;
       
   279 	exp_nl=ctx->expect_nl;
       
   280 
       
   281 	/* last line of input. */
       
   282 	if ((inl == 0) || ((n == 0) && (conv_ascii2bin(in[0]) == B64_EOF)))
       
   283 		{ rv=0; goto end; }
       
   284 		
       
   285 	/* We parse the input data */
       
   286 	for (i=0; i<inl; i++)
       
   287 		{
       
   288 		/* If the current line is > 80 characters, scream alot */
       
   289 		if (ln >= 80) { rv= -1; goto end; }
       
   290 
       
   291 		/* Get char and put it into the buffer */
       
   292 		tmp= *(in++);
       
   293 		v=conv_ascii2bin(tmp);
       
   294 		/* only save the good data :-) */
       
   295 		if (!B64_NOT_BASE64(v))
       
   296 			{
       
   297 			OPENSSL_assert(n < (int)sizeof(ctx->enc_data));
       
   298 			d[n++]=tmp;
       
   299 			ln++;
       
   300 			}
       
   301 		else if (v == B64_ERROR)
       
   302 			{
       
   303 			rv= -1;
       
   304 			goto end;
       
   305 			}
       
   306 
       
   307 		/* have we seen a '=' which is 'definitly' the last
       
   308 		 * input line.  seof will point to the character that
       
   309 		 * holds it. and eof will hold how many characters to
       
   310 		 * chop off. */
       
   311 		if (tmp == '=')
       
   312 			{
       
   313 			if (seof == -1) seof=n;
       
   314 			eof++;
       
   315 			}
       
   316 
       
   317 		if (v == B64_CR)
       
   318 			{
       
   319 			ln = 0;
       
   320 			if (exp_nl)
       
   321 				continue;
       
   322 			}
       
   323 
       
   324 		/* eoln */
       
   325 		if (v == B64_EOLN)
       
   326 			{
       
   327 			ln=0;
       
   328 			if (exp_nl)
       
   329 				{
       
   330 				exp_nl=0;
       
   331 				continue;
       
   332 				}
       
   333 			}
       
   334 		exp_nl=0;
       
   335 
       
   336 		/* If we are at the end of input and it looks like a
       
   337 		 * line, process it. */
       
   338 		if (((i+1) == inl) && (((n&3) == 0) || eof))
       
   339 			{
       
   340 			v=B64_EOF;
       
   341 			/* In case things were given us in really small
       
   342 			   records (so two '=' were given in separate
       
   343 			   updates), eof may contain the incorrect number
       
   344 			   of ending bytes to skip, so let's redo the count */
       
   345 			eof = 0;
       
   346 			if (d[n-1] == '=') eof++;
       
   347 			if (d[n-2] == '=') eof++;
       
   348 			/* There will never be more than two '=' */
       
   349 			}
       
   350 
       
   351 		if ((v == B64_EOF && (n&3) == 0) || (n >= 64))
       
   352 			{
       
   353 			/* This is needed to work correctly on 64 byte input
       
   354 			 * lines.  We process the line and then need to
       
   355 			 * accept the '\n' */
       
   356 			if ((v != B64_EOF) && (n >= 64)) exp_nl=1;
       
   357 			tmp2=v;
       
   358 			if (n > 0)
       
   359 				{
       
   360 				v=EVP_DecodeBlock(out,d,n);
       
   361 				n=0;
       
   362 				if (v < 0) { rv=0; goto end; }
       
   363 				ret+=(v-eof);
       
   364 				}
       
   365 			else
       
   366 				{
       
   367 				eof=1;
       
   368 				v=0;
       
   369 				}
       
   370 
       
   371 			/* This is the case where we have had a short
       
   372 			 * but valid input line */
       
   373 			if ((v < ctx->length) && eof)
       
   374 				{
       
   375 				rv=0;
       
   376 				goto end;
       
   377 				}
       
   378 			else
       
   379 				ctx->length=v;
       
   380 
       
   381 			if (seof >= 0) { rv=0; goto end; }
       
   382 			out+=v;
       
   383 			}
       
   384 		}
       
   385 	rv=1;
       
   386 end:
       
   387 	*outl=ret;
       
   388 	ctx->num=n;
       
   389 	ctx->line_num=ln;
       
   390 	ctx->expect_nl=exp_nl;
       
   391 	return(rv);
       
   392 	}
       
   393 
       
   394 EXPORT_C int EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n)
       
   395 	{
       
   396 	int i,ret=0,a,b,c,d;
       
   397 	unsigned long l;
       
   398 
       
   399 	/* trim white space from the start of the line. */
       
   400 	while ((conv_ascii2bin(*f) == B64_WS) && (n > 0))
       
   401 		{
       
   402 		f++;
       
   403 		n--;
       
   404 		}
       
   405 
       
   406 	/* strip off stuff at the end of the line
       
   407 	 * ascii2bin values B64_WS, B64_EOLN, B64_EOLN and B64_EOF */
       
   408 	while ((n > 3) && (B64_NOT_BASE64(conv_ascii2bin(f[n-1]))))
       
   409 		n--;
       
   410 
       
   411 	if (n%4 != 0) return(-1);
       
   412 
       
   413 	for (i=0; i<n; i+=4)
       
   414 		{
       
   415 		a=conv_ascii2bin(*(f++));
       
   416 		b=conv_ascii2bin(*(f++));
       
   417 		c=conv_ascii2bin(*(f++));
       
   418 		d=conv_ascii2bin(*(f++));
       
   419 		if (	(a & 0x80) || (b & 0x80) ||
       
   420 			(c & 0x80) || (d & 0x80))
       
   421 			return(-1);
       
   422 		l=(	(((unsigned long)a)<<18L)|
       
   423 			(((unsigned long)b)<<12L)|
       
   424 			(((unsigned long)c)<< 6L)|
       
   425 			(((unsigned long)d)     ));
       
   426 		*(t++)=(unsigned char)(l>>16L)&0xff;
       
   427 		*(t++)=(unsigned char)(l>> 8L)&0xff;
       
   428 		*(t++)=(unsigned char)(l     )&0xff;
       
   429 		ret+=3;
       
   430 		}
       
   431 	return(ret);
       
   432 	}
       
   433 
       
   434 EXPORT_C int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
       
   435 	{
       
   436 	int i;
       
   437 
       
   438 	*outl=0;
       
   439 	if (ctx->num != 0)
       
   440 		{
       
   441 		i=EVP_DecodeBlock(out,ctx->enc_data,ctx->num);
       
   442 		if (i < 0) return(-1);
       
   443 		ctx->num=0;
       
   444 		*outl=i;
       
   445 		return(1);
       
   446 		}
       
   447 	else
       
   448 		return(1);
       
   449 	}
       
   450 
       
   451 #ifdef undef
       
   452 EXPORT_C int EVP_DecodeValid(unsigned char *buf, int len)
       
   453 	{
       
   454 	int i,num=0,bad=0;
       
   455 
       
   456 	if (len == 0) return(-1);
       
   457 	while (conv_ascii2bin(*buf) == B64_WS)
       
   458 		{
       
   459 		buf++;
       
   460 		len--;
       
   461 		if (len == 0) return(-1);
       
   462 		}
       
   463 
       
   464 	for (i=len; i >= 4; i-=4)
       
   465 		{
       
   466 		if (	(conv_ascii2bin(buf[0]) >= 0x40) ||
       
   467 			(conv_ascii2bin(buf[1]) >= 0x40) ||
       
   468 			(conv_ascii2bin(buf[2]) >= 0x40) ||
       
   469 			(conv_ascii2bin(buf[3]) >= 0x40))
       
   470 			return(-1);
       
   471 		buf+=4;
       
   472 		num+=1+(buf[2] != '=')+(buf[3] != '=');
       
   473 		}
       
   474 	if ((i == 1) && (conv_ascii2bin(buf[0]) == B64_EOLN))
       
   475 		return(num);
       
   476 	if ((i == 2) && (conv_ascii2bin(buf[0]) == B64_EOLN) &&
       
   477 		(conv_ascii2bin(buf[0]) == B64_EOLN))
       
   478 		return(num);
       
   479 	return(1);
       
   480 	}
       
   481 #endif