bio_b64.c revision 59191
11638Srgrimes/* crypto/evp/bio_b64.c */ 21638Srgrimes/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 31638Srgrimes * All rights reserved. 41638Srgrimes * 51638Srgrimes * This package is an SSL implementation written 61638Srgrimes * by Eric Young (eay@cryptsoft.com). 71638Srgrimes * The implementation was written so as to conform with Netscapes SSL. 81638Srgrimes * 91638Srgrimes * This library is free for commercial and non-commercial use as long as 101638Srgrimes * the following conditions are aheared to. The following conditions 111638Srgrimes * apply to all code found in this distribution, be it the RC4, RSA, 121638Srgrimes * lhash, DES, etc., code; not just the SSL code. The SSL documentation 131638Srgrimes * included with this distribution is covered by the same copyright terms 141638Srgrimes * except that the holder is Tim Hudson (tjh@cryptsoft.com). 151638Srgrimes * 161638Srgrimes * Copyright remains Eric Young's, and as such any Copyright notices in 171638Srgrimes * the code are not to be removed. 181638Srgrimes * If this package is used in a product, Eric Young should be given attribution 191638Srgrimes * as the author of the parts of the library used. 201638Srgrimes * This can be in the form of a textual message at program startup or 211638Srgrimes * in documentation (online or textual) provided with the package. 221638Srgrimes * 231638Srgrimes * Redistribution and use in source and binary forms, with or without 241638Srgrimes * modification, are permitted provided that the following conditions 251638Srgrimes * are met: 261638Srgrimes * 1. Redistributions of source code must retain the copyright 271638Srgrimes * notice, this list of conditions and the following disclaimer. 281638Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 291638Srgrimes * notice, this list of conditions and the following disclaimer in the 301638Srgrimes * documentation and/or other materials provided with the distribution. 311638Srgrimes * 3. All advertising materials mentioning features or use of this software 321638Srgrimes * must display the following acknowledgement: 331638Srgrimes * "This product includes cryptographic software written by 34108533Sschweikh * Eric Young (eay@cryptsoft.com)" 35108533Sschweikh * The word 'cryptographic' can be left out if the rouines from the library 361638Srgrimes * being used are not cryptographic related :-). 371638Srgrimes * 4. If you include any Windows specific code (or a derivative thereof) from 381638Srgrimes * the apps directory (application code) you must include an acknowledgement: 391638Srgrimes * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 401638Srgrimes * 411638Srgrimes * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 421638Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 431638Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 441638Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 451638Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 461638Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 471638Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 481638Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 491638Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 501638Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 511638Srgrimes * SUCH DAMAGE. 521638Srgrimes * 531638Srgrimes * The licence and distribution terms for any publically available version or 5445319Sgrog * derivative of this code cannot be changed. i.e. this code cannot simply be 5545319Sgrog * copied and put under another distribution licence 5645319Sgrog * [including the GNU Public Licence.] 571638Srgrimes */ 581638Srgrimes 591638Srgrimes#include <stdio.h> 60108533Sschweikh#include <errno.h> 611638Srgrimes#include "cryptlib.h" 621638Srgrimes#include <openssl/buffer.h> 631638Srgrimes#include <openssl/evp.h> 641638Srgrimes 651638Srgrimesstatic int b64_write(BIO *h,char *buf,int num); 661638Srgrimesstatic int b64_read(BIO *h,char *buf,int size); 671638Srgrimes/*static int b64_puts(BIO *h,char *str); */ 681638Srgrimes/*static int b64_gets(BIO *h,char *str,int size); */ 691638Srgrimesstatic long b64_ctrl(BIO *h,int cmd,long arg1,char *arg2); 701638Srgrimesstatic int b64_new(BIO *h); 711638Srgrimesstatic int b64_free(BIO *data); 721638Srgrimesstatic long b64_callback_ctrl(BIO *h,int cmd,void (*fp)()); 731638Srgrimes#define B64_BLOCK_SIZE 1024 741638Srgrimes#define B64_BLOCK_SIZE2 768 751638Srgrimes#define B64_NONE 0 761638Srgrimes#define B64_ENCODE 1 771638Srgrimes#define B64_DECODE 2 781638Srgrimes 791638Srgrimestypedef struct b64_struct 801638Srgrimes { 811638Srgrimes /*BIO *bio; moved to the BIO structure */ 821638Srgrimes int buf_len; 831638Srgrimes int buf_off; 841638Srgrimes int tmp_len; /* used to find the start when decoding */ 85108533Sschweikh int tmp_nl; /* If true, scan until '\n' */ 861638Srgrimes int encode; 871638Srgrimes int start; /* have we started decoding yet? */ 881638Srgrimes int cont; /* <= 0 when finished */ 891638Srgrimes EVP_ENCODE_CTX base64; 901638Srgrimes char buf[EVP_ENCODE_LENGTH(B64_BLOCK_SIZE)+10]; 911638Srgrimes char tmp[B64_BLOCK_SIZE]; 921638Srgrimes } BIO_B64_CTX; 931638Srgrimes 941638Srgrimesstatic BIO_METHOD methods_b64= 951638Srgrimes { 961638Srgrimes BIO_TYPE_BASE64,"base64 encoding", 971638Srgrimes b64_write, 981638Srgrimes b64_read, 991638Srgrimes NULL, /* b64_puts, */ 1001638Srgrimes NULL, /* b64_gets, */ 1011638Srgrimes b64_ctrl, 1021638Srgrimes b64_new, 1031638Srgrimes b64_free, 1041638Srgrimes b64_callback_ctrl, 1051638Srgrimes }; 1061638Srgrimes 1071638SrgrimesBIO_METHOD *BIO_f_base64(void) 1081638Srgrimes { 1091638Srgrimes return(&methods_b64); 1101638Srgrimes } 1111638Srgrimes 1121638Srgrimesstatic int b64_new(BIO *bi) 1131638Srgrimes { 114108533Sschweikh BIO_B64_CTX *ctx; 1151638Srgrimes 1161638Srgrimes ctx=(BIO_B64_CTX *)Malloc(sizeof(BIO_B64_CTX)); 1171638Srgrimes if (ctx == NULL) return(0); 1181638Srgrimes 1191638Srgrimes ctx->buf_len=0; 1201638Srgrimes ctx->tmp_len=0; 1211638Srgrimes ctx->tmp_nl=0; 1221638Srgrimes ctx->buf_off=0; 1231638Srgrimes ctx->cont=1; 1241638Srgrimes ctx->start=1; 1251638Srgrimes ctx->encode=0; 1261638Srgrimes 1271638Srgrimes bi->init=1; 1281638Srgrimes bi->ptr=(char *)ctx; 1291638Srgrimes bi->flags=0; 1301638Srgrimes return(1); 1311638Srgrimes } 1321638Srgrimes 1331638Srgrimesstatic int b64_free(BIO *a) 1341638Srgrimes { 1351638Srgrimes if (a == NULL) return(0); 136108533Sschweikh Free(a->ptr); 1371638Srgrimes a->ptr=NULL; 1381638Srgrimes a->init=0; 1391638Srgrimes a->flags=0; 1401638Srgrimes return(1); 1411638Srgrimes } 1421638Srgrimes 1431638Srgrimesstatic int b64_read(BIO *b, char *out, int outl) 1441638Srgrimes { 1451638Srgrimes int ret=0,i,ii,j,k,x,n,num,ret_code=0; 1461638Srgrimes BIO_B64_CTX *ctx; 1471638Srgrimes unsigned char *p,*q; 1481638Srgrimes 1491638Srgrimes if (out == NULL) return(0); 1501638Srgrimes ctx=(BIO_B64_CTX *)b->ptr; 1511638Srgrimes 1521638Srgrimes if ((ctx == NULL) || (b->next_bio == NULL)) return(0); 1531638Srgrimes 1541638Srgrimes if (ctx->encode != B64_DECODE) 1551638Srgrimes { 1561638Srgrimes ctx->encode=B64_DECODE; 1571638Srgrimes ctx->buf_len=0; 1581638Srgrimes ctx->buf_off=0; 1591638Srgrimes ctx->tmp_len=0; 1601638Srgrimes EVP_DecodeInit(&(ctx->base64)); 1611638Srgrimes } 1621638Srgrimes 1631638Srgrimes /* First check if there are bytes decoded/encoded */ 1641638Srgrimes if (ctx->buf_len > 0) 1651638Srgrimes { 1661638Srgrimes i=ctx->buf_len-ctx->buf_off; 1671638Srgrimes if (i > outl) i=outl; 1681638Srgrimes memcpy(out,&(ctx->buf[ctx->buf_off]),i); 1691638Srgrimes ret=i; 1701638Srgrimes out+=i; 1711638Srgrimes outl-=i; 1721638Srgrimes ctx->buf_off+=i; 1731638Srgrimes if (ctx->buf_len == ctx->buf_off) 1741638Srgrimes { 1751638Srgrimes ctx->buf_len=0; 1761638Srgrimes ctx->buf_off=0; 1771638Srgrimes } 1781638Srgrimes } 1791638Srgrimes 1801638Srgrimes /* At this point, we have room of outl bytes and an empty 1811638Srgrimes * buffer, so we should read in some more. */ 1821638Srgrimes 1831638Srgrimes ret_code=0; 1841638Srgrimes while (outl > 0) 1851638Srgrimes { 1861638Srgrimes if (ctx->cont <= 0) break; 1871638Srgrimes 1881638Srgrimes i=BIO_read(b->next_bio,&(ctx->tmp[ctx->tmp_len]), 1891638Srgrimes B64_BLOCK_SIZE-ctx->tmp_len); 1901638Srgrimes 1911638Srgrimes if (i <= 0) 1921638Srgrimes { 1931638Srgrimes ret_code=i; 1941638Srgrimes 1951638Srgrimes /* Should be continue next time we are called? */ 1961638Srgrimes if (!BIO_should_retry(b->next_bio)) 1971638Srgrimes ctx->cont=i; 1981638Srgrimes /* else we should continue when called again */ 1991638Srgrimes break; 2001638Srgrimes } 2011638Srgrimes i+=ctx->tmp_len; 202108533Sschweikh 2031638Srgrimes /* We need to scan, a line at a time until we 2041638Srgrimes * have a valid line if we are starting. */ 2051638Srgrimes if (ctx->start && (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL)) 2061638Srgrimes { 2071638Srgrimes /* ctx->start=1; */ 2081638Srgrimes ctx->tmp_len=0; 2091638Srgrimes } 2101638Srgrimes else if (ctx->start) 2111638Srgrimes { 2121638Srgrimes q=p=(unsigned char *)ctx->tmp; 2131638Srgrimes for (j=0; j<i; j++) 2141638Srgrimes { 2151638Srgrimes if (*(q++) != '\n') continue; 2161638Srgrimes 2171638Srgrimes /* due to a previous very long line, 2181638Srgrimes * we need to keep on scanning for a '\n' 2191638Srgrimes * before we even start looking for 2201638Srgrimes * base64 encoded stuff. */ 2211638Srgrimes if (ctx->tmp_nl) 2221638Srgrimes { 2231638Srgrimes p=q; 2241638Srgrimes ctx->tmp_nl=0; 2251638Srgrimes continue; 2261638Srgrimes } 2271638Srgrimes 2281638Srgrimes k=EVP_DecodeUpdate(&(ctx->base64), 2291638Srgrimes (unsigned char *)ctx->buf, 2301638Srgrimes &num,p,q-p); 2311638Srgrimes if ((k <= 0) && (num == 0) && (ctx->start)) 2321638Srgrimes EVP_DecodeInit(&ctx->base64); 2331638Srgrimes else 2341638Srgrimes { 2351638Srgrimes if (p != (unsigned char *) 2361638Srgrimes &(ctx->tmp[0])) 2371638Srgrimes { 2381638Srgrimes i-=(p- (unsigned char *) 2391638Srgrimes &(ctx->tmp[0])); 2401638Srgrimes for (x=0; x < i; x++) 2411638Srgrimes ctx->tmp[x]=p[x]; 2421638Srgrimes } 2431638Srgrimes EVP_DecodeInit(&ctx->base64); 2441638Srgrimes ctx->start=0; 2451638Srgrimes break; 2461638Srgrimes } 2471638Srgrimes p=q; 2481638Srgrimes } 2491638Srgrimes 2501638Srgrimes /* we fell off the end without starting */ 2511638Srgrimes if (j == i) 2521638Srgrimes { 2531638Srgrimes /* Is this is one long chunk?, if so, keep on 2541638Srgrimes * reading until a new line. */ 2551638Srgrimes if (p == (unsigned char *)&(ctx->tmp[0])) 2561638Srgrimes { 2571638Srgrimes ctx->tmp_nl=1; 2581638Srgrimes ctx->tmp_len=0; 2591638Srgrimes } 2601638Srgrimes else if (p != q) /* finished on a '\n' */ 261108533Sschweikh { 2621638Srgrimes n=q-p; 2631638Srgrimes for (ii=0; ii<n; ii++) 2641638Srgrimes ctx->tmp[ii]=p[ii]; 2651638Srgrimes ctx->tmp_len=n; 2661638Srgrimes } 2671638Srgrimes /* else finished on a '\n' */ 2681638Srgrimes continue; 2691638Srgrimes } 2701638Srgrimes else 2711638Srgrimes ctx->tmp_len=0; 2721638Srgrimes } 2731638Srgrimes 2741638Srgrimes if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) 2751638Srgrimes { 2761638Srgrimes int z,jj; 2771638Srgrimes 2781638Srgrimes jj=(i>>2)<<2; 279108533Sschweikh z=EVP_DecodeBlock((unsigned char *)ctx->buf, 2801638Srgrimes (unsigned char *)ctx->tmp,jj); 2811638Srgrimes if (jj > 2) 2821638Srgrimes { 2831638Srgrimes if (ctx->tmp[jj-1] == '=') 2841638Srgrimes { 2851638Srgrimes z--; 2861638Srgrimes if (ctx->tmp[jj-2] == '=') 2871638Srgrimes z--; 2881638Srgrimes } 2891638Srgrimes } 2901638Srgrimes /* z is now number of output bytes and jj is the 2911638Srgrimes * number consumed */ 2921638Srgrimes if (jj != i) 2931638Srgrimes { 2941638Srgrimes memcpy((unsigned char *)ctx->tmp, 2951638Srgrimes (unsigned char *)&(ctx->tmp[jj]),i-jj); 2961638Srgrimes ctx->tmp_len=i-jj; 2971638Srgrimes } 2981638Srgrimes ctx->buf_len=0; 2991638Srgrimes if (z > 0) 3001638Srgrimes { 3011638Srgrimes ctx->buf_len=z; 3021638Srgrimes i=1; 3031638Srgrimes } 3041638Srgrimes else 3051638Srgrimes i=z; 3061638Srgrimes } 3071638Srgrimes else 3081638Srgrimes { 3091638Srgrimes i=EVP_DecodeUpdate(&(ctx->base64), 3101638Srgrimes (unsigned char *)ctx->buf,&ctx->buf_len, 3111638Srgrimes (unsigned char *)ctx->tmp,i); 3121638Srgrimes } 3131638Srgrimes ctx->cont=i; 3141638Srgrimes ctx->buf_off=0; 3151638Srgrimes if (i < 0) 3161638Srgrimes { 3171638Srgrimes ret_code=0; 3181638Srgrimes ctx->buf_len=0; 3191638Srgrimes break; 3201638Srgrimes } 3211638Srgrimes 3221638Srgrimes if (ctx->buf_len <= outl) 3231638Srgrimes i=ctx->buf_len; 3241638Srgrimes else 3251638Srgrimes i=outl; 3261638Srgrimes 3271638Srgrimes memcpy(out,ctx->buf,i); 3281638Srgrimes ret+=i; 3291638Srgrimes ctx->buf_off=i; 3301638Srgrimes if (ctx->buf_off == ctx->buf_len) 3311638Srgrimes { 3321638Srgrimes ctx->buf_len=0; 3331638Srgrimes ctx->buf_off=0; 3341638Srgrimes } 3351638Srgrimes outl-=i; 3361638Srgrimes out+=i; 3371638Srgrimes } 3381638Srgrimes BIO_clear_retry_flags(b); 3391638Srgrimes BIO_copy_next_retry(b); 3401638Srgrimes return((ret == 0)?ret_code:ret); 3411638Srgrimes } 3421638Srgrimes 3431638Srgrimesstatic int b64_write(BIO *b, char *in, int inl) 3441638Srgrimes { 3451638Srgrimes int ret=inl,n,i; 3461638Srgrimes BIO_B64_CTX *ctx; 3471638Srgrimes 3481638Srgrimes ctx=(BIO_B64_CTX *)b->ptr; 3491638Srgrimes BIO_clear_retry_flags(b); 350108533Sschweikh 3511638Srgrimes if (ctx->encode != B64_ENCODE) 3521638Srgrimes { 3531638Srgrimes ctx->encode=B64_ENCODE; 3541638Srgrimes ctx->buf_len=0; 3551638Srgrimes ctx->buf_off=0; 3561638Srgrimes ctx->tmp_len=0; 3571638Srgrimes EVP_EncodeInit(&(ctx->base64)); 358108533Sschweikh } 3591638Srgrimes 3601638Srgrimes n=ctx->buf_len-ctx->buf_off; 3611638Srgrimes while (n > 0) 362108533Sschweikh { 3631638Srgrimes i=BIO_write(b->next_bio,&(ctx->buf[ctx->buf_off]),n); 3641638Srgrimes if (i <= 0) 3651638Srgrimes { 3661638Srgrimes BIO_copy_next_retry(b); 3671638Srgrimes return(i); 3681638Srgrimes } 3691638Srgrimes ctx->buf_off+=i; 3701638Srgrimes n-=i; 3711638Srgrimes } 3721638Srgrimes /* at this point all pending data has been written */ 3731638Srgrimes 3741638Srgrimes if ((in == NULL) || (inl <= 0)) return(0); 375108533Sschweikh 376108533Sschweikh ctx->buf_off=0; 3771638Srgrimes while (inl > 0) 3781638Srgrimes { 3791638Srgrimes n=(inl > B64_BLOCK_SIZE)?B64_BLOCK_SIZE:inl; 3801638Srgrimes 3811638Srgrimes if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) 3821638Srgrimes { 3831638Srgrimes if (ctx->tmp_len > 0) 3841638Srgrimes { 3851638Srgrimes n=3-ctx->tmp_len; 3861638Srgrimes memcpy(&(ctx->tmp[ctx->tmp_len]),in,n); 3871638Srgrimes ctx->tmp_len+=n; 3881638Srgrimes n=ctx->tmp_len; 3891638Srgrimes if (n < 3) 3901638Srgrimes break; 3911638Srgrimes ctx->buf_len=EVP_EncodeBlock( 3921638Srgrimes (unsigned char *)ctx->buf, 3931638Srgrimes (unsigned char *)ctx->tmp,n); 3941638Srgrimes } 3951638Srgrimes else 3961638Srgrimes { 3971638Srgrimes if (n < 3) 3981638Srgrimes { 3991638Srgrimes memcpy(&(ctx->tmp[0]),in,n); 4001638Srgrimes ctx->tmp_len=n; 4011638Srgrimes break; 4021638Srgrimes } 4031638Srgrimes n-=n%3; 4041638Srgrimes ctx->buf_len=EVP_EncodeBlock( 4051638Srgrimes (unsigned char *)ctx->buf, 4061638Srgrimes (unsigned char *)in,n); 4071638Srgrimes } 4081638Srgrimes } 4091638Srgrimes else 4101638Srgrimes { 4111638Srgrimes EVP_EncodeUpdate(&(ctx->base64), 4121638Srgrimes (unsigned char *)ctx->buf,&ctx->buf_len, 4131638Srgrimes (unsigned char *)in,n); 4141638Srgrimes } 4151638Srgrimes inl-=n; 4161638Srgrimes in+=n; 4171638Srgrimes 4181638Srgrimes ctx->buf_off=0; 4191638Srgrimes n=ctx->buf_len; 4201638Srgrimes while (n > 0) 4211638Srgrimes { 4221638Srgrimes i=BIO_write(b->next_bio,&(ctx->buf[ctx->buf_off]),n); 4231638Srgrimes if (i <= 0) 4241638Srgrimes { 4251638Srgrimes BIO_copy_next_retry(b); 4261638Srgrimes return((ret == 0)?i:ret); 4271638Srgrimes } 4281638Srgrimes n-=i; 4291638Srgrimes ctx->buf_off+=i; 4301638Srgrimes } 4311638Srgrimes ctx->buf_len=0; 4321638Srgrimes ctx->buf_off=0; 4331638Srgrimes } 4341638Srgrimes return(ret); 4351638Srgrimes } 4361638Srgrimes 4371638Srgrimesstatic long b64_ctrl(BIO *b, int cmd, long num, char *ptr) 4381638Srgrimes { 4391638Srgrimes BIO_B64_CTX *ctx; 4401638Srgrimes long ret=1; 4411638Srgrimes int i; 4421638Srgrimes 4431638Srgrimes ctx=(BIO_B64_CTX *)b->ptr; 444108533Sschweikh 4451638Srgrimes switch (cmd) 4461638Srgrimes { 4471638Srgrimes case BIO_CTRL_RESET: 4481638Srgrimes ctx->cont=1; 4491638Srgrimes ctx->start=1; 4501638Srgrimes ctx->encode=B64_NONE; 4511638Srgrimes ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 4521638Srgrimes break; 4531638Srgrimes case BIO_CTRL_EOF: /* More to read */ 4541638Srgrimes if (ctx->cont <= 0) 4551638Srgrimes ret=1; 4561638Srgrimes else 4571638Srgrimes ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 4581638Srgrimes break; 4591638Srgrimes case BIO_CTRL_WPENDING: /* More to write in buffer */ 4601638Srgrimes ret=ctx->buf_len-ctx->buf_off; 4611638Srgrimes if ((ret == 0) && (ctx->base64.num != 0)) 4621638Srgrimes ret=1; 4631638Srgrimes else if (ret <= 0) 4641638Srgrimes ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 4651638Srgrimes break; 4661638Srgrimes case BIO_CTRL_PENDING: /* More to read in buffer */ 4671638Srgrimes ret=ctx->buf_len-ctx->buf_off; 4681638Srgrimes if (ret <= 0) 469108533Sschweikh ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 4701638Srgrimes break; 4711638Srgrimes case BIO_CTRL_FLUSH: 4721638Srgrimes /* do a final write */ 4731638Srgrimesagain: 4741638Srgrimes while (ctx->buf_len != ctx->buf_off) 4751638Srgrimes { 4761638Srgrimes i=b64_write(b,NULL,0); 4771638Srgrimes if (i < 0) 4781638Srgrimes { 4791638Srgrimes ret=i; 4801638Srgrimes break; 4811638Srgrimes } 4821638Srgrimes } 4831638Srgrimes if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) 4841638Srgrimes { 4851638Srgrimes if (ctx->tmp_len != 0) 4861638Srgrimes { 4871638Srgrimes ctx->buf_len=EVP_EncodeBlock( 4881638Srgrimes (unsigned char *)ctx->buf, 4891638Srgrimes (unsigned char *)ctx->tmp, 4901638Srgrimes ctx->tmp_len); 491108533Sschweikh ctx->buf_off=0; 4921638Srgrimes ctx->tmp_len=0; 4931638Srgrimes goto again; 4941638Srgrimes } 4951638Srgrimes } 4961638Srgrimes else if (ctx->base64.num != 0) 4971638Srgrimes { 4981638Srgrimes ctx->buf_off=0; 4991638Srgrimes EVP_EncodeFinal(&(ctx->base64), 5001638Srgrimes (unsigned char *)ctx->buf, 5011638Srgrimes &(ctx->buf_len)); 5021638Srgrimes /* push out the bytes */ 5031638Srgrimes goto again; 5041638Srgrimes } 5051638Srgrimes /* Finally flush the underlying BIO */ 5061638Srgrimes ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 5071638Srgrimes break; 5081638Srgrimes 5091638Srgrimes case BIO_C_DO_STATE_MACHINE: 5101638Srgrimes BIO_clear_retry_flags(b); 5111638Srgrimes ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 5121638Srgrimes BIO_copy_next_retry(b); 5131638Srgrimes break; 5141638Srgrimes 5151638Srgrimes case BIO_CTRL_DUP: 5161638Srgrimes break; 5171638Srgrimes case BIO_CTRL_INFO: 5181638Srgrimes case BIO_CTRL_GET: 5191638Srgrimes case BIO_CTRL_SET: 5201638Srgrimes default: 5211638Srgrimes ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 5221638Srgrimes break; 5231638Srgrimes } 5241638Srgrimes return(ret); 5251638Srgrimes } 5261638Srgrimes 5271638Srgrimesstatic long b64_callback_ctrl(BIO *b, int cmd, void (*fp)()) 5281638Srgrimes { 5291638Srgrimes long ret=1; 5301638Srgrimes 5311638Srgrimes if (b->next_bio == NULL) return(0); 5321638Srgrimes switch (cmd) 5331638Srgrimes { 5341638Srgrimes default: 5351638Srgrimes ret=BIO_callback_ctrl(b->next_bio,cmd,fp); 5361638Srgrimes break; 5371638Srgrimes } 5381638Srgrimes return(ret); 5391638Srgrimes } 5401638Srgrimes 5411638Srgrimes