155714Skris/* crypto/evp/bio_enc.c */ 255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 355714Skris * All rights reserved. 455714Skris * 555714Skris * This package is an SSL implementation written 655714Skris * by Eric Young (eay@cryptsoft.com). 755714Skris * The implementation was written so as to conform with Netscapes SSL. 855714Skris * 955714Skris * This library is free for commercial and non-commercial use as long as 1055714Skris * the following conditions are aheared to. The following conditions 1155714Skris * apply to all code found in this distribution, be it the RC4, RSA, 1255714Skris * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1355714Skris * included with this distribution is covered by the same copyright terms 1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com). 1555714Skris * 1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in 1755714Skris * the code are not to be removed. 1855714Skris * If this package is used in a product, Eric Young should be given attribution 1955714Skris * as the author of the parts of the library used. 2055714Skris * This can be in the form of a textual message at program startup or 2155714Skris * in documentation (online or textual) provided with the package. 2255714Skris * 2355714Skris * Redistribution and use in source and binary forms, with or without 2455714Skris * modification, are permitted provided that the following conditions 2555714Skris * are met: 2655714Skris * 1. Redistributions of source code must retain the copyright 2755714Skris * notice, this list of conditions and the following disclaimer. 2855714Skris * 2. Redistributions in binary form must reproduce the above copyright 2955714Skris * notice, this list of conditions and the following disclaimer in the 3055714Skris * documentation and/or other materials provided with the distribution. 3155714Skris * 3. All advertising materials mentioning features or use of this software 3255714Skris * must display the following acknowledgement: 3355714Skris * "This product includes cryptographic software written by 3455714Skris * Eric Young (eay@cryptsoft.com)" 3555714Skris * The word 'cryptographic' can be left out if the rouines from the library 3655714Skris * being used are not cryptographic related :-). 3755714Skris * 4. If you include any Windows specific code (or a derivative thereof) from 3855714Skris * the apps directory (application code) you must include an acknowledgement: 3955714Skris * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 4055714Skris * 4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4455714Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5155714Skris * SUCH DAMAGE. 5255714Skris * 5355714Skris * The licence and distribution terms for any publically available version or 5455714Skris * derivative of this code cannot be changed. i.e. this code cannot simply be 5555714Skris * copied and put under another distribution licence 5655714Skris * [including the GNU Public Licence.] 5755714Skris */ 5855714Skris 5955714Skris#include <stdio.h> 6055714Skris#include <errno.h> 6155714Skris#include "cryptlib.h" 6255714Skris#include <openssl/buffer.h> 6355714Skris#include <openssl/evp.h> 6455714Skris 6568651Skrisstatic int enc_write(BIO *h, const char *buf, int num); 6668651Skrisstatic int enc_read(BIO *h, char *buf, int size); 6768651Skris/*static int enc_puts(BIO *h, const char *str); */ 6868651Skris/*static int enc_gets(BIO *h, char *str, int size); */ 6968651Skrisstatic long enc_ctrl(BIO *h, int cmd, long arg1, void *arg2); 7055714Skrisstatic int enc_new(BIO *h); 7155714Skrisstatic int enc_free(BIO *data); 7268651Skrisstatic long enc_callback_ctrl(BIO *h, int cmd, bio_info_cb *fps); 7355714Skris#define ENC_BLOCK_SIZE (1024*4) 74160814Ssimon#define BUF_OFFSET (EVP_MAX_BLOCK_LENGTH*2) 7555714Skris 7655714Skristypedef struct enc_struct 7755714Skris { 7855714Skris int buf_len; 7955714Skris int buf_off; 8055714Skris int cont; /* <= 0 when finished */ 8155714Skris int finished; 8255714Skris int ok; /* bad decrypt */ 8355714Skris EVP_CIPHER_CTX cipher; 84109998Smarkm /* buf is larger than ENC_BLOCK_SIZE because EVP_DecryptUpdate 85109998Smarkm * can return up to a block more data than is presented to it 86109998Smarkm */ 87109998Smarkm char buf[ENC_BLOCK_SIZE+BUF_OFFSET+2]; 8855714Skris } BIO_ENC_CTX; 8955714Skris 9055714Skrisstatic BIO_METHOD methods_enc= 9155714Skris { 9255714Skris BIO_TYPE_CIPHER,"cipher", 9355714Skris enc_write, 9455714Skris enc_read, 9555714Skris NULL, /* enc_puts, */ 9655714Skris NULL, /* enc_gets, */ 9755714Skris enc_ctrl, 9855714Skris enc_new, 9955714Skris enc_free, 10059191Skris enc_callback_ctrl, 10155714Skris }; 10255714Skris 10355714SkrisBIO_METHOD *BIO_f_cipher(void) 10455714Skris { 10555714Skris return(&methods_enc); 10655714Skris } 10755714Skris 10855714Skrisstatic int enc_new(BIO *bi) 10955714Skris { 11055714Skris BIO_ENC_CTX *ctx; 11155714Skris 11268651Skris ctx=(BIO_ENC_CTX *)OPENSSL_malloc(sizeof(BIO_ENC_CTX)); 113100936Snectar if (ctx == NULL) return(0); 11455714Skris EVP_CIPHER_CTX_init(&ctx->cipher); 11555714Skris 11655714Skris ctx->buf_len=0; 11755714Skris ctx->buf_off=0; 11855714Skris ctx->cont=1; 11955714Skris ctx->finished=0; 12055714Skris ctx->ok=1; 12155714Skris 12255714Skris bi->init=0; 12355714Skris bi->ptr=(char *)ctx; 12455714Skris bi->flags=0; 12555714Skris return(1); 12655714Skris } 12755714Skris 12855714Skrisstatic int enc_free(BIO *a) 12955714Skris { 13055714Skris BIO_ENC_CTX *b; 13155714Skris 13255714Skris if (a == NULL) return(0); 13355714Skris b=(BIO_ENC_CTX *)a->ptr; 13455714Skris EVP_CIPHER_CTX_cleanup(&(b->cipher)); 135109998Smarkm OPENSSL_cleanse(a->ptr,sizeof(BIO_ENC_CTX)); 13668651Skris OPENSSL_free(a->ptr); 13755714Skris a->ptr=NULL; 13855714Skris a->init=0; 13955714Skris a->flags=0; 14055714Skris return(1); 14155714Skris } 14255714Skris 14355714Skrisstatic int enc_read(BIO *b, char *out, int outl) 14455714Skris { 14555714Skris int ret=0,i; 14655714Skris BIO_ENC_CTX *ctx; 14755714Skris 14855714Skris if (out == NULL) return(0); 14955714Skris ctx=(BIO_ENC_CTX *)b->ptr; 15055714Skris 15155714Skris if ((ctx == NULL) || (b->next_bio == NULL)) return(0); 15255714Skris 15355714Skris /* First check if there are bytes decoded/encoded */ 15455714Skris if (ctx->buf_len > 0) 15555714Skris { 15655714Skris i=ctx->buf_len-ctx->buf_off; 15755714Skris if (i > outl) i=outl; 15855714Skris memcpy(out,&(ctx->buf[ctx->buf_off]),i); 15955714Skris ret=i; 16055714Skris out+=i; 16155714Skris outl-=i; 16255714Skris ctx->buf_off+=i; 16355714Skris if (ctx->buf_len == ctx->buf_off) 16455714Skris { 16555714Skris ctx->buf_len=0; 16655714Skris ctx->buf_off=0; 16755714Skris } 16855714Skris } 16955714Skris 17055714Skris /* At this point, we have room of outl bytes and an empty 17155714Skris * buffer, so we should read in some more. */ 17255714Skris 17355714Skris while (outl > 0) 17455714Skris { 17555714Skris if (ctx->cont <= 0) break; 17655714Skris 177109998Smarkm /* read in at IV offset, read the EVP_Cipher 17855714Skris * documentation about why */ 179109998Smarkm i=BIO_read(b->next_bio,&(ctx->buf[BUF_OFFSET]),ENC_BLOCK_SIZE); 18055714Skris 18155714Skris if (i <= 0) 18255714Skris { 18355714Skris /* Should be continue next time we are called? */ 18455714Skris if (!BIO_should_retry(b->next_bio)) 18555714Skris { 18655714Skris ctx->cont=i; 187109998Smarkm i=EVP_CipherFinal_ex(&(ctx->cipher), 18855714Skris (unsigned char *)ctx->buf, 18955714Skris &(ctx->buf_len)); 19055714Skris ctx->ok=i; 19155714Skris ctx->buf_off=0; 19255714Skris } 19359191Skris else 19459191Skris { 19555714Skris ret=(ret == 0)?i:ret; 19659191Skris break; 19759191Skris } 19855714Skris } 19955714Skris else 20055714Skris { 20155714Skris EVP_CipherUpdate(&(ctx->cipher), 20255714Skris (unsigned char *)ctx->buf,&ctx->buf_len, 203109998Smarkm (unsigned char *)&(ctx->buf[BUF_OFFSET]),i); 20455714Skris ctx->cont=1; 20559191Skris /* Note: it is possible for EVP_CipherUpdate to 20659191Skris * decrypt zero bytes because this is or looks like 20759191Skris * the final block: if this happens we should retry 20859191Skris * and either read more data or decrypt the final 20959191Skris * block 21059191Skris */ 21159191Skris if(ctx->buf_len == 0) continue; 21255714Skris } 21355714Skris 21455714Skris if (ctx->buf_len <= outl) 21555714Skris i=ctx->buf_len; 21655714Skris else 21755714Skris i=outl; 21855714Skris if (i <= 0) break; 21955714Skris memcpy(out,ctx->buf,i); 22055714Skris ret+=i; 22155714Skris ctx->buf_off=i; 22255714Skris outl-=i; 22355714Skris out+=i; 22455714Skris } 22555714Skris 22655714Skris BIO_clear_retry_flags(b); 22755714Skris BIO_copy_next_retry(b); 22855714Skris return((ret == 0)?ctx->cont:ret); 22955714Skris } 23055714Skris 23168651Skrisstatic int enc_write(BIO *b, const char *in, int inl) 23255714Skris { 23355714Skris int ret=0,n,i; 23455714Skris BIO_ENC_CTX *ctx; 23555714Skris 23655714Skris ctx=(BIO_ENC_CTX *)b->ptr; 23755714Skris ret=inl; 23855714Skris 23955714Skris BIO_clear_retry_flags(b); 24055714Skris n=ctx->buf_len-ctx->buf_off; 24155714Skris while (n > 0) 24255714Skris { 24355714Skris i=BIO_write(b->next_bio,&(ctx->buf[ctx->buf_off]),n); 24455714Skris if (i <= 0) 24555714Skris { 24655714Skris BIO_copy_next_retry(b); 24755714Skris return(i); 24855714Skris } 24955714Skris ctx->buf_off+=i; 25055714Skris n-=i; 25155714Skris } 25255714Skris /* at this point all pending data has been written */ 25355714Skris 25455714Skris if ((in == NULL) || (inl <= 0)) return(0); 25555714Skris 25655714Skris ctx->buf_off=0; 25755714Skris while (inl > 0) 25855714Skris { 25955714Skris n=(inl > ENC_BLOCK_SIZE)?ENC_BLOCK_SIZE:inl; 26055714Skris EVP_CipherUpdate(&(ctx->cipher), 26155714Skris (unsigned char *)ctx->buf,&ctx->buf_len, 26255714Skris (unsigned char *)in,n); 26355714Skris inl-=n; 26455714Skris in+=n; 26555714Skris 26655714Skris ctx->buf_off=0; 26755714Skris n=ctx->buf_len; 26855714Skris while (n > 0) 26955714Skris { 27055714Skris i=BIO_write(b->next_bio,&(ctx->buf[ctx->buf_off]),n); 27155714Skris if (i <= 0) 27255714Skris { 27355714Skris BIO_copy_next_retry(b); 274120631Snectar return (ret == inl) ? i : ret - inl; 27555714Skris } 27655714Skris n-=i; 27755714Skris ctx->buf_off+=i; 27855714Skris } 27955714Skris ctx->buf_len=0; 28055714Skris ctx->buf_off=0; 28155714Skris } 28255714Skris BIO_copy_next_retry(b); 28355714Skris return(ret); 28455714Skris } 28555714Skris 28668651Skrisstatic long enc_ctrl(BIO *b, int cmd, long num, void *ptr) 28755714Skris { 28855714Skris BIO *dbio; 28955714Skris BIO_ENC_CTX *ctx,*dctx; 29055714Skris long ret=1; 29155714Skris int i; 29255714Skris EVP_CIPHER_CTX **c_ctx; 29355714Skris 29455714Skris ctx=(BIO_ENC_CTX *)b->ptr; 29555714Skris 29655714Skris switch (cmd) 29755714Skris { 29855714Skris case BIO_CTRL_RESET: 29955714Skris ctx->ok=1; 30055714Skris ctx->finished=0; 301109998Smarkm EVP_CipherInit_ex(&(ctx->cipher),NULL,NULL,NULL,NULL, 30255714Skris ctx->cipher.encrypt); 30355714Skris ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 30455714Skris break; 30555714Skris case BIO_CTRL_EOF: /* More to read */ 30655714Skris if (ctx->cont <= 0) 30755714Skris ret=1; 30855714Skris else 30955714Skris ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 31055714Skris break; 31155714Skris case BIO_CTRL_WPENDING: 31255714Skris ret=ctx->buf_len-ctx->buf_off; 31355714Skris if (ret <= 0) 31455714Skris ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 31555714Skris break; 31655714Skris case BIO_CTRL_PENDING: /* More to read in buffer */ 31755714Skris ret=ctx->buf_len-ctx->buf_off; 31855714Skris if (ret <= 0) 31955714Skris ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 32055714Skris break; 32155714Skris case BIO_CTRL_FLUSH: 32255714Skris /* do a final write */ 32355714Skrisagain: 32455714Skris while (ctx->buf_len != ctx->buf_off) 32555714Skris { 32655714Skris i=enc_write(b,NULL,0); 32755714Skris if (i < 0) 328120631Snectar return i; 32955714Skris } 33055714Skris 33155714Skris if (!ctx->finished) 33255714Skris { 33355714Skris ctx->finished=1; 33455714Skris ctx->buf_off=0; 335109998Smarkm ret=EVP_CipherFinal_ex(&(ctx->cipher), 33655714Skris (unsigned char *)ctx->buf, 33755714Skris &(ctx->buf_len)); 33855714Skris ctx->ok=(int)ret; 33955714Skris if (ret <= 0) break; 34055714Skris 34155714Skris /* push out the bytes */ 34255714Skris goto again; 34355714Skris } 34455714Skris 34555714Skris /* Finally flush the underlying BIO */ 34655714Skris ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 34755714Skris break; 34855714Skris case BIO_C_GET_CIPHER_STATUS: 34955714Skris ret=(long)ctx->ok; 35055714Skris break; 35155714Skris case BIO_C_DO_STATE_MACHINE: 35255714Skris BIO_clear_retry_flags(b); 35355714Skris ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 35455714Skris BIO_copy_next_retry(b); 35555714Skris break; 35655714Skris case BIO_C_GET_CIPHER_CTX: 35755714Skris c_ctx=(EVP_CIPHER_CTX **)ptr; 35855714Skris (*c_ctx)= &(ctx->cipher); 35955714Skris b->init=1; 36055714Skris break; 36155714Skris case BIO_CTRL_DUP: 36255714Skris dbio=(BIO *)ptr; 36355714Skris dctx=(BIO_ENC_CTX *)dbio->ptr; 364238405Sjkim EVP_CIPHER_CTX_init(&dctx->cipher); 365238405Sjkim ret = EVP_CIPHER_CTX_copy(&dctx->cipher,&ctx->cipher); 366238405Sjkim if (ret) 367238405Sjkim dbio->init=1; 36855714Skris break; 36955714Skris default: 37055714Skris ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 37155714Skris break; 37255714Skris } 37355714Skris return(ret); 37455714Skris } 37555714Skris 37668651Skrisstatic long enc_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) 37759191Skris { 37859191Skris long ret=1; 37959191Skris 38059191Skris if (b->next_bio == NULL) return(0); 38159191Skris switch (cmd) 38259191Skris { 38359191Skris default: 38459191Skris ret=BIO_callback_ctrl(b->next_bio,cmd,fp); 38559191Skris break; 38659191Skris } 38759191Skris return(ret); 38859191Skris } 38959191Skris 39055714Skris/* 39155714Skrisvoid BIO_set_cipher_ctx(b,c) 39255714SkrisBIO *b; 39355714SkrisEVP_CIPHER_ctx *c; 39455714Skris { 39555714Skris if (b == NULL) return; 39655714Skris 39755714Skris if ((b->callback != NULL) && 39855714Skris (b->callback(b,BIO_CB_CTRL,(char *)c,BIO_CTRL_SET,e,0L) <= 0)) 39955714Skris return; 40055714Skris 40155714Skris b->init=1; 40255714Skris ctx=(BIO_ENC_CTX *)b->ptr; 40355714Skris memcpy(ctx->cipher,c,sizeof(EVP_CIPHER_CTX)); 40455714Skris 40555714Skris if (b->callback != NULL) 40655714Skris b->callback(b,BIO_CB_CTRL,(char *)c,BIO_CTRL_SET,e,1L); 40755714Skris } 40855714Skris*/ 40955714Skris 410160814Ssimonvoid BIO_set_cipher(BIO *b, const EVP_CIPHER *c, const unsigned char *k, 411160814Ssimon const unsigned char *i, int e) 41255714Skris { 41355714Skris BIO_ENC_CTX *ctx; 41455714Skris 41555714Skris if (b == NULL) return; 41655714Skris 41755714Skris if ((b->callback != NULL) && 41855714Skris (b->callback(b,BIO_CB_CTRL,(const char *)c,BIO_CTRL_SET,e,0L) <= 0)) 41955714Skris return; 42055714Skris 42155714Skris b->init=1; 42255714Skris ctx=(BIO_ENC_CTX *)b->ptr; 423109998Smarkm EVP_CipherInit_ex(&(ctx->cipher),c,NULL, k,i,e); 42455714Skris 42555714Skris if (b->callback != NULL) 42655714Skris b->callback(b,BIO_CB_CTRL,(const char *)c,BIO_CTRL_SET,e,1L); 42755714Skris } 42855714Skris 429