X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=crypto%2Fevp%2Fbio_b64.c;h=f12eac1b55a06b37a49d1d579f1b65d7edb9fca0;hb=c938563a81d48e1d23bddcf9283d4961794db132;hp=e362dc3bfeb9174a492db54ef357689641c216ec;hpb=b7896b3cb86d80206af14a14d69b0717786f2729;p=oweals%2Fopenssl.git diff --git a/crypto/evp/bio_b64.c b/crypto/evp/bio_b64.c index e362dc3bfe..f12eac1b55 100644 --- a/crypto/evp/bio_b64.c +++ b/crypto/evp/bio_b64.c @@ -1,5 +1,5 @@ /* crypto/evp/bio_b64.c */ -/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written @@ -59,28 +59,19 @@ #include #include #include "cryptlib.h" -#include "buffer.h" -#include "evp.h" - -#ifndef NOPROTO -static int b64_write(BIO *h,char *buf,int num); -static int b64_read(BIO *h,char *buf,int size); -/*static int b64_puts(BIO *h,char *str); */ -/*static int b64_gets(BIO *h,char *str,int size); */ -static long b64_ctrl(BIO *h,int cmd,long arg1,char *arg2); +#include +#include + +static int b64_write(BIO *h, const char *buf, int num); +static int b64_read(BIO *h, char *buf, int size); +/*static int b64_puts(BIO *h, const char *str); */ +/*static int b64_gets(BIO *h, char *str, int size); */ +static long b64_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int b64_new(BIO *h); static int b64_free(BIO *data); -#else -static int b64_write(); -static int b64_read(); -/*static int b64_puts(); */ -/*static int b64_gets(); */ -static long b64_ctrl(); -static int b64_new(); -static int b64_free(); -#endif - +static long b64_callback_ctrl(BIO *h,int cmd,bio_info_cb *fp); #define B64_BLOCK_SIZE 1024 +#define B64_BLOCK_SIZE2 768 #define B64_NONE 0 #define B64_ENCODE 1 #define B64_DECODE 2 @@ -110,19 +101,19 @@ static BIO_METHOD methods_b64= b64_ctrl, b64_new, b64_free, + b64_callback_ctrl, }; -BIO_METHOD *BIO_f_base64() +BIO_METHOD *BIO_f_base64(void) { return(&methods_b64); } -static int b64_new(bi) -BIO *bi; +static int b64_new(BIO *bi) { BIO_B64_CTX *ctx; - ctx=(BIO_B64_CTX *)Malloc(sizeof(BIO_B64_CTX)); + ctx=(BIO_B64_CTX *)OPENSSL_malloc(sizeof(BIO_B64_CTX)); if (ctx == NULL) return(0); ctx->buf_len=0; @@ -139,23 +130,19 @@ BIO *bi; return(1); } -static int b64_free(a) -BIO *a; +static int b64_free(BIO *a) { if (a == NULL) return(0); - Free(a->ptr); + OPENSSL_free(a->ptr); a->ptr=NULL; a->init=0; a->flags=0; return(1); } -static int b64_read(b,out,outl) -BIO *b; -char *out; -int outl; +static int b64_read(BIO *b, char *out, int outl) { - int ret=0,i,ii,j,k,x,n,num; + int ret=0,i,ii,j,k,x,n,num,ret_code=0; BIO_B64_CTX *ctx; unsigned char *p,*q; @@ -169,6 +156,7 @@ int outl; ctx->encode=B64_DECODE; ctx->buf_len=0; ctx->buf_off=0; + ctx->tmp_len=0; EVP_DecodeInit(&(ctx->base64)); } @@ -192,6 +180,7 @@ int outl; /* At this point, we have room of outl bytes and an empty * buffer, so we should read in some more. */ + ret_code=0; while (outl > 0) { if (ctx->cont <= 0) break; @@ -201,16 +190,24 @@ int outl; if (i <= 0) { + ret_code=i; + /* Should be continue next time we are called? */ if (!BIO_should_retry(b->next_bio)) ctx->cont=i; + /* else we should continue when called again */ break; } i+=ctx->tmp_len; /* We need to scan, a line at a time until we * have a valid line if we are starting. */ - if (ctx->start) + if (ctx->start && (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL)) + { + /* ctx->start=1; */ + ctx->tmp_len=0; + } + else if (ctx->start) { q=p=(unsigned char *)ctx->tmp; for (j=0; jtmp[0])); for (x=0; x < i; x++) ctx->tmp[x]=p[x]; - EVP_DecodeInit(&ctx->base64); } + EVP_DecodeInit(&ctx->base64); ctx->start=0; break; } @@ -273,13 +270,51 @@ int outl; else ctx->tmp_len=0; } - i=EVP_DecodeUpdate(&(ctx->base64), - (unsigned char *)ctx->buf,&ctx->buf_len, - (unsigned char *)ctx->tmp,i); + + if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) + { + int z,jj; + + jj=(i>>2)<<2; + z=EVP_DecodeBlock((unsigned char *)ctx->buf, + (unsigned char *)ctx->tmp,jj); + if (jj > 2) + { + if (ctx->tmp[jj-1] == '=') + { + z--; + if (ctx->tmp[jj-2] == '=') + z--; + } + } + /* z is now number of output bytes and jj is the + * number consumed */ + if (jj != i) + { + memcpy((unsigned char *)ctx->tmp, + (unsigned char *)&(ctx->tmp[jj]),i-jj); + ctx->tmp_len=i-jj; + } + ctx->buf_len=0; + if (z > 0) + { + ctx->buf_len=z; + i=1; + } + else + i=z; + } + else + { + i=EVP_DecodeUpdate(&(ctx->base64), + (unsigned char *)ctx->buf,&ctx->buf_len, + (unsigned char *)ctx->tmp,i); + } ctx->cont=i; ctx->buf_off=0; if (i < 0) { + ret_code=0; ctx->buf_len=0; break; } @@ -302,13 +337,10 @@ int outl; } BIO_clear_retry_flags(b); BIO_copy_next_retry(b); - return((ret == 0)?ctx->cont:ret); + return((ret == 0)?ret_code:ret); } -static int b64_write(b,in,inl) -BIO *b; -char *in; -int inl; +static int b64_write(BIO *b, const char *in, int inl) { int ret=inl,n,i; BIO_B64_CTX *ctx; @@ -321,6 +353,7 @@ int inl; ctx->encode=B64_ENCODE; ctx->buf_len=0; ctx->buf_off=0; + ctx->tmp_len=0; EVP_EncodeInit(&(ctx->base64)); } @@ -337,16 +370,55 @@ int inl; n-=i; } /* at this point all pending data has been written */ + ctx->buf_off=0; + ctx->buf_len=0; if ((in == NULL) || (inl <= 0)) return(0); - ctx->buf_off=0; while (inl > 0) { n=(inl > B64_BLOCK_SIZE)?B64_BLOCK_SIZE:inl; - EVP_EncodeUpdate(&(ctx->base64), - (unsigned char *)ctx->buf,&ctx->buf_len, - (unsigned char *)in,n); + + if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) + { + if (ctx->tmp_len > 0) + { + n=3-ctx->tmp_len; + /* There's a teoretical possibility for this */ + if (n > inl) + n=inl; + memcpy(&(ctx->tmp[ctx->tmp_len]),in,n); + ctx->tmp_len+=n; + if (ctx->tmp_len < 3) + break; + ctx->buf_len=EVP_EncodeBlock( + (unsigned char *)ctx->buf, + (unsigned char *)ctx->tmp, + ctx->tmp_len); + /* Since we're now done using the temporary + buffer, the length should be 0'd */ + ctx->tmp_len=0; + } + else + { + if (n < 3) + { + memcpy(&(ctx->tmp[0]),in,n); + ctx->tmp_len=n; + break; + } + n-=n%3; + ctx->buf_len=EVP_EncodeBlock( + (unsigned char *)ctx->buf, + (unsigned char *)in,n); + } + } + else + { + EVP_EncodeUpdate(&(ctx->base64), + (unsigned char *)ctx->buf,&ctx->buf_len, + (unsigned char *)in,n); + } inl-=n; in+=n; @@ -369,11 +441,7 @@ int inl; return(ret); } -static long b64_ctrl(b,cmd,num,ptr) -BIO *b; -int cmd; -long num; -char *ptr; +static long b64_ctrl(BIO *b, int cmd, long num, void *ptr) { BIO_B64_CTX *ctx; long ret=1; @@ -397,7 +465,8 @@ char *ptr; break; case BIO_CTRL_WPENDING: /* More to write in buffer */ ret=ctx->buf_len-ctx->buf_off; - if ((ret == 0) && (ctx->base64.num != 0)) + if ((ret == 0) && (ctx->encode != B64_NONE) + && (ctx->base64.num != 0)) ret=1; else if (ret <= 0) ret=BIO_ctrl(b->next_bio,cmd,num,ptr); @@ -419,7 +488,20 @@ again: break; } } - if (ctx->base64.num != 0) + if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) + { + if (ctx->tmp_len != 0) + { + ctx->buf_len=EVP_EncodeBlock( + (unsigned char *)ctx->buf, + (unsigned char *)ctx->tmp, + ctx->tmp_len); + ctx->buf_off=0; + ctx->tmp_len=0; + goto again; + } + } + else if (ctx->encode != B64_NONE && ctx->base64.num != 0) { ctx->buf_off=0; EVP_EncodeFinal(&(ctx->base64), @@ -450,3 +532,17 @@ again: return(ret); } +static long b64_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) + { + long ret=1; + + if (b->next_bio == NULL) return(0); + switch (cmd) + { + default: + ret=BIO_callback_ctrl(b->next_bio,cmd,fp); + break; + } + return(ret); + } +