1 /* 2 * Copyright 1995-2026 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #define OPENSSL_SUPPRESS_DEPRECATED /* for BIO_get_callback */ 11 12 #include <stdio.h> 13 #include <errno.h> 14 #include "internal/cryptlib.h" 15 #include <openssl/buffer.h> 16 #include <openssl/evp.h> 17 #include "internal/bio.h" 18 19 static int enc_write(BIO *h, const char *buf, int num); 20 static int enc_read(BIO *h, char *buf, int size); 21 static long enc_ctrl(BIO *h, int cmd, long arg1, void *arg2); 22 static int enc_new(BIO *h); 23 static int enc_free(BIO *data); 24 static long enc_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fps); 25 #define ENC_BLOCK_SIZE (1024 * 4) 26 #define ENC_MIN_CHUNK (256) 27 #define BUF_OFFSET (ENC_MIN_CHUNK + EVP_MAX_BLOCK_LENGTH) 28 29 typedef struct enc_struct { 30 int buf_len; 31 int buf_off; 32 int cont; /* <= 0 when finished */ 33 int finished; 34 int ok; /* bad decrypt */ 35 EVP_CIPHER_CTX *cipher; 36 unsigned char *read_start, *read_end; 37 /* 38 * buf is larger than ENC_BLOCK_SIZE because EVP_DecryptUpdate can return 39 * up to a block more data than is presented to it 40 */ 41 unsigned char buf[BUF_OFFSET + ENC_BLOCK_SIZE]; 42 } BIO_ENC_CTX; 43 44 static const BIO_METHOD methods_enc = { 45 BIO_TYPE_CIPHER, 46 "cipher", 47 bwrite_conv, 48 enc_write, 49 bread_conv, 50 enc_read, 51 NULL, /* enc_puts, */ 52 NULL, /* enc_gets, */ 53 enc_ctrl, 54 enc_new, 55 enc_free, 56 enc_callback_ctrl, 57 }; 58 59 const BIO_METHOD *BIO_f_cipher(void) 60 { 61 return &methods_enc; 62 } 63 64 static int enc_new(BIO *bi) 65 { 66 BIO_ENC_CTX *ctx; 67 68 if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) 69 return 0; 70 71 ctx->cipher = EVP_CIPHER_CTX_new(); 72 if (ctx->cipher == NULL) { 73 OPENSSL_free(ctx); 74 return 0; 75 } 76 ctx->cont = 1; 77 ctx->ok = 1; 78 ctx->read_end = ctx->read_start = &(ctx->buf[BUF_OFFSET]); 79 BIO_set_data(bi, ctx); 80 BIO_set_init(bi, 1); 81 82 return 1; 83 } 84 85 static int enc_free(BIO *a) 86 { 87 BIO_ENC_CTX *b; 88 89 if (a == NULL) 90 return 0; 91 92 b = BIO_get_data(a); 93 if (b == NULL) 94 return 0; 95 96 EVP_CIPHER_CTX_free(b->cipher); 97 OPENSSL_clear_free(b, sizeof(BIO_ENC_CTX)); 98 BIO_set_data(a, NULL); 99 BIO_set_init(a, 0); 100 101 return 1; 102 } 103 104 static int enc_read(BIO *b, char *out, int outl) 105 { 106 int ret = 0, i, blocksize; 107 BIO_ENC_CTX *ctx; 108 BIO *next; 109 110 if (out == NULL) 111 return 0; 112 ctx = BIO_get_data(b); 113 114 next = BIO_next(b); 115 if ((ctx == NULL) || (next == NULL)) 116 return 0; 117 118 /* First check if there are bytes decoded/encoded */ 119 if (ctx->buf_len > 0) { 120 i = ctx->buf_len - ctx->buf_off; 121 if (i > outl) 122 i = outl; 123 memcpy(out, &(ctx->buf[ctx->buf_off]), i); 124 ret = i; 125 out += i; 126 outl -= i; 127 ctx->buf_off += i; 128 if (ctx->buf_len == ctx->buf_off) { 129 ctx->buf_len = 0; 130 ctx->buf_off = 0; 131 } 132 } 133 134 blocksize = EVP_CIPHER_CTX_get_block_size(ctx->cipher); 135 136 if (blocksize == 0) 137 return 0; 138 139 if (blocksize == 1) 140 blocksize = 0; 141 142 /* 143 * At this point, we have room of outl bytes and an empty buffer, so we 144 * should read in some more. 145 */ 146 147 while (outl > 0) { 148 if (ctx->cont <= 0) 149 break; 150 151 if (ctx->read_start == ctx->read_end) { /* time to read more data */ 152 ctx->read_end = ctx->read_start = &(ctx->buf[BUF_OFFSET]); 153 i = BIO_read(next, ctx->read_start, ENC_BLOCK_SIZE); 154 if (i > 0) 155 ctx->read_end += i; 156 } else { 157 i = ctx->read_end - ctx->read_start; 158 } 159 160 if (i <= 0) { 161 /* Should be continue next time we are called? */ 162 if (!BIO_should_retry(next)) { 163 ctx->cont = i; 164 ctx->finished = 1; 165 i = EVP_CipherFinal_ex(ctx->cipher, 166 ctx->buf, &(ctx->buf_len)); 167 ctx->ok = i; 168 ctx->buf_off = 0; 169 } else { 170 ret = (ret == 0) ? i : ret; 171 break; 172 } 173 } else { 174 if (outl > ENC_MIN_CHUNK) { 175 /* 176 * Depending on flags block cipher decrypt can write 177 * one extra block and then back off, i.e. output buffer 178 * has to accommodate extra block... 179 */ 180 int j = outl - blocksize, buf_len; 181 182 if (!EVP_CipherUpdate(ctx->cipher, 183 (unsigned char *)out, &buf_len, 184 ctx->read_start, i > j ? j : i)) { 185 BIO_clear_retry_flags(b); 186 return 0; 187 } 188 ret += buf_len; 189 out += buf_len; 190 outl -= buf_len; 191 192 if ((i -= j) <= 0) { 193 ctx->read_start = ctx->read_end; 194 continue; 195 } 196 ctx->read_start += j; 197 } 198 if (i > ENC_MIN_CHUNK) 199 i = ENC_MIN_CHUNK; 200 if (!EVP_CipherUpdate(ctx->cipher, 201 ctx->buf, &ctx->buf_len, 202 ctx->read_start, i)) { 203 BIO_clear_retry_flags(b); 204 ctx->ok = 0; 205 return 0; 206 } 207 ctx->read_start += i; 208 ctx->cont = 1; 209 /* 210 * Note: it is possible for EVP_CipherUpdate to decrypt zero 211 * bytes because this is or looks like the final block: if this 212 * happens we should retry and either read more data or decrypt 213 * the final block 214 */ 215 if (ctx->buf_len == 0) 216 continue; 217 } 218 219 if (ctx->buf_len <= outl) 220 i = ctx->buf_len; 221 else 222 i = outl; 223 if (i <= 0) 224 break; 225 memcpy(out, ctx->buf, i); 226 ret += i; 227 ctx->buf_off = i; 228 outl -= i; 229 out += i; 230 } 231 232 BIO_clear_retry_flags(b); 233 BIO_copy_next_retry(b); 234 return ((ret == 0) ? ctx->cont : ret); 235 } 236 237 static int enc_write(BIO *b, const char *in, int inl) 238 { 239 int ret = 0, n, i; 240 BIO_ENC_CTX *ctx; 241 BIO *next; 242 243 ctx = BIO_get_data(b); 244 next = BIO_next(b); 245 if ((ctx == NULL) || (next == NULL)) 246 return 0; 247 248 ret = inl; 249 250 BIO_clear_retry_flags(b); 251 n = ctx->buf_len - ctx->buf_off; 252 while (n > 0) { 253 i = BIO_write(next, &(ctx->buf[ctx->buf_off]), n); 254 if (i <= 0) { 255 BIO_copy_next_retry(b); 256 return i; 257 } 258 ctx->buf_off += i; 259 n -= i; 260 } 261 /* at this point all pending data has been written */ 262 263 if ((in == NULL) || (inl <= 0)) 264 return 0; 265 266 ctx->buf_off = 0; 267 while (inl > 0) { 268 n = (inl > ENC_BLOCK_SIZE) ? ENC_BLOCK_SIZE : inl; 269 if (!EVP_CipherUpdate(ctx->cipher, 270 ctx->buf, &ctx->buf_len, 271 (const unsigned char *)in, n)) { 272 BIO_clear_retry_flags(b); 273 ctx->ok = 0; 274 return 0; 275 } 276 inl -= n; 277 in += n; 278 279 ctx->buf_off = 0; 280 n = ctx->buf_len; 281 while (n > 0) { 282 i = BIO_write(next, &(ctx->buf[ctx->buf_off]), n); 283 if (i <= 0) { 284 BIO_copy_next_retry(b); 285 return (ret == inl) ? i : ret - inl; 286 } 287 n -= i; 288 ctx->buf_off += i; 289 } 290 ctx->buf_len = 0; 291 ctx->buf_off = 0; 292 } 293 BIO_copy_next_retry(b); 294 return ret; 295 } 296 297 static long 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 BIO *next; 305 int pend; 306 307 ctx = BIO_get_data(b); 308 next = BIO_next(b); 309 if (ctx == NULL) 310 return 0; 311 312 switch (cmd) { 313 case BIO_CTRL_RESET: 314 ctx->ok = 1; 315 ctx->finished = 0; 316 if (!EVP_CipherInit_ex(ctx->cipher, NULL, NULL, NULL, NULL, 317 EVP_CIPHER_CTX_is_encrypting(ctx->cipher))) 318 return 0; 319 ret = BIO_ctrl(next, cmd, num, ptr); 320 break; 321 case BIO_CTRL_EOF: /* More to read */ 322 if (ctx->cont <= 0) 323 ret = 1; 324 else 325 ret = BIO_ctrl(next, cmd, num, ptr); 326 break; 327 case BIO_CTRL_WPENDING: 328 ret = ctx->buf_len - ctx->buf_off; 329 if (ret <= 0) 330 ret = BIO_ctrl(next, cmd, num, ptr); 331 break; 332 case BIO_CTRL_PENDING: /* More to read in buffer */ 333 ret = ctx->buf_len - ctx->buf_off; 334 if (ret <= 0) 335 ret = BIO_ctrl(next, cmd, num, ptr); 336 break; 337 case BIO_CTRL_FLUSH: 338 /* do a final write */ 339 again: 340 while (ctx->buf_len != ctx->buf_off) { 341 pend = ctx->buf_len - ctx->buf_off; 342 i = enc_write(b, NULL, 0); 343 /* 344 * i should never be > 0 here because we didn't ask to write any 345 * new data. We stop if we get an error or we failed to make any 346 * progress writing pending data. 347 */ 348 if (i < 0 || (ctx->buf_len - ctx->buf_off) == pend) 349 return i; 350 } 351 352 if (!ctx->finished) { 353 ctx->finished = 1; 354 ctx->buf_off = 0; 355 ret = EVP_CipherFinal_ex(ctx->cipher, 356 (unsigned char *)ctx->buf, 357 &(ctx->buf_len)); 358 ctx->ok = (int)ret; 359 if (ret <= 0) 360 break; 361 362 /* push out the bytes */ 363 goto again; 364 } 365 366 /* Finally flush the underlying BIO */ 367 ret = BIO_ctrl(next, cmd, num, ptr); 368 BIO_copy_next_retry(b); 369 break; 370 case BIO_C_GET_CIPHER_STATUS: 371 ret = (long)ctx->ok; 372 break; 373 case BIO_C_DO_STATE_MACHINE: 374 BIO_clear_retry_flags(b); 375 ret = BIO_ctrl(next, cmd, num, ptr); 376 BIO_copy_next_retry(b); 377 break; 378 case BIO_C_GET_CIPHER_CTX: 379 c_ctx = (EVP_CIPHER_CTX **)ptr; 380 *c_ctx = ctx->cipher; 381 BIO_set_init(b, 1); 382 break; 383 case BIO_CTRL_DUP: 384 dbio = (BIO *)ptr; 385 dctx = BIO_get_data(dbio); 386 ret = EVP_CIPHER_CTX_copy(dctx->cipher, ctx->cipher); 387 if (ret) 388 BIO_set_init(dbio, 1); 389 break; 390 default: 391 ret = BIO_ctrl(next, cmd, num, ptr); 392 break; 393 } 394 return ret; 395 } 396 397 static long enc_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) 398 { 399 BIO *next = BIO_next(b); 400 401 if (next == NULL) 402 return 0; 403 404 return BIO_callback_ctrl(next, cmd, fp); 405 } 406 407 int BIO_set_cipher(BIO *b, const EVP_CIPHER *c, const unsigned char *k, 408 const unsigned char *i, int e) 409 { 410 BIO_ENC_CTX *ctx; 411 BIO_callback_fn_ex callback_ex; 412 #ifndef OPENSSL_NO_DEPRECATED_3_0 413 long (*callback)(struct bio_st *, int, const char *, int, long, long) = NULL; 414 #endif 415 416 ctx = BIO_get_data(b); 417 if (ctx == NULL) 418 return 0; 419 420 if ((callback_ex = BIO_get_callback_ex(b)) != NULL) { 421 if (callback_ex(b, BIO_CB_CTRL, (const char *)c, 0, BIO_CTRL_SET, 422 e, 1, NULL) 423 <= 0) 424 return 0; 425 } 426 #ifndef OPENSSL_NO_DEPRECATED_3_0 427 else { 428 callback = BIO_get_callback(b); 429 430 if ((callback != NULL) && (callback(b, BIO_CB_CTRL, (const char *)c, BIO_CTRL_SET, e, 0L) <= 0)) 431 return 0; 432 } 433 #endif 434 435 BIO_set_init(b, 1); 436 437 if (!EVP_CipherInit_ex(ctx->cipher, c, NULL, k, i, e)) 438 return 0; 439 440 if (callback_ex != NULL) 441 return callback_ex(b, BIO_CB_CTRL | BIO_CB_RETURN, (const char *)c, 0, 442 BIO_CTRL_SET, e, 1, NULL); 443 #ifndef OPENSSL_NO_DEPRECATED_3_0 444 else if (callback != NULL) 445 return callback(b, BIO_CB_CTRL, (const char *)c, BIO_CTRL_SET, e, 1L); 446 #endif 447 return 1; 448 } 449