diff options
| author | Arne Schwabe <arne@rfc2549.org> | 2012-04-16 19:21:14 +0200 | 
|---|---|---|
| committer | Arne Schwabe <arne@rfc2549.org> | 2012-04-16 19:21:14 +0200 | 
| commit | 3e4d8f433239c40311037616b1b8833a06651ae0 (patch) | |
| tree | 98ab7fce0d011d34677b0beb762d389cb5c39199 /openssl/crypto/evp/encode.c | |
Initial import
Diffstat (limited to 'openssl/crypto/evp/encode.c')
| -rw-r--r-- | openssl/crypto/evp/encode.c | 445 | 
1 files changed, 445 insertions, 0 deletions
diff --git a/openssl/crypto/evp/encode.c b/openssl/crypto/evp/encode.c new file mode 100644 index 00000000..28546a84 --- /dev/null +++ b/openssl/crypto/evp/encode.c @@ -0,0 +1,445 @@ +/* crypto/evp/encode.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + *  + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to.  The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code.  The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + *  + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + *  + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *    "This product includes cryptographic software written by + *     Eric Young (eay@cryptsoft.com)" + *    The word 'cryptographic' can be left out if the rouines from the library + *    being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from  + *    the apps directory (application code) you must include an acknowledgement: + *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + *  + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + *  + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed.  i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include <stdio.h> +#include "cryptlib.h" +#include <openssl/evp.h> + +#ifndef CHARSET_EBCDIC +#define conv_bin2ascii(a)	(data_bin2ascii[(a)&0x3f]) +#define conv_ascii2bin(a)	(data_ascii2bin[(a)&0x7f]) +#else +/* We assume that PEM encoded files are EBCDIC files + * (i.e., printable text files). Convert them here while decoding. + * When encoding, output is EBCDIC (text) format again. + * (No need for conversion in the conv_bin2ascii macro, as the + * underlying textstring data_bin2ascii[] is already EBCDIC) + */ +#define conv_bin2ascii(a)	(data_bin2ascii[(a)&0x3f]) +#define conv_ascii2bin(a)	(data_ascii2bin[os_toascii[a]&0x7f]) +#endif + +/* 64 char lines + * pad input with 0 + * left over chars are set to = + * 1 byte  => xx== + * 2 bytes => xxx= + * 3 bytes => xxxx + */ +#define BIN_PER_LINE    (64/4*3) +#define CHUNKS_PER_LINE (64/4) +#define CHAR_PER_LINE   (64+1) + +static const unsigned char data_bin2ascii[65]="ABCDEFGHIJKLMNOPQRSTUVWXYZ\ +abcdefghijklmnopqrstuvwxyz0123456789+/"; + +/* 0xF0 is a EOLN + * 0xF1 is ignore but next needs to be 0xF0 (for \r\n processing). + * 0xF2 is EOF + * 0xE0 is ignore at start of line. + * 0xFF is error + */ + +#define B64_EOLN		0xF0 +#define B64_CR			0xF1 +#define B64_EOF			0xF2 +#define B64_WS			0xE0 +#define B64_ERROR       	0xFF +#define B64_NOT_BASE64(a)	(((a)|0x13) == 0xF3) + +static const unsigned char data_ascii2bin[128]={ +	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +	0xFF,0xE0,0xF0,0xFF,0xFF,0xF1,0xFF,0xFF, +	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +	0xE0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +	0xFF,0xFF,0xFF,0x3E,0xFF,0xF2,0xFF,0x3F, +	0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B, +	0x3C,0x3D,0xFF,0xFF,0xFF,0x00,0xFF,0xFF, +	0xFF,0x00,0x01,0x02,0x03,0x04,0x05,0x06, +	0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E, +	0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16, +	0x17,0x18,0x19,0xFF,0xFF,0xFF,0xFF,0xFF, +	0xFF,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20, +	0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28, +	0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30, +	0x31,0x32,0x33,0xFF,0xFF,0xFF,0xFF,0xFF, +	}; + +void EVP_EncodeInit(EVP_ENCODE_CTX *ctx) +	{ +	ctx->length=48; +	ctx->num=0; +	ctx->line_num=0; +	} + +void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl, +	     const unsigned char *in, int inl) +	{ +	int i,j; +	unsigned int total=0; + +	*outl=0; +	if (inl == 0) return; +	OPENSSL_assert(ctx->length <= (int)sizeof(ctx->enc_data)); +	if ((ctx->num+inl) < ctx->length) +		{ +		memcpy(&(ctx->enc_data[ctx->num]),in,inl); +		ctx->num+=inl; +		return; +		} +	if (ctx->num != 0) +		{ +		i=ctx->length-ctx->num; +		memcpy(&(ctx->enc_data[ctx->num]),in,i); +		in+=i; +		inl-=i; +		j=EVP_EncodeBlock(out,ctx->enc_data,ctx->length); +		ctx->num=0; +		out+=j; +		*(out++)='\n'; +		*out='\0'; +		total=j+1; +		} +	while (inl >= ctx->length) +		{ +		j=EVP_EncodeBlock(out,in,ctx->length); +		in+=ctx->length; +		inl-=ctx->length; +		out+=j; +		*(out++)='\n'; +		*out='\0'; +		total+=j+1; +		} +	if (inl != 0) +		memcpy(&(ctx->enc_data[0]),in,inl); +	ctx->num=inl; +	*outl=total; +	} + +void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl) +	{ +	unsigned int ret=0; + +	if (ctx->num != 0) +		{ +		ret=EVP_EncodeBlock(out,ctx->enc_data,ctx->num); +		out[ret++]='\n'; +		out[ret]='\0'; +		ctx->num=0; +		} +	*outl=ret; +	} + +int EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int dlen) +	{ +	int i,ret=0; +	unsigned long l; + +	for (i=dlen; i > 0; i-=3) +		{ +		if (i >= 3) +			{ +			l=	(((unsigned long)f[0])<<16L)| +				(((unsigned long)f[1])<< 8L)|f[2]; +			*(t++)=conv_bin2ascii(l>>18L); +			*(t++)=conv_bin2ascii(l>>12L); +			*(t++)=conv_bin2ascii(l>> 6L); +			*(t++)=conv_bin2ascii(l     ); +			} +		else +			{ +			l=((unsigned long)f[0])<<16L; +			if (i == 2) l|=((unsigned long)f[1]<<8L); + +			*(t++)=conv_bin2ascii(l>>18L); +			*(t++)=conv_bin2ascii(l>>12L); +			*(t++)=(i == 1)?'=':conv_bin2ascii(l>> 6L); +			*(t++)='='; +			} +		ret+=4; +		f+=3; +		} + +	*t='\0'; +	return(ret); +	} + +void EVP_DecodeInit(EVP_ENCODE_CTX *ctx) +	{ +	ctx->length=30; +	ctx->num=0; +	ctx->line_num=0; +	ctx->expect_nl=0; +	} + +/* -1 for error + *  0 for last line + *  1 for full line + */ +int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl, +	     const unsigned char *in, int inl) +	{ +	int seof= -1,eof=0,rv= -1,ret=0,i,v,tmp,n,ln,exp_nl; +	unsigned char *d; + +	n=ctx->num; +	d=ctx->enc_data; +	ln=ctx->line_num; +	exp_nl=ctx->expect_nl; + +	/* last line of input. */ +	if ((inl == 0) || ((n == 0) && (conv_ascii2bin(in[0]) == B64_EOF))) +		{ rv=0; goto end; } +		 +	/* We parse the input data */ +	for (i=0; i<inl; i++) +		{ +		/* If the current line is > 80 characters, scream alot */ +		if (ln >= 80) { rv= -1; goto end; } + +		/* Get char and put it into the buffer */ +		tmp= *(in++); +		v=conv_ascii2bin(tmp); +		/* only save the good data :-) */ +		if (!B64_NOT_BASE64(v)) +			{ +			OPENSSL_assert(n < (int)sizeof(ctx->enc_data)); +			d[n++]=tmp; +			ln++; +			} +		else if (v == B64_ERROR) +			{ +			rv= -1; +			goto end; +			} + +		/* have we seen a '=' which is 'definitly' the last +		 * input line.  seof will point to the character that +		 * holds it. and eof will hold how many characters to +		 * chop off. */ +		if (tmp == '=') +			{ +			if (seof == -1) seof=n; +			eof++; +			} + +		if (v == B64_CR) +			{ +			ln = 0; +			if (exp_nl) +				continue; +			} + +		/* eoln */ +		if (v == B64_EOLN) +			{ +			ln=0; +			if (exp_nl) +				{ +				exp_nl=0; +				continue; +				} +			} +		exp_nl=0; + +		/* If we are at the end of input and it looks like a +		 * line, process it. */ +		if (((i+1) == inl) && (((n&3) == 0) || eof)) +			{ +			v=B64_EOF; +			/* In case things were given us in really small +			   records (so two '=' were given in separate +			   updates), eof may contain the incorrect number +			   of ending bytes to skip, so let's redo the count */ +			eof = 0; +			if (d[n-1] == '=') eof++; +			if (d[n-2] == '=') eof++; +			/* There will never be more than two '=' */ +			} + +		if ((v == B64_EOF && (n&3) == 0) || (n >= 64)) +			{ +			/* This is needed to work correctly on 64 byte input +			 * lines.  We process the line and then need to +			 * accept the '\n' */ +			if ((v != B64_EOF) && (n >= 64)) exp_nl=1; +			if (n > 0) +				{ +				v=EVP_DecodeBlock(out,d,n); +				n=0; +				if (v < 0) { rv=0; goto end; } +				ret+=(v-eof); +				} +			else +				{ +				eof=1; +				v=0; +				} + +			/* This is the case where we have had a short +			 * but valid input line */ +			if ((v < ctx->length) && eof) +				{ +				rv=0; +				goto end; +				} +			else +				ctx->length=v; + +			if (seof >= 0) { rv=0; goto end; } +			out+=v; +			} +		} +	rv=1; +end: +	*outl=ret; +	ctx->num=n; +	ctx->line_num=ln; +	ctx->expect_nl=exp_nl; +	return(rv); +	} + +int EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n) +	{ +	int i,ret=0,a,b,c,d; +	unsigned long l; + +	/* trim white space from the start of the line. */ +	while ((conv_ascii2bin(*f) == B64_WS) && (n > 0)) +		{ +		f++; +		n--; +		} + +	/* strip off stuff at the end of the line +	 * ascii2bin values B64_WS, B64_EOLN, B64_EOLN and B64_EOF */ +	while ((n > 3) && (B64_NOT_BASE64(conv_ascii2bin(f[n-1])))) +		n--; + +	if (n%4 != 0) return(-1); + +	for (i=0; i<n; i+=4) +		{ +		a=conv_ascii2bin(*(f++)); +		b=conv_ascii2bin(*(f++)); +		c=conv_ascii2bin(*(f++)); +		d=conv_ascii2bin(*(f++)); +		if (	(a & 0x80) || (b & 0x80) || +			(c & 0x80) || (d & 0x80)) +			return(-1); +		l=(	(((unsigned long)a)<<18L)| +			(((unsigned long)b)<<12L)| +			(((unsigned long)c)<< 6L)| +			(((unsigned long)d)     )); +		*(t++)=(unsigned char)(l>>16L)&0xff; +		*(t++)=(unsigned char)(l>> 8L)&0xff; +		*(t++)=(unsigned char)(l     )&0xff; +		ret+=3; +		} +	return(ret); +	} + +int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl) +	{ +	int i; + +	*outl=0; +	if (ctx->num != 0) +		{ +		i=EVP_DecodeBlock(out,ctx->enc_data,ctx->num); +		if (i < 0) return(-1); +		ctx->num=0; +		*outl=i; +		return(1); +		} +	else +		return(1); +	} + +#ifdef undef +int EVP_DecodeValid(unsigned char *buf, int len) +	{ +	int i,num=0,bad=0; + +	if (len == 0) return(-1); +	while (conv_ascii2bin(*buf) == B64_WS) +		{ +		buf++; +		len--; +		if (len == 0) return(-1); +		} + +	for (i=len; i >= 4; i-=4) +		{ +		if (	(conv_ascii2bin(buf[0]) >= 0x40) || +			(conv_ascii2bin(buf[1]) >= 0x40) || +			(conv_ascii2bin(buf[2]) >= 0x40) || +			(conv_ascii2bin(buf[3]) >= 0x40)) +			return(-1); +		buf+=4; +		num+=1+(buf[2] != '=')+(buf[3] != '='); +		} +	if ((i == 1) && (conv_ascii2bin(buf[0]) == B64_EOLN)) +		return(num); +	if ((i == 2) && (conv_ascii2bin(buf[0]) == B64_EOLN) && +		(conv_ascii2bin(buf[0]) == B64_EOLN)) +		return(num); +	return(1); +	} +#endif  | 
