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