1 /* $OpenBSD: bio_enc.c,v 1.22 2018/08/24 19:30:24 tb Exp $ */ 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 <errno.h> 60 #include <stdio.h> 61 #include <string.h> 62 63 #include <openssl/buffer.h> 64 #include <openssl/evp.h> 65 66 static int enc_write(BIO *h, const char *buf, int num); 67 static int enc_read(BIO *h, char *buf, int size); 68 /*static int enc_puts(BIO *h, const char *str); */ 69 /*static int enc_gets(BIO *h, char *str, int size); */ 70 static long enc_ctrl(BIO *h, int cmd, long arg1, void *arg2); 71 static int enc_new(BIO *h); 72 static int enc_free(BIO *data); 73 static long enc_callback_ctrl(BIO *h, int cmd, bio_info_cb *fps); 74 #define ENC_BLOCK_SIZE (1024*4) 75 #define BUF_OFFSET (EVP_MAX_BLOCK_LENGTH*2) 76 77 typedef struct enc_struct { 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 const BIO_METHOD methods_enc = { 91 .type = BIO_TYPE_CIPHER, 92 .name = "cipher", 93 .bwrite = enc_write, 94 .bread = enc_read, 95 .ctrl = enc_ctrl, 96 .create = enc_new, 97 .destroy = enc_free, 98 .callback_ctrl = enc_callback_ctrl 99 }; 100 101 const BIO_METHOD * 102 BIO_f_cipher(void) 103 { 104 return (&methods_enc); 105 } 106 107 static int 108 enc_new(BIO *bi) 109 { 110 BIO_ENC_CTX *ctx; 111 112 ctx = malloc(sizeof(BIO_ENC_CTX)); 113 if (ctx == NULL) 114 return (0); 115 EVP_CIPHER_CTX_init(&ctx->cipher); 116 117 ctx->buf_len = 0; 118 ctx->buf_off = 0; 119 ctx->cont = 1; 120 ctx->finished = 0; 121 ctx->ok = 1; 122 123 bi->init = 0; 124 bi->ptr = (char *)ctx; 125 bi->flags = 0; 126 return (1); 127 } 128 129 static int 130 enc_free(BIO *a) 131 { 132 BIO_ENC_CTX *b; 133 134 if (a == NULL) 135 return (0); 136 b = (BIO_ENC_CTX *)a->ptr; 137 EVP_CIPHER_CTX_cleanup(&(b->cipher)); 138 freezero(a->ptr, sizeof(BIO_ENC_CTX)); 139 a->ptr = NULL; 140 a->init = 0; 141 a->flags = 0; 142 return (1); 143 } 144 145 static int 146 enc_read(BIO *b, char *out, int outl) 147 { 148 int ret = 0, i; 149 BIO_ENC_CTX *ctx; 150 151 if (out == NULL) 152 return (0); 153 ctx = (BIO_ENC_CTX *)b->ptr; 154 155 if ((ctx == NULL) || (b->next_bio == NULL)) 156 return (0); 157 158 /* First check if there are bytes decoded/encoded */ 159 if (ctx->buf_len > 0) { 160 i = ctx->buf_len - ctx->buf_off; 161 if (i > outl) 162 i = outl; 163 memcpy(out, &(ctx->buf[ctx->buf_off]), i); 164 ret = i; 165 out += i; 166 outl -= i; 167 ctx->buf_off += i; 168 if (ctx->buf_len == ctx->buf_off) { 169 ctx->buf_len = 0; 170 ctx->buf_off = 0; 171 } 172 } 173 174 /* At this point, we have room of outl bytes and an empty 175 * buffer, so we should read in some more. */ 176 177 while (outl > 0) { 178 if (ctx->cont <= 0) 179 break; 180 181 /* read in at IV offset, read the EVP_Cipher 182 * documentation about why */ 183 i = BIO_read(b->next_bio, &(ctx->buf[BUF_OFFSET]), ENC_BLOCK_SIZE); 184 185 if (i <= 0) { 186 /* Should be continue next time we are called? */ 187 if (!BIO_should_retry(b->next_bio)) { 188 ctx->cont = i; 189 i = EVP_CipherFinal_ex(&(ctx->cipher), 190 (unsigned char *)ctx->buf, 191 &(ctx->buf_len)); 192 ctx->ok = i; 193 ctx->buf_off = 0; 194 } else { 195 ret = (ret == 0) ? i : ret; 196 break; 197 } 198 } else { 199 EVP_CipherUpdate(&(ctx->cipher), 200 (unsigned char *)ctx->buf, &ctx->buf_len, 201 (unsigned char *)&(ctx->buf[BUF_OFFSET]), i); 202 ctx->cont = 1; 203 /* Note: it is possible for EVP_CipherUpdate to 204 * decrypt zero bytes because this is or looks like 205 * the final block: if this happens we should retry 206 * and either read more data or decrypt the final 207 * block 208 */ 209 if (ctx->buf_len == 0) 210 continue; 211 } 212 213 if (ctx->buf_len <= outl) 214 i = ctx->buf_len; 215 else 216 i = outl; 217 if (i <= 0) 218 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 232 enc_write(BIO *b, const char *in, int inl) 233 { 234 int ret = 0, n, i; 235 BIO_ENC_CTX *ctx; 236 237 ctx = (BIO_ENC_CTX *)b->ptr; 238 ret = inl; 239 240 BIO_clear_retry_flags(b); 241 n = ctx->buf_len - ctx->buf_off; 242 while (n > 0) { 243 i = BIO_write(b->next_bio, &(ctx->buf[ctx->buf_off]), n); 244 if (i <= 0) { 245 BIO_copy_next_retry(b); 246 return (i); 247 } 248 ctx->buf_off += i; 249 n -= i; 250 } 251 /* at this point all pending data has been written */ 252 253 if ((in == NULL) || (inl <= 0)) 254 return (0); 255 256 ctx->buf_off = 0; 257 while (inl > 0) { 258 n = (inl > ENC_BLOCK_SIZE) ? ENC_BLOCK_SIZE : inl; 259 EVP_CipherUpdate(&(ctx->cipher), 260 (unsigned char *)ctx->buf, &ctx->buf_len, 261 (unsigned char *)in, n); 262 inl -= n; 263 in += n; 264 265 ctx->buf_off = 0; 266 n = ctx->buf_len; 267 while (n > 0) { 268 i = BIO_write(b->next_bio, &(ctx->buf[ctx->buf_off]), n); 269 if (i <= 0) { 270 BIO_copy_next_retry(b); 271 return (ret == inl) ? i : ret - inl; 272 } 273 n -= i; 274 ctx->buf_off += i; 275 } 276 ctx->buf_len = 0; 277 ctx->buf_off = 0; 278 } 279 BIO_copy_next_retry(b); 280 return (ret); 281 } 282 283 static long 284 enc_ctrl(BIO *b, int cmd, long num, void *ptr) 285 { 286 BIO *dbio; 287 BIO_ENC_CTX *ctx, *dctx; 288 long ret = 1; 289 int i; 290 EVP_CIPHER_CTX **c_ctx; 291 292 ctx = (BIO_ENC_CTX *)b->ptr; 293 294 switch (cmd) { 295 case BIO_CTRL_RESET: 296 ctx->ok = 1; 297 ctx->finished = 0; 298 EVP_CipherInit_ex(&(ctx->cipher), NULL, NULL, NULL, NULL, 299 ctx->cipher.encrypt); 300 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 301 break; 302 case BIO_CTRL_EOF: /* More to read */ 303 if (ctx->cont <= 0) 304 ret = 1; 305 else 306 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 307 break; 308 case BIO_CTRL_WPENDING: 309 ret = ctx->buf_len - ctx->buf_off; 310 if (ret <= 0) 311 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 312 break; 313 case BIO_CTRL_PENDING: /* More to read in buffer */ 314 ret = ctx->buf_len - ctx->buf_off; 315 if (ret <= 0) 316 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 317 break; 318 case BIO_CTRL_FLUSH: 319 /* do a final write */ 320 again: 321 while (ctx->buf_len != ctx->buf_off) { 322 i = enc_write(b, NULL, 0); 323 if (i < 0) 324 return i; 325 } 326 327 if (!ctx->finished) { 328 ctx->finished = 1; 329 ctx->buf_off = 0; 330 ret = EVP_CipherFinal_ex(&(ctx->cipher), 331 (unsigned char *)ctx->buf, 332 &(ctx->buf_len)); 333 ctx->ok = (int)ret; 334 if (ret <= 0) 335 break; 336 337 /* push out the bytes */ 338 goto again; 339 } 340 341 /* Finally flush the underlying BIO */ 342 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 343 break; 344 case BIO_C_GET_CIPHER_STATUS: 345 ret = (long)ctx->ok; 346 break; 347 case BIO_C_DO_STATE_MACHINE: 348 BIO_clear_retry_flags(b); 349 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 350 BIO_copy_next_retry(b); 351 break; 352 case BIO_C_GET_CIPHER_CTX: 353 c_ctx = (EVP_CIPHER_CTX **)ptr; 354 (*c_ctx) = &(ctx->cipher); 355 b->init = 1; 356 break; 357 case BIO_CTRL_DUP: 358 dbio = (BIO *)ptr; 359 dctx = (BIO_ENC_CTX *)dbio->ptr; 360 EVP_CIPHER_CTX_init(&dctx->cipher); 361 ret = EVP_CIPHER_CTX_copy(&dctx->cipher, &ctx->cipher); 362 if (ret) 363 dbio->init = 1; 364 break; 365 default: 366 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 367 break; 368 } 369 return (ret); 370 } 371 372 static long 373 enc_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) 374 { 375 long ret = 1; 376 377 if (b->next_bio == NULL) 378 return (0); 379 switch (cmd) { 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 int 408 BIO_set_cipher(BIO *b, const EVP_CIPHER *c, const unsigned char *k, 409 const unsigned char *i, int e) 410 { 411 BIO_ENC_CTX *ctx; 412 long (*cb)(BIO *, int, const char *, int, long, long); 413 414 if (b == NULL) 415 return 0; 416 417 if ((ctx = BIO_get_data(b)) == NULL) 418 return 0; 419 420 if ((cb = BIO_get_callback(b)) != NULL) { 421 if (cb(b, BIO_CB_CTRL, (const char *)c, BIO_CTRL_SET, e, 0L) 422 <= 0) 423 return 0; 424 } 425 426 BIO_set_init(b, 1); 427 428 if (!EVP_CipherInit_ex(&(ctx->cipher), c, NULL, k, i, e)) 429 return 0; 430 431 if (cb != NULL) 432 return cb(b, BIO_CB_CTRL, (const char *)c, BIO_CTRL_SET, e, 1L); 433 434 return 1; 435 } 436