1 /* $OpenBSD: bio_enc.c,v 1.26 2022/01/14 08:40:57 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 #include "bio_local.h" 67 #include "evp_locl.h" 68 69 static int enc_write(BIO *h, const char *buf, int num); 70 static int enc_read(BIO *h, char *buf, int size); 71 /*static int enc_puts(BIO *h, const char *str); */ 72 /*static int enc_gets(BIO *h, char *str, int size); */ 73 static long enc_ctrl(BIO *h, int cmd, long arg1, void *arg2); 74 static int enc_new(BIO *h); 75 static int enc_free(BIO *data); 76 static long enc_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fps); 77 #define ENC_BLOCK_SIZE (1024*4) 78 #define BUF_OFFSET (EVP_MAX_BLOCK_LENGTH*2) 79 80 typedef struct enc_struct { 81 int buf_len; 82 int buf_off; 83 int cont; /* <= 0 when finished */ 84 int finished; 85 int ok; /* bad decrypt */ 86 EVP_CIPHER_CTX cipher; 87 /* buf is larger than ENC_BLOCK_SIZE because EVP_DecryptUpdate 88 * can return up to a block more data than is presented to it 89 */ 90 char buf[ENC_BLOCK_SIZE + BUF_OFFSET + 2]; 91 } BIO_ENC_CTX; 92 93 static const BIO_METHOD methods_enc = { 94 .type = BIO_TYPE_CIPHER, 95 .name = "cipher", 96 .bwrite = enc_write, 97 .bread = enc_read, 98 .ctrl = enc_ctrl, 99 .create = enc_new, 100 .destroy = enc_free, 101 .callback_ctrl = enc_callback_ctrl 102 }; 103 104 const BIO_METHOD * 105 BIO_f_cipher(void) 106 { 107 return (&methods_enc); 108 } 109 110 static int 111 enc_new(BIO *bi) 112 { 113 BIO_ENC_CTX *ctx; 114 115 ctx = malloc(sizeof(BIO_ENC_CTX)); 116 if (ctx == NULL) 117 return (0); 118 EVP_CIPHER_CTX_init(&ctx->cipher); 119 120 ctx->buf_len = 0; 121 ctx->buf_off = 0; 122 ctx->cont = 1; 123 ctx->finished = 0; 124 ctx->ok = 1; 125 126 bi->init = 0; 127 bi->ptr = (char *)ctx; 128 bi->flags = 0; 129 return (1); 130 } 131 132 static int 133 enc_free(BIO *a) 134 { 135 BIO_ENC_CTX *b; 136 137 if (a == NULL) 138 return (0); 139 b = (BIO_ENC_CTX *)a->ptr; 140 EVP_CIPHER_CTX_cleanup(&(b->cipher)); 141 freezero(a->ptr, sizeof(BIO_ENC_CTX)); 142 a->ptr = NULL; 143 a->init = 0; 144 a->flags = 0; 145 return (1); 146 } 147 148 static int 149 enc_read(BIO *b, char *out, int outl) 150 { 151 int ret = 0, i; 152 BIO_ENC_CTX *ctx; 153 154 if (out == NULL) 155 return (0); 156 ctx = (BIO_ENC_CTX *)b->ptr; 157 158 if ((ctx == NULL) || (b->next_bio == NULL)) 159 return (0); 160 161 /* First check if there are bytes decoded/encoded */ 162 if (ctx->buf_len > 0) { 163 i = ctx->buf_len - ctx->buf_off; 164 if (i > outl) 165 i = outl; 166 memcpy(out, &(ctx->buf[ctx->buf_off]), i); 167 ret = i; 168 out += i; 169 outl -= i; 170 ctx->buf_off += i; 171 if (ctx->buf_len == ctx->buf_off) { 172 ctx->buf_len = 0; 173 ctx->buf_off = 0; 174 } 175 } 176 177 /* At this point, we have room of outl bytes and an empty 178 * buffer, so we should read in some more. */ 179 180 while (outl > 0) { 181 if (ctx->cont <= 0) 182 break; 183 184 /* read in at IV offset, read the EVP_Cipher 185 * documentation about why */ 186 i = BIO_read(b->next_bio, &(ctx->buf[BUF_OFFSET]), ENC_BLOCK_SIZE); 187 188 if (i <= 0) { 189 /* Should be continue next time we are called? */ 190 if (!BIO_should_retry(b->next_bio)) { 191 ctx->cont = i; 192 i = EVP_CipherFinal_ex(&(ctx->cipher), 193 (unsigned char *)ctx->buf, 194 &(ctx->buf_len)); 195 ctx->ok = i; 196 ctx->buf_off = 0; 197 } else { 198 ret = (ret == 0) ? i : ret; 199 break; 200 } 201 } else { 202 EVP_CipherUpdate(&(ctx->cipher), 203 (unsigned char *)ctx->buf, &ctx->buf_len, 204 (unsigned char *)&(ctx->buf[BUF_OFFSET]), i); 205 ctx->cont = 1; 206 /* Note: it is possible for EVP_CipherUpdate to 207 * decrypt zero bytes because this is or looks like 208 * the final block: if this happens we should retry 209 * and either read more data or decrypt the final 210 * block 211 */ 212 if (ctx->buf_len == 0) 213 continue; 214 } 215 216 if (ctx->buf_len <= outl) 217 i = ctx->buf_len; 218 else 219 i = outl; 220 if (i <= 0) 221 break; 222 memcpy(out, ctx->buf, i); 223 ret += i; 224 ctx->buf_off = i; 225 outl -= i; 226 out += i; 227 } 228 229 BIO_clear_retry_flags(b); 230 BIO_copy_next_retry(b); 231 return ((ret == 0) ? ctx->cont : ret); 232 } 233 234 static int 235 enc_write(BIO *b, const char *in, int inl) 236 { 237 int ret = 0, n, i; 238 BIO_ENC_CTX *ctx; 239 240 ctx = (BIO_ENC_CTX *)b->ptr; 241 ret = inl; 242 243 BIO_clear_retry_flags(b); 244 n = ctx->buf_len - ctx->buf_off; 245 while (n > 0) { 246 i = BIO_write(b->next_bio, &(ctx->buf[ctx->buf_off]), n); 247 if (i <= 0) { 248 BIO_copy_next_retry(b); 249 return (i); 250 } 251 ctx->buf_off += i; 252 n -= i; 253 } 254 /* at this point all pending data has been written */ 255 256 if ((in == NULL) || (inl <= 0)) 257 return (0); 258 259 ctx->buf_off = 0; 260 while (inl > 0) { 261 n = (inl > ENC_BLOCK_SIZE) ? ENC_BLOCK_SIZE : inl; 262 EVP_CipherUpdate(&(ctx->cipher), 263 (unsigned char *)ctx->buf, &ctx->buf_len, 264 (unsigned char *)in, n); 265 inl -= n; 266 in += n; 267 268 ctx->buf_off = 0; 269 n = ctx->buf_len; 270 while (n > 0) { 271 i = BIO_write(b->next_bio, &(ctx->buf[ctx->buf_off]), n); 272 if (i <= 0) { 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 287 enc_ctrl(BIO *b, int cmd, long num, void *ptr) 288 { 289 BIO *dbio; 290 BIO_ENC_CTX *ctx, *dctx; 291 long ret = 1; 292 int i; 293 EVP_CIPHER_CTX **c_ctx; 294 295 ctx = (BIO_ENC_CTX *)b->ptr; 296 297 switch (cmd) { 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 i = enc_write(b, NULL, 0); 326 if (i < 0) 327 return i; 328 } 329 330 if (!ctx->finished) { 331 ctx->finished = 1; 332 ctx->buf_off = 0; 333 ret = EVP_CipherFinal_ex(&(ctx->cipher), 334 (unsigned char *)ctx->buf, 335 &(ctx->buf_len)); 336 ctx->ok = (int)ret; 337 if (ret <= 0) 338 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 EVP_CIPHER_CTX_init(&dctx->cipher); 364 ret = EVP_CIPHER_CTX_copy(&dctx->cipher, &ctx->cipher); 365 if (ret) 366 dbio->init = 1; 367 break; 368 default: 369 ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 370 break; 371 } 372 return (ret); 373 } 374 375 static long 376 enc_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) 377 { 378 long ret = 1; 379 380 if (b->next_bio == NULL) 381 return (0); 382 switch (cmd) { 383 default: 384 ret = BIO_callback_ctrl(b->next_bio, cmd, fp); 385 break; 386 } 387 return (ret); 388 } 389 390 int 391 BIO_set_cipher(BIO *b, const EVP_CIPHER *c, const unsigned char *k, 392 const unsigned char *i, int e) 393 { 394 BIO_ENC_CTX *ctx; 395 long (*cb)(BIO *, int, const char *, int, long, long); 396 397 if (b == NULL) 398 return 0; 399 400 if ((ctx = BIO_get_data(b)) == NULL) 401 return 0; 402 403 if ((cb = BIO_get_callback(b)) != NULL) { 404 if (cb(b, BIO_CB_CTRL, (const char *)c, BIO_CTRL_SET, e, 0L) 405 <= 0) 406 return 0; 407 } 408 409 BIO_set_init(b, 1); 410 411 if (!EVP_CipherInit_ex(&(ctx->cipher), c, NULL, k, i, e)) 412 return 0; 413 414 if (cb != NULL) 415 return cb(b, BIO_CB_CTRL, (const char *)c, BIO_CTRL_SET, e, 1L); 416 417 return 1; 418 } 419