Home | History | Annotate | Download | only in evp
      1 /* crypto/evp/bio_b64.c */
      2 /* Copyright (C) 1995-1998 Eric Young (eay (at) cryptsoft.com)
      3  * All rights reserved.
      4  *
      5  * This package is an SSL implementation written
      6  * by Eric Young (eay (at) 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 (at) 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 (at) 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 (at) 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 <errno.h>
     61 #include "cryptlib.h"
     62 #include <openssl/buffer.h>
     63 #include <openssl/evp.h>
     64 
     65 static int b64_write(BIO *h, const char *buf, int num);
     66 static int b64_read(BIO *h, char *buf, int size);
     67 static int b64_puts(BIO *h, const char *str);
     68 /*static int b64_gets(BIO *h, char *str, int size); */
     69 static long b64_ctrl(BIO *h, int cmd, long arg1, void *arg2);
     70 static int b64_new(BIO *h);
     71 static int b64_free(BIO *data);
     72 static long b64_callback_ctrl(BIO *h,int cmd,bio_info_cb *fp);
     73 #define B64_BLOCK_SIZE	1024
     74 #define B64_BLOCK_SIZE2	768
     75 #define B64_NONE	0
     76 #define B64_ENCODE	1
     77 #define B64_DECODE	2
     78 
     79 typedef struct b64_struct
     80 	{
     81 	/*BIO *bio; moved to the BIO structure */
     82 	int buf_len;
     83 	int buf_off;
     84 	int tmp_len;		/* used to find the start when decoding */
     85 	int tmp_nl;		/* If true, scan until '\n' */
     86 	int encode;
     87 	int start;		/* have we started decoding yet? */
     88 	int cont;		/* <= 0 when finished */
     89 	EVP_ENCODE_CTX base64;
     90 	char buf[EVP_ENCODE_LENGTH(B64_BLOCK_SIZE)+10];
     91 	char tmp[B64_BLOCK_SIZE];
     92 	} BIO_B64_CTX;
     93 
     94 static BIO_METHOD methods_b64=
     95 	{
     96 	BIO_TYPE_BASE64,"base64 encoding",
     97 	b64_write,
     98 	b64_read,
     99 	b64_puts,
    100 	NULL, /* b64_gets, */
    101 	b64_ctrl,
    102 	b64_new,
    103 	b64_free,
    104 	b64_callback_ctrl,
    105 	};
    106 
    107 BIO_METHOD *BIO_f_base64(void)
    108 	{
    109 	return(&methods_b64);
    110 	}
    111 
    112 static int b64_new(BIO *bi)
    113 	{
    114 	BIO_B64_CTX *ctx;
    115 
    116 	ctx=(BIO_B64_CTX *)OPENSSL_malloc(sizeof(BIO_B64_CTX));
    117 	if (ctx == NULL) return(0);
    118 
    119 	ctx->buf_len=0;
    120 	ctx->tmp_len=0;
    121 	ctx->tmp_nl=0;
    122 	ctx->buf_off=0;
    123 	ctx->cont=1;
    124 	ctx->start=1;
    125 	ctx->encode=0;
    126 
    127 	bi->init=1;
    128 	bi->ptr=(char *)ctx;
    129 	bi->flags=0;
    130 	bi->num = 0;
    131 	return(1);
    132 	}
    133 
    134 static int b64_free(BIO *a)
    135 	{
    136 	if (a == NULL) return(0);
    137 	OPENSSL_free(a->ptr);
    138 	a->ptr=NULL;
    139 	a->init=0;
    140 	a->flags=0;
    141 	return(1);
    142 	}
    143 
    144 static int b64_read(BIO *b, char *out, int outl)
    145 	{
    146 	int ret=0,i,ii,j,k,x,n,num,ret_code=0;
    147 	BIO_B64_CTX *ctx;
    148 	unsigned char *p,*q;
    149 
    150 	if (out == NULL) return(0);
    151 	ctx=(BIO_B64_CTX *)b->ptr;
    152 
    153 	if ((ctx == NULL) || (b->next_bio == NULL)) return(0);
    154 
    155 	BIO_clear_retry_flags(b);
    156 
    157 	if (ctx->encode != B64_DECODE)
    158 		{
    159 		ctx->encode=B64_DECODE;
    160 		ctx->buf_len=0;
    161 		ctx->buf_off=0;
    162 		ctx->tmp_len=0;
    163 		EVP_DecodeInit(&(ctx->base64));
    164 		}
    165 
    166 	/* First check if there are bytes decoded/encoded */
    167 	if (ctx->buf_len > 0)
    168 		{
    169 		OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
    170 		i=ctx->buf_len-ctx->buf_off;
    171 		if (i > outl) i=outl;
    172 		OPENSSL_assert(ctx->buf_off+i < (int)sizeof(ctx->buf));
    173 		memcpy(out,&(ctx->buf[ctx->buf_off]),i);
    174 		ret=i;
    175 		out+=i;
    176 		outl-=i;
    177 		ctx->buf_off+=i;
    178 		if (ctx->buf_len == ctx->buf_off)
    179 			{
    180 			ctx->buf_len=0;
    181 			ctx->buf_off=0;
    182 			}
    183 		}
    184 
    185 	/* At this point, we have room of outl bytes and an empty
    186 	 * buffer, so we should read in some more. */
    187 
    188 	ret_code=0;
    189 	while (outl > 0)
    190 		{
    191 		if (ctx->cont <= 0)
    192 			break;
    193 
    194 		i=BIO_read(b->next_bio,&(ctx->tmp[ctx->tmp_len]),
    195 			B64_BLOCK_SIZE-ctx->tmp_len);
    196 
    197 		if (i <= 0)
    198 			{
    199 			ret_code=i;
    200 
    201 			/* Should we continue next time we are called? */
    202 			if (!BIO_should_retry(b->next_bio))
    203 				{
    204 				ctx->cont=i;
    205 				/* If buffer empty break */
    206 				if(ctx->tmp_len == 0)
    207 					break;
    208 				/* Fall through and process what we have */
    209 				else
    210 					i = 0;
    211 				}
    212 			/* else we retry and add more data to buffer */
    213 			else
    214 				break;
    215 			}
    216 		i+=ctx->tmp_len;
    217 		ctx->tmp_len = i;
    218 
    219 		/* We need to scan, a line at a time until we
    220 		 * have a valid line if we are starting. */
    221 		if (ctx->start && (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL))
    222 			{
    223 			/* ctx->start=1; */
    224 			ctx->tmp_len=0;
    225 			}
    226 		else if (ctx->start)
    227 			{
    228 			q=p=(unsigned char *)ctx->tmp;
    229 			num = 0;
    230 			for (j=0; j<i; j++)
    231 				{
    232 				if (*(q++) != '\n') continue;
    233 
    234 				/* due to a previous very long line,
    235 				 * we need to keep on scanning for a '\n'
    236 				 * before we even start looking for
    237 				 * base64 encoded stuff. */
    238 				if (ctx->tmp_nl)
    239 					{
    240 					p=q;
    241 					ctx->tmp_nl=0;
    242 					continue;
    243 					}
    244 
    245 				k=EVP_DecodeUpdate(&(ctx->base64),
    246 					(unsigned char *)ctx->buf,
    247 					&num,p,q-p);
    248 				if ((k <= 0) && (num == 0) && (ctx->start))
    249 					EVP_DecodeInit(&ctx->base64);
    250 				else
    251 					{
    252 					if (p != (unsigned char *)
    253 						&(ctx->tmp[0]))
    254 						{
    255 						i-=(p- (unsigned char *)
    256 							&(ctx->tmp[0]));
    257 						for (x=0; x < i; x++)
    258 							ctx->tmp[x]=p[x];
    259 						}
    260 					EVP_DecodeInit(&ctx->base64);
    261 					ctx->start=0;
    262 					break;
    263 					}
    264 				p=q;
    265 				}
    266 
    267 			/* we fell off the end without starting */
    268 			if ((j == i) && (num == 0))
    269 				{
    270 				/* Is this is one long chunk?, if so, keep on
    271 				 * reading until a new line. */
    272 				if (p == (unsigned char *)&(ctx->tmp[0]))
    273 					{
    274 					/* Check buffer full */
    275 					if (i == B64_BLOCK_SIZE)
    276 						{
    277 						ctx->tmp_nl=1;
    278 						ctx->tmp_len=0;
    279 						}
    280 					}
    281 				else if (p != q) /* finished on a '\n' */
    282 					{
    283 					n=q-p;
    284 					for (ii=0; ii<n; ii++)
    285 						ctx->tmp[ii]=p[ii];
    286 					ctx->tmp_len=n;
    287 					}
    288 				/* else finished on a '\n' */
    289 				continue;
    290 				}
    291 			else
    292 			{
    293 				ctx->tmp_len=0;
    294 			}
    295 		}
    296 		else if ((i < B64_BLOCK_SIZE) && (ctx->cont > 0))
    297 		{
    298 			/* If buffer isn't full and we can retry then
    299 			 * restart to read in more data.
    300 			 */
    301 			continue;
    302 		}
    303 
    304 		if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL)
    305 			{
    306 			int z,jj;
    307 
    308 #if 0
    309 			jj=(i>>2)<<2;
    310 #else
    311 			jj = i & ~3; /* process per 4 */
    312 #endif
    313 			z=EVP_DecodeBlock((unsigned char *)ctx->buf,
    314 				(unsigned char *)ctx->tmp,jj);
    315 			if (jj > 2)
    316 				{
    317 				if (ctx->tmp[jj-1] == '=')
    318 					{
    319 					z--;
    320 					if (ctx->tmp[jj-2] == '=')
    321 						z--;
    322 					}
    323 				}
    324 			/* z is now number of output bytes and jj is the
    325 			 * number consumed */
    326 			if (jj != i)
    327 				{
    328 				memmove(ctx->tmp, &ctx->tmp[jj], i-jj);
    329 				ctx->tmp_len=i-jj;
    330 				}
    331 			ctx->buf_len=0;
    332 			if (z > 0)
    333 				{
    334 				ctx->buf_len=z;
    335 				}
    336 			i=z;
    337 			}
    338 		else
    339 			{
    340 			i=EVP_DecodeUpdate(&(ctx->base64),
    341 				(unsigned char *)ctx->buf,&ctx->buf_len,
    342 				(unsigned char *)ctx->tmp,i);
    343 			ctx->tmp_len = 0;
    344 			}
    345 		ctx->buf_off=0;
    346 		if (i < 0)
    347 			{
    348 			ret_code=0;
    349 			ctx->buf_len=0;
    350 			break;
    351 			}
    352 
    353 		if (ctx->buf_len <= outl)
    354 			i=ctx->buf_len;
    355 		else
    356 			i=outl;
    357 
    358 		memcpy(out,ctx->buf,i);
    359 		ret+=i;
    360 		ctx->buf_off=i;
    361 		if (ctx->buf_off == ctx->buf_len)
    362 			{
    363 			ctx->buf_len=0;
    364 			ctx->buf_off=0;
    365 			}
    366 		outl-=i;
    367 		out+=i;
    368 		}
    369 	/* BIO_clear_retry_flags(b); */
    370 	BIO_copy_next_retry(b);
    371 	return((ret == 0)?ret_code:ret);
    372 	}
    373 
    374 static int b64_write(BIO *b, const char *in, int inl)
    375 	{
    376 	int ret=0;
    377 	int n;
    378 	int i;
    379 	BIO_B64_CTX *ctx;
    380 
    381 	ctx=(BIO_B64_CTX *)b->ptr;
    382 	BIO_clear_retry_flags(b);
    383 
    384 	if (ctx->encode != B64_ENCODE)
    385 		{
    386 		ctx->encode=B64_ENCODE;
    387 		ctx->buf_len=0;
    388 		ctx->buf_off=0;
    389 		ctx->tmp_len=0;
    390 		EVP_EncodeInit(&(ctx->base64));
    391 		}
    392 
    393 	OPENSSL_assert(ctx->buf_off < (int)sizeof(ctx->buf));
    394 	OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf));
    395 	OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
    396 	n=ctx->buf_len-ctx->buf_off;
    397 	while (n > 0)
    398 		{
    399 		i=BIO_write(b->next_bio,&(ctx->buf[ctx->buf_off]),n);
    400 		if (i <= 0)
    401 			{
    402 			BIO_copy_next_retry(b);
    403 			return(i);
    404 			}
    405 		OPENSSL_assert(i <= n);
    406 		ctx->buf_off+=i;
    407 		OPENSSL_assert(ctx->buf_off <= (int)sizeof(ctx->buf));
    408 		OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
    409 		n-=i;
    410 		}
    411 	/* at this point all pending data has been written */
    412 	ctx->buf_off=0;
    413 	ctx->buf_len=0;
    414 
    415 	if ((in == NULL) || (inl <= 0)) return(0);
    416 
    417 	while (inl > 0)
    418 		{
    419 		n=(inl > B64_BLOCK_SIZE)?B64_BLOCK_SIZE:inl;
    420 
    421 		if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL)
    422 			{
    423 			if (ctx->tmp_len > 0)
    424 				{
    425 				OPENSSL_assert(ctx->tmp_len <= 3);
    426 				n=3-ctx->tmp_len;
    427 				/* There's a theoretical possibility for this */
    428 				if (n > inl)
    429 					n=inl;
    430 				memcpy(&(ctx->tmp[ctx->tmp_len]),in,n);
    431 				ctx->tmp_len+=n;
    432 				ret += n;
    433 				if (ctx->tmp_len < 3)
    434 					break;
    435 				ctx->buf_len=EVP_EncodeBlock((unsigned char *)ctx->buf,(unsigned char *)ctx->tmp,ctx->tmp_len);
    436 				OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf));
    437 				OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
    438 				/* Since we're now done using the temporary
    439 				   buffer, the length should be 0'd */
    440 				ctx->tmp_len=0;
    441 				}
    442 			else
    443 				{
    444 				if (n < 3)
    445 					{
    446 					memcpy(ctx->tmp,in,n);
    447 					ctx->tmp_len=n;
    448 					ret += n;
    449 					break;
    450 					}
    451 				n-=n%3;
    452 				ctx->buf_len=EVP_EncodeBlock((unsigned char *)ctx->buf,(const unsigned char *)in,n);
    453 				OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf));
    454 				OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
    455 				ret += n;
    456 				}
    457 			}
    458 		else
    459 			{
    460 			EVP_EncodeUpdate(&(ctx->base64),
    461 				(unsigned char *)ctx->buf,&ctx->buf_len,
    462 				(unsigned char *)in,n);
    463 			OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf));
    464 			OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
    465 			ret += n;
    466 			}
    467 		inl-=n;
    468 		in+=n;
    469 
    470 		ctx->buf_off=0;
    471 		n=ctx->buf_len;
    472 		while (n > 0)
    473 			{
    474 			i=BIO_write(b->next_bio,&(ctx->buf[ctx->buf_off]),n);
    475 			if (i <= 0)
    476 				{
    477 				BIO_copy_next_retry(b);
    478 				return((ret == 0)?i:ret);
    479 				}
    480 			OPENSSL_assert(i <= n);
    481 			n-=i;
    482 			ctx->buf_off+=i;
    483 			OPENSSL_assert(ctx->buf_off <= (int)sizeof(ctx->buf));
    484 			OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
    485 			}
    486 		ctx->buf_len=0;
    487 		ctx->buf_off=0;
    488 		}
    489 	return(ret);
    490 	}
    491 
    492 static long b64_ctrl(BIO *b, int cmd, long num, void *ptr)
    493 	{
    494 	BIO_B64_CTX *ctx;
    495 	long ret=1;
    496 	int i;
    497 
    498 	ctx=(BIO_B64_CTX *)b->ptr;
    499 
    500 	switch (cmd)
    501 		{
    502 	case BIO_CTRL_RESET:
    503 		ctx->cont=1;
    504 		ctx->start=1;
    505 		ctx->encode=B64_NONE;
    506 		ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
    507 		break;
    508 	case BIO_CTRL_EOF:	/* More to read */
    509 		if (ctx->cont <= 0)
    510 			ret=1;
    511 		else
    512 			ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
    513 		break;
    514 	case BIO_CTRL_WPENDING: /* More to write in buffer */
    515 		OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
    516 		ret=ctx->buf_len-ctx->buf_off;
    517 		if ((ret == 0) && (ctx->encode != B64_NONE)
    518 			&& (ctx->base64.num != 0))
    519 			ret=1;
    520 		else if (ret <= 0)
    521 			ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
    522 		break;
    523 	case BIO_CTRL_PENDING: /* More to read in buffer */
    524 		OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
    525 		ret=ctx->buf_len-ctx->buf_off;
    526 		if (ret <= 0)
    527 			ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
    528 		break;
    529 	case BIO_CTRL_FLUSH:
    530 		/* do a final write */
    531 again:
    532 		while (ctx->buf_len != ctx->buf_off)
    533 			{
    534 			i=b64_write(b,NULL,0);
    535 			if (i < 0)
    536 				return i;
    537 			}
    538 		if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL)
    539 			{
    540 			if (ctx->tmp_len != 0)
    541 				{
    542 				ctx->buf_len=EVP_EncodeBlock(
    543 					(unsigned char *)ctx->buf,
    544 					(unsigned char *)ctx->tmp,
    545 					ctx->tmp_len);
    546 				ctx->buf_off=0;
    547 				ctx->tmp_len=0;
    548 				goto again;
    549 				}
    550 			}
    551 		else if (ctx->encode != B64_NONE && ctx->base64.num != 0)
    552 			{
    553 			ctx->buf_off=0;
    554 			EVP_EncodeFinal(&(ctx->base64),
    555 				(unsigned char *)ctx->buf,
    556 				&(ctx->buf_len));
    557 			/* push out the bytes */
    558 			goto again;
    559 			}
    560 		/* Finally flush the underlying BIO */
    561 		ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
    562 		break;
    563 
    564 	case BIO_C_DO_STATE_MACHINE:
    565 		BIO_clear_retry_flags(b);
    566 		ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
    567 		BIO_copy_next_retry(b);
    568 		break;
    569 
    570 	case BIO_CTRL_DUP:
    571 		break;
    572 	case BIO_CTRL_INFO:
    573 	case BIO_CTRL_GET:
    574 	case BIO_CTRL_SET:
    575 	default:
    576 		ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
    577 		break;
    578 		}
    579 	return(ret);
    580 	}
    581 
    582 static long b64_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
    583 	{
    584 	long ret=1;
    585 
    586 	if (b->next_bio == NULL) return(0);
    587 	switch (cmd)
    588 		{
    589 	default:
    590 		ret=BIO_callback_ctrl(b->next_bio,cmd,fp);
    591 		break;
    592 		}
    593 	return(ret);
    594 	}
    595 
    596 static int b64_puts(BIO *b, const char *str)
    597 	{
    598 	return b64_write(b,str,strlen(str));
    599 	}
    600