1 /* crypto/evp/bio_enc.c */ 2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3 * All rights reserved. 4 * 5 * This package is an SSL implementation written 6 * by Eric Young (eay@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@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@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@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 enc_write(BIO *h, const char *buf, int num); 66 static int enc_read(BIO *h, char *buf, int size); 67 /*static int enc_puts(BIO *h, const char *str); */ 68 /*static int enc_gets(BIO *h, char *str, int size); */ 69 static long enc_ctrl(BIO *h, int cmd, long arg1, void *arg2); 70 static int enc_new(BIO *h); 71 static int enc_free(BIO *data); 72 static long enc_callback_ctrl(BIO *h, int cmd, bio_info_cb *fps); 73 #define ENC_BLOCK_SIZE (1024*4) 74 #define BUF_OFFSET (EVP_MAX_BLOCK_LENGTH*2) 75 76 typedef struct enc_struct 77 { 78 int buf_len; 79 int buf_off; 80 int cont; /* <= 0 when finished */ 81 int finished; 82 int ok; /* bad decrypt */ 83 EVP_CIPHER_CTX cipher; 84 /* buf is larger than ENC_BLOCK_SIZE because EVP_DecryptUpdate 85 * can return up to a block more data than is presented to it 86 */ 87 char buf[ENC_BLOCK_SIZE+BUF_OFFSET+2]; 88 } BIO_ENC_CTX; 89 90 static BIO_METHOD methods_enc= 91 { 92 BIO_TYPE_CIPHER,"cipher", 93 enc_write, 94 enc_read, 95 NULL, /* enc_puts, */ 96 NULL, /* enc_gets, */ 97 enc_ctrl, 98 enc_new, 99 enc_free, 100 enc_callback_ctrl, 101 }; 102 103 BIO_METHOD *BIO_f_cipher(void) 104 { 105 return(&methods_enc); 106 } 107 108 static int enc_new(BIO *bi) 109 { 110 BIO_ENC_CTX *ctx; 111 112 ctx=(BIO_ENC_CTX *)OPENSSL_malloc(sizeof(BIO_ENC_CTX)); 113 if (ctx == NULL) return(0); 114 EVP_CIPHER_CTX_init(&ctx->cipher); 115 116 ctx->buf_len=0; 117 ctx->buf_off=0; 118 ctx->cont=1; 119 ctx->finished=0; 120 ctx->ok=1; 121 122 bi->init=0; 123 bi->ptr=(char *)ctx; 124 bi->flags=0; 125 return(1); 126 } 127 128 static int enc_free(BIO *a) 129 { 130 BIO_ENC_CTX *b; 131 132 if (a == NULL) return(0); 133 b=(BIO_ENC_CTX *)a->ptr; 134 EVP_CIPHER_CTX_cleanup(&(b->cipher)); 135 OPENSSL_cleanse(a->ptr,sizeof(BIO_ENC_CTX)); 136 OPENSSL_free(a->ptr); 137 a->ptr=NULL; 138 a->init=0; 139 a->flags=0; 140 return(1); 141 } 142 143 static int enc_read(BIO *b, char *out, int outl) 144 { 145 int ret=0,i; 146 BIO_ENC_CTX *ctx; 147 148 if (out == NULL) return(0); 149 ctx=(BIO_ENC_CTX *)b->ptr; 150 151 if ((ctx == NULL) || (b->next_bio == NULL)) return(0); 152 153 /* First check if there are bytes decoded/encoded */ 154 if (ctx->buf_len > 0) 155 { 156 i=ctx->buf_len-ctx->buf_off; 157 if (i > outl) i=outl; 158 memcpy(out,&(ctx->buf[ctx->buf_off]),i); 159 ret=i; 160 out+=i; 161 outl-=i; 162 ctx->buf_off+=i; 163 if (ctx->buf_len == ctx->buf_off) 164 { 165 ctx->buf_len=0; 166 ctx->buf_off=0; 167 } 168 } 169 170 /* At this point, we have room of outl bytes and an empty 171 * buffer, so we should read in some more. */ 172 173 while (outl > 0) 174 { 175 if (ctx->cont <= 0) break; 176 177 /* read in at IV offset, read the EVP_Cipher 178 * documentation about why */ 179 i=BIO_read(b->next_bio,&(ctx->buf[BUF_OFFSET]),ENC_BLOCK_SIZE); 180 181 if (i <= 0) 182 { 183 /* Should be continue next time we are called? */ 184 if (!BIO_should_retry(b->next_bio)) 185 { 186 ctx->cont=i; 187 i=EVP_CipherFinal_ex(&(ctx->cipher), 188 (unsigned char *)ctx->buf, 189 &(ctx->buf_len)); 190 ctx->ok=i; 191 ctx->buf_off=0; 192 } 193 else 194 { 195 ret=(ret == 0)?i:ret; 196 break; 197 } 198 } 199 else 200 { 201 EVP_CipherUpdate(&(ctx->cipher), 202 (unsigned char *)ctx->buf,&ctx->buf_len, 203 (unsigned char *)&(ctx->buf[BUF_OFFSET]),i); 204 ctx->cont=1; 205 /* Note: it is possible for EVP_CipherUpdate to 206 * decrypt zero bytes because this is or looks like 207 * the final block: if this happens we should retry 208 * and either read more data or decrypt the final 209 * block 210 */ 211 if(ctx->buf_len == 0) continue; 212 } 213 214 if (ctx->buf_len <= outl) 215 i=ctx->buf_len; 216 else 217 i=outl; 218 if (i <= 0) break; 219 memcpy(out,ctx->buf,i); 220 ret+=i; 221 ctx->buf_off=i; 222 outl-=i; 223 out+=i; 224 } 225 226 BIO_clear_retry_flags(b); 227 BIO_copy_next_retry(b); 228 return((ret == 0)?ctx->cont:ret); 229 } 230 231 static int enc_write(BIO *b, const char *in, int inl) 232 { 233 int ret=0,n,i; 234 BIO_ENC_CTX *ctx; 235 236 ctx=(BIO_ENC_CTX *)b->ptr; 237 ret=inl; 238 239 BIO_clear_retry_flags(b); 240 n=ctx->buf_len-ctx->buf_off; 241 while (n > 0) 242 { 243 i=BIO_write(b->next_bio,&(ctx->buf[ctx->buf_off]),n); 244 if (i <= 0) 245 { 246 BIO_copy_next_retry(b); 247 return(i); 248 } 249 ctx->buf_off+=i; 250 n-=i; 251 } 252 /* at this point all pending data has been written */ 253 254 if ((in == NULL) || (inl <= 0)) return(0); 255 256 ctx->buf_off=0; 257 while (inl > 0) 258 { 259 n=(inl > ENC_BLOCK_SIZE)?ENC_BLOCK_SIZE:inl; 260 EVP_CipherUpdate(&(ctx->cipher), 261 (unsigned char *)ctx->buf,&ctx->buf_len, 262 (unsigned char *)in,n); 263 inl-=n; 264 in+=n; 265 266 ctx->buf_off=0; 267 n=ctx->buf_len; 268 while (n > 0) 269 { 270 i=BIO_write(b->next_bio,&(ctx->buf[ctx->buf_off]),n); 271 if (i <= 0) 272 { 273 BIO_copy_next_retry(b); 274 return (ret == inl) ? i : ret - inl; 275 } 276 n-=i; 277 ctx->buf_off+=i; 278 } 279 ctx->buf_len=0; 280 ctx->buf_off=0; 281 } 282 BIO_copy_next_retry(b); 283 return(ret); 284 } 285 286 static long enc_ctrl(BIO *b, int cmd, long num, void *ptr) 287 { 288 BIO *dbio; 289 BIO_ENC_CTX *ctx,*dctx; 290 long ret=1; 291 int i; 292 EVP_CIPHER_CTX **c_ctx; 293 294 ctx=(BIO_ENC_CTX *)b->ptr; 295 296 switch (cmd) 297 { 298 case BIO_CTRL_RESET: 299 ctx->ok=1; 300 ctx->finished=0; 301 EVP_CipherInit_ex(&(ctx->cipher),NULL,NULL,NULL,NULL, 302 ctx->cipher.encrypt); 303 ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 304 break; 305 case BIO_CTRL_EOF: /* More to read */ 306 if (ctx->cont <= 0) 307 ret=1; 308 else 309 ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 310 break; 311 case BIO_CTRL_WPENDING: 312 ret=ctx->buf_len-ctx->buf_off; 313 if (ret <= 0) 314 ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 315 break; 316 case BIO_CTRL_PENDING: /* More to read in buffer */ 317 ret=ctx->buf_len-ctx->buf_off; 318 if (ret <= 0) 319 ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 320 break; 321 case BIO_CTRL_FLUSH: 322 /* do a final write */ 323 again: 324 while (ctx->buf_len != ctx->buf_off) 325 { 326 i=enc_write(b,NULL,0); 327 if (i < 0) 328 return i; 329 } 330 331 if (!ctx->finished) 332 { 333 ctx->finished=1; 334 ctx->buf_off=0; 335 ret=EVP_CipherFinal_ex(&(ctx->cipher), 336 (unsigned char *)ctx->buf, 337 &(ctx->buf_len)); 338 ctx->ok=(int)ret; 339 if (ret <= 0) break; 340 341 /* push out the bytes */ 342 goto again; 343 } 344 345 /* Finally flush the underlying BIO */ 346 ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 347 break; 348 case BIO_C_GET_CIPHER_STATUS: 349 ret=(long)ctx->ok; 350 break; 351 case BIO_C_DO_STATE_MACHINE: 352 BIO_clear_retry_flags(b); 353 ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 354 BIO_copy_next_retry(b); 355 break; 356 case BIO_C_GET_CIPHER_CTX: 357 c_ctx=(EVP_CIPHER_CTX **)ptr; 358 (*c_ctx)= &(ctx->cipher); 359 b->init=1; 360 break; 361 case BIO_CTRL_DUP: 362 dbio=(BIO *)ptr; 363 dctx=(BIO_ENC_CTX *)dbio->ptr; 364 EVP_CIPHER_CTX_init(&dctx->cipher); 365 ret = EVP_CIPHER_CTX_copy(&dctx->cipher,&ctx->cipher); 366 if (ret) 367 dbio->init=1; 368 break; 369 default: 370 ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 371 break; 372 } 373 return(ret); 374 } 375 376 static long enc_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) 377 { 378 long ret=1; 379 380 if (b->next_bio == NULL) return(0); 381 switch (cmd) 382 { 383 default: 384 ret=BIO_callback_ctrl(b->next_bio,cmd,fp); 385 break; 386 } 387 return(ret); 388 } 389 390 /* 391 void BIO_set_cipher_ctx(b,c) 392 BIO *b; 393 EVP_CIPHER_ctx *c; 394 { 395 if (b == NULL) return; 396 397 if ((b->callback != NULL) && 398 (b->callback(b,BIO_CB_CTRL,(char *)c,BIO_CTRL_SET,e,0L) <= 0)) 399 return; 400 401 b->init=1; 402 ctx=(BIO_ENC_CTX *)b->ptr; 403 memcpy(ctx->cipher,c,sizeof(EVP_CIPHER_CTX)); 404 405 if (b->callback != NULL) 406 b->callback(b,BIO_CB_CTRL,(char *)c,BIO_CTRL_SET,e,1L); 407 } 408 */ 409 410 void BIO_set_cipher(BIO *b, const EVP_CIPHER *c, const unsigned char *k, 411 const unsigned char *i, int e) 412 { 413 BIO_ENC_CTX *ctx; 414 415 if (b == NULL) return; 416 417 if ((b->callback != NULL) && 418 (b->callback(b,BIO_CB_CTRL,(const char *)c,BIO_CTRL_SET,e,0L) <= 0)) 419 return; 420 421 b->init=1; 422 ctx=(BIO_ENC_CTX *)b->ptr; 423 EVP_CipherInit_ex(&(ctx->cipher),c,NULL, k,i,e); 424 425 if (b->callback != NULL) 426 b->callback(b,BIO_CB_CTRL,(const char *)c,BIO_CTRL_SET,e,1L); 427 }