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