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