11cb0ef41Sopenharmony_ci/* 21cb0ef41Sopenharmony_ci * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. 31cb0ef41Sopenharmony_ci * 41cb0ef41Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 51cb0ef41Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 61cb0ef41Sopenharmony_ci * in the file LICENSE in the source distribution or at 71cb0ef41Sopenharmony_ci * https://www.openssl.org/source/license.html 81cb0ef41Sopenharmony_ci */ 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ci#define OPENSSL_SUPPRESS_DEPRECATED /* for BIO_get_callback */ 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_ci#include <stdio.h> 131cb0ef41Sopenharmony_ci#include <errno.h> 141cb0ef41Sopenharmony_ci#include "internal/cryptlib.h" 151cb0ef41Sopenharmony_ci#include <openssl/buffer.h> 161cb0ef41Sopenharmony_ci#include <openssl/evp.h> 171cb0ef41Sopenharmony_ci#include "internal/bio.h" 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_cistatic int enc_write(BIO *h, const char *buf, int num); 201cb0ef41Sopenharmony_cistatic int enc_read(BIO *h, char *buf, int size); 211cb0ef41Sopenharmony_cistatic long enc_ctrl(BIO *h, int cmd, long arg1, void *arg2); 221cb0ef41Sopenharmony_cistatic int enc_new(BIO *h); 231cb0ef41Sopenharmony_cistatic int enc_free(BIO *data); 241cb0ef41Sopenharmony_cistatic long enc_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fps); 251cb0ef41Sopenharmony_ci#define ENC_BLOCK_SIZE (1024*4) 261cb0ef41Sopenharmony_ci#define ENC_MIN_CHUNK (256) 271cb0ef41Sopenharmony_ci#define BUF_OFFSET (ENC_MIN_CHUNK + EVP_MAX_BLOCK_LENGTH) 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_citypedef struct enc_struct { 301cb0ef41Sopenharmony_ci int buf_len; 311cb0ef41Sopenharmony_ci int buf_off; 321cb0ef41Sopenharmony_ci int cont; /* <= 0 when finished */ 331cb0ef41Sopenharmony_ci int finished; 341cb0ef41Sopenharmony_ci int ok; /* bad decrypt */ 351cb0ef41Sopenharmony_ci EVP_CIPHER_CTX *cipher; 361cb0ef41Sopenharmony_ci unsigned char *read_start, *read_end; 371cb0ef41Sopenharmony_ci /* 381cb0ef41Sopenharmony_ci * buf is larger than ENC_BLOCK_SIZE because EVP_DecryptUpdate can return 391cb0ef41Sopenharmony_ci * up to a block more data than is presented to it 401cb0ef41Sopenharmony_ci */ 411cb0ef41Sopenharmony_ci unsigned char buf[BUF_OFFSET + ENC_BLOCK_SIZE]; 421cb0ef41Sopenharmony_ci} BIO_ENC_CTX; 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_cistatic const BIO_METHOD methods_enc = { 451cb0ef41Sopenharmony_ci BIO_TYPE_CIPHER, 461cb0ef41Sopenharmony_ci "cipher", 471cb0ef41Sopenharmony_ci bwrite_conv, 481cb0ef41Sopenharmony_ci enc_write, 491cb0ef41Sopenharmony_ci bread_conv, 501cb0ef41Sopenharmony_ci enc_read, 511cb0ef41Sopenharmony_ci NULL, /* enc_puts, */ 521cb0ef41Sopenharmony_ci NULL, /* enc_gets, */ 531cb0ef41Sopenharmony_ci enc_ctrl, 541cb0ef41Sopenharmony_ci enc_new, 551cb0ef41Sopenharmony_ci enc_free, 561cb0ef41Sopenharmony_ci enc_callback_ctrl, 571cb0ef41Sopenharmony_ci}; 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_ciconst BIO_METHOD *BIO_f_cipher(void) 601cb0ef41Sopenharmony_ci{ 611cb0ef41Sopenharmony_ci return &methods_enc; 621cb0ef41Sopenharmony_ci} 631cb0ef41Sopenharmony_ci 641cb0ef41Sopenharmony_cistatic int enc_new(BIO *bi) 651cb0ef41Sopenharmony_ci{ 661cb0ef41Sopenharmony_ci BIO_ENC_CTX *ctx; 671cb0ef41Sopenharmony_ci 681cb0ef41Sopenharmony_ci if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) { 691cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); 701cb0ef41Sopenharmony_ci return 0; 711cb0ef41Sopenharmony_ci } 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ci ctx->cipher = EVP_CIPHER_CTX_new(); 741cb0ef41Sopenharmony_ci if (ctx->cipher == NULL) { 751cb0ef41Sopenharmony_ci OPENSSL_free(ctx); 761cb0ef41Sopenharmony_ci return 0; 771cb0ef41Sopenharmony_ci } 781cb0ef41Sopenharmony_ci ctx->cont = 1; 791cb0ef41Sopenharmony_ci ctx->ok = 1; 801cb0ef41Sopenharmony_ci ctx->read_end = ctx->read_start = &(ctx->buf[BUF_OFFSET]); 811cb0ef41Sopenharmony_ci BIO_set_data(bi, ctx); 821cb0ef41Sopenharmony_ci BIO_set_init(bi, 1); 831cb0ef41Sopenharmony_ci 841cb0ef41Sopenharmony_ci return 1; 851cb0ef41Sopenharmony_ci} 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_cistatic int enc_free(BIO *a) 881cb0ef41Sopenharmony_ci{ 891cb0ef41Sopenharmony_ci BIO_ENC_CTX *b; 901cb0ef41Sopenharmony_ci 911cb0ef41Sopenharmony_ci if (a == NULL) 921cb0ef41Sopenharmony_ci return 0; 931cb0ef41Sopenharmony_ci 941cb0ef41Sopenharmony_ci b = BIO_get_data(a); 951cb0ef41Sopenharmony_ci if (b == NULL) 961cb0ef41Sopenharmony_ci return 0; 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_ci EVP_CIPHER_CTX_free(b->cipher); 991cb0ef41Sopenharmony_ci OPENSSL_clear_free(b, sizeof(BIO_ENC_CTX)); 1001cb0ef41Sopenharmony_ci BIO_set_data(a, NULL); 1011cb0ef41Sopenharmony_ci BIO_set_init(a, 0); 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_ci return 1; 1041cb0ef41Sopenharmony_ci} 1051cb0ef41Sopenharmony_ci 1061cb0ef41Sopenharmony_cistatic int enc_read(BIO *b, char *out, int outl) 1071cb0ef41Sopenharmony_ci{ 1081cb0ef41Sopenharmony_ci int ret = 0, i, blocksize; 1091cb0ef41Sopenharmony_ci BIO_ENC_CTX *ctx; 1101cb0ef41Sopenharmony_ci BIO *next; 1111cb0ef41Sopenharmony_ci 1121cb0ef41Sopenharmony_ci if (out == NULL) 1131cb0ef41Sopenharmony_ci return 0; 1141cb0ef41Sopenharmony_ci ctx = BIO_get_data(b); 1151cb0ef41Sopenharmony_ci 1161cb0ef41Sopenharmony_ci next = BIO_next(b); 1171cb0ef41Sopenharmony_ci if ((ctx == NULL) || (next == NULL)) 1181cb0ef41Sopenharmony_ci return 0; 1191cb0ef41Sopenharmony_ci 1201cb0ef41Sopenharmony_ci /* First check if there are bytes decoded/encoded */ 1211cb0ef41Sopenharmony_ci if (ctx->buf_len > 0) { 1221cb0ef41Sopenharmony_ci i = ctx->buf_len - ctx->buf_off; 1231cb0ef41Sopenharmony_ci if (i > outl) 1241cb0ef41Sopenharmony_ci i = outl; 1251cb0ef41Sopenharmony_ci memcpy(out, &(ctx->buf[ctx->buf_off]), i); 1261cb0ef41Sopenharmony_ci ret = i; 1271cb0ef41Sopenharmony_ci out += i; 1281cb0ef41Sopenharmony_ci outl -= i; 1291cb0ef41Sopenharmony_ci ctx->buf_off += i; 1301cb0ef41Sopenharmony_ci if (ctx->buf_len == ctx->buf_off) { 1311cb0ef41Sopenharmony_ci ctx->buf_len = 0; 1321cb0ef41Sopenharmony_ci ctx->buf_off = 0; 1331cb0ef41Sopenharmony_ci } 1341cb0ef41Sopenharmony_ci } 1351cb0ef41Sopenharmony_ci 1361cb0ef41Sopenharmony_ci blocksize = EVP_CIPHER_CTX_get_block_size(ctx->cipher); 1371cb0ef41Sopenharmony_ci if (blocksize == 1) 1381cb0ef41Sopenharmony_ci blocksize = 0; 1391cb0ef41Sopenharmony_ci 1401cb0ef41Sopenharmony_ci /* 1411cb0ef41Sopenharmony_ci * At this point, we have room of outl bytes and an empty buffer, so we 1421cb0ef41Sopenharmony_ci * should read in some more. 1431cb0ef41Sopenharmony_ci */ 1441cb0ef41Sopenharmony_ci 1451cb0ef41Sopenharmony_ci while (outl > 0) { 1461cb0ef41Sopenharmony_ci if (ctx->cont <= 0) 1471cb0ef41Sopenharmony_ci break; 1481cb0ef41Sopenharmony_ci 1491cb0ef41Sopenharmony_ci if (ctx->read_start == ctx->read_end) { /* time to read more data */ 1501cb0ef41Sopenharmony_ci ctx->read_end = ctx->read_start = &(ctx->buf[BUF_OFFSET]); 1511cb0ef41Sopenharmony_ci i = BIO_read(next, ctx->read_start, ENC_BLOCK_SIZE); 1521cb0ef41Sopenharmony_ci if (i > 0) 1531cb0ef41Sopenharmony_ci ctx->read_end += i; 1541cb0ef41Sopenharmony_ci } else { 1551cb0ef41Sopenharmony_ci i = ctx->read_end - ctx->read_start; 1561cb0ef41Sopenharmony_ci } 1571cb0ef41Sopenharmony_ci 1581cb0ef41Sopenharmony_ci if (i <= 0) { 1591cb0ef41Sopenharmony_ci /* Should be continue next time we are called? */ 1601cb0ef41Sopenharmony_ci if (!BIO_should_retry(next)) { 1611cb0ef41Sopenharmony_ci ctx->cont = i; 1621cb0ef41Sopenharmony_ci i = EVP_CipherFinal_ex(ctx->cipher, 1631cb0ef41Sopenharmony_ci ctx->buf, &(ctx->buf_len)); 1641cb0ef41Sopenharmony_ci ctx->ok = i; 1651cb0ef41Sopenharmony_ci ctx->buf_off = 0; 1661cb0ef41Sopenharmony_ci } else { 1671cb0ef41Sopenharmony_ci ret = (ret == 0) ? i : ret; 1681cb0ef41Sopenharmony_ci break; 1691cb0ef41Sopenharmony_ci } 1701cb0ef41Sopenharmony_ci } else { 1711cb0ef41Sopenharmony_ci if (outl > ENC_MIN_CHUNK) { 1721cb0ef41Sopenharmony_ci /* 1731cb0ef41Sopenharmony_ci * Depending on flags block cipher decrypt can write 1741cb0ef41Sopenharmony_ci * one extra block and then back off, i.e. output buffer 1751cb0ef41Sopenharmony_ci * has to accommodate extra block... 1761cb0ef41Sopenharmony_ci */ 1771cb0ef41Sopenharmony_ci int j = outl - blocksize, buf_len; 1781cb0ef41Sopenharmony_ci 1791cb0ef41Sopenharmony_ci if (!EVP_CipherUpdate(ctx->cipher, 1801cb0ef41Sopenharmony_ci (unsigned char *)out, &buf_len, 1811cb0ef41Sopenharmony_ci ctx->read_start, i > j ? j : i)) { 1821cb0ef41Sopenharmony_ci BIO_clear_retry_flags(b); 1831cb0ef41Sopenharmony_ci return 0; 1841cb0ef41Sopenharmony_ci } 1851cb0ef41Sopenharmony_ci ret += buf_len; 1861cb0ef41Sopenharmony_ci out += buf_len; 1871cb0ef41Sopenharmony_ci outl -= buf_len; 1881cb0ef41Sopenharmony_ci 1891cb0ef41Sopenharmony_ci if ((i -= j) <= 0) { 1901cb0ef41Sopenharmony_ci ctx->read_start = ctx->read_end; 1911cb0ef41Sopenharmony_ci continue; 1921cb0ef41Sopenharmony_ci } 1931cb0ef41Sopenharmony_ci ctx->read_start += j; 1941cb0ef41Sopenharmony_ci } 1951cb0ef41Sopenharmony_ci if (i > ENC_MIN_CHUNK) 1961cb0ef41Sopenharmony_ci i = ENC_MIN_CHUNK; 1971cb0ef41Sopenharmony_ci if (!EVP_CipherUpdate(ctx->cipher, 1981cb0ef41Sopenharmony_ci ctx->buf, &ctx->buf_len, 1991cb0ef41Sopenharmony_ci ctx->read_start, i)) { 2001cb0ef41Sopenharmony_ci BIO_clear_retry_flags(b); 2011cb0ef41Sopenharmony_ci ctx->ok = 0; 2021cb0ef41Sopenharmony_ci return 0; 2031cb0ef41Sopenharmony_ci } 2041cb0ef41Sopenharmony_ci ctx->read_start += i; 2051cb0ef41Sopenharmony_ci ctx->cont = 1; 2061cb0ef41Sopenharmony_ci /* 2071cb0ef41Sopenharmony_ci * Note: it is possible for EVP_CipherUpdate to decrypt zero 2081cb0ef41Sopenharmony_ci * bytes because this is or looks like the final block: if this 2091cb0ef41Sopenharmony_ci * happens we should retry and either read more data or decrypt 2101cb0ef41Sopenharmony_ci * the final block 2111cb0ef41Sopenharmony_ci */ 2121cb0ef41Sopenharmony_ci if (ctx->buf_len == 0) 2131cb0ef41Sopenharmony_ci continue; 2141cb0ef41Sopenharmony_ci } 2151cb0ef41Sopenharmony_ci 2161cb0ef41Sopenharmony_ci if (ctx->buf_len <= outl) 2171cb0ef41Sopenharmony_ci i = ctx->buf_len; 2181cb0ef41Sopenharmony_ci else 2191cb0ef41Sopenharmony_ci i = outl; 2201cb0ef41Sopenharmony_ci if (i <= 0) 2211cb0ef41Sopenharmony_ci break; 2221cb0ef41Sopenharmony_ci memcpy(out, ctx->buf, i); 2231cb0ef41Sopenharmony_ci ret += i; 2241cb0ef41Sopenharmony_ci ctx->buf_off = i; 2251cb0ef41Sopenharmony_ci outl -= i; 2261cb0ef41Sopenharmony_ci out += i; 2271cb0ef41Sopenharmony_ci } 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_ci BIO_clear_retry_flags(b); 2301cb0ef41Sopenharmony_ci BIO_copy_next_retry(b); 2311cb0ef41Sopenharmony_ci return ((ret == 0) ? ctx->cont : ret); 2321cb0ef41Sopenharmony_ci} 2331cb0ef41Sopenharmony_ci 2341cb0ef41Sopenharmony_cistatic int enc_write(BIO *b, const char *in, int inl) 2351cb0ef41Sopenharmony_ci{ 2361cb0ef41Sopenharmony_ci int ret = 0, n, i; 2371cb0ef41Sopenharmony_ci BIO_ENC_CTX *ctx; 2381cb0ef41Sopenharmony_ci BIO *next; 2391cb0ef41Sopenharmony_ci 2401cb0ef41Sopenharmony_ci ctx = BIO_get_data(b); 2411cb0ef41Sopenharmony_ci next = BIO_next(b); 2421cb0ef41Sopenharmony_ci if ((ctx == NULL) || (next == NULL)) 2431cb0ef41Sopenharmony_ci return 0; 2441cb0ef41Sopenharmony_ci 2451cb0ef41Sopenharmony_ci ret = inl; 2461cb0ef41Sopenharmony_ci 2471cb0ef41Sopenharmony_ci BIO_clear_retry_flags(b); 2481cb0ef41Sopenharmony_ci n = ctx->buf_len - ctx->buf_off; 2491cb0ef41Sopenharmony_ci while (n > 0) { 2501cb0ef41Sopenharmony_ci i = BIO_write(next, &(ctx->buf[ctx->buf_off]), n); 2511cb0ef41Sopenharmony_ci if (i <= 0) { 2521cb0ef41Sopenharmony_ci BIO_copy_next_retry(b); 2531cb0ef41Sopenharmony_ci return i; 2541cb0ef41Sopenharmony_ci } 2551cb0ef41Sopenharmony_ci ctx->buf_off += i; 2561cb0ef41Sopenharmony_ci n -= i; 2571cb0ef41Sopenharmony_ci } 2581cb0ef41Sopenharmony_ci /* at this point all pending data has been written */ 2591cb0ef41Sopenharmony_ci 2601cb0ef41Sopenharmony_ci if ((in == NULL) || (inl <= 0)) 2611cb0ef41Sopenharmony_ci return 0; 2621cb0ef41Sopenharmony_ci 2631cb0ef41Sopenharmony_ci ctx->buf_off = 0; 2641cb0ef41Sopenharmony_ci while (inl > 0) { 2651cb0ef41Sopenharmony_ci n = (inl > ENC_BLOCK_SIZE) ? ENC_BLOCK_SIZE : inl; 2661cb0ef41Sopenharmony_ci if (!EVP_CipherUpdate(ctx->cipher, 2671cb0ef41Sopenharmony_ci ctx->buf, &ctx->buf_len, 2681cb0ef41Sopenharmony_ci (const unsigned char *)in, n)) { 2691cb0ef41Sopenharmony_ci BIO_clear_retry_flags(b); 2701cb0ef41Sopenharmony_ci ctx->ok = 0; 2711cb0ef41Sopenharmony_ci return 0; 2721cb0ef41Sopenharmony_ci } 2731cb0ef41Sopenharmony_ci inl -= n; 2741cb0ef41Sopenharmony_ci in += n; 2751cb0ef41Sopenharmony_ci 2761cb0ef41Sopenharmony_ci ctx->buf_off = 0; 2771cb0ef41Sopenharmony_ci n = ctx->buf_len; 2781cb0ef41Sopenharmony_ci while (n > 0) { 2791cb0ef41Sopenharmony_ci i = BIO_write(next, &(ctx->buf[ctx->buf_off]), n); 2801cb0ef41Sopenharmony_ci if (i <= 0) { 2811cb0ef41Sopenharmony_ci BIO_copy_next_retry(b); 2821cb0ef41Sopenharmony_ci return (ret == inl) ? i : ret - inl; 2831cb0ef41Sopenharmony_ci } 2841cb0ef41Sopenharmony_ci n -= i; 2851cb0ef41Sopenharmony_ci ctx->buf_off += i; 2861cb0ef41Sopenharmony_ci } 2871cb0ef41Sopenharmony_ci ctx->buf_len = 0; 2881cb0ef41Sopenharmony_ci ctx->buf_off = 0; 2891cb0ef41Sopenharmony_ci } 2901cb0ef41Sopenharmony_ci BIO_copy_next_retry(b); 2911cb0ef41Sopenharmony_ci return ret; 2921cb0ef41Sopenharmony_ci} 2931cb0ef41Sopenharmony_ci 2941cb0ef41Sopenharmony_cistatic long enc_ctrl(BIO *b, int cmd, long num, void *ptr) 2951cb0ef41Sopenharmony_ci{ 2961cb0ef41Sopenharmony_ci BIO *dbio; 2971cb0ef41Sopenharmony_ci BIO_ENC_CTX *ctx, *dctx; 2981cb0ef41Sopenharmony_ci long ret = 1; 2991cb0ef41Sopenharmony_ci int i; 3001cb0ef41Sopenharmony_ci EVP_CIPHER_CTX **c_ctx; 3011cb0ef41Sopenharmony_ci BIO *next; 3021cb0ef41Sopenharmony_ci int pend; 3031cb0ef41Sopenharmony_ci 3041cb0ef41Sopenharmony_ci ctx = BIO_get_data(b); 3051cb0ef41Sopenharmony_ci next = BIO_next(b); 3061cb0ef41Sopenharmony_ci if (ctx == NULL) 3071cb0ef41Sopenharmony_ci return 0; 3081cb0ef41Sopenharmony_ci 3091cb0ef41Sopenharmony_ci switch (cmd) { 3101cb0ef41Sopenharmony_ci case BIO_CTRL_RESET: 3111cb0ef41Sopenharmony_ci ctx->ok = 1; 3121cb0ef41Sopenharmony_ci ctx->finished = 0; 3131cb0ef41Sopenharmony_ci if (!EVP_CipherInit_ex(ctx->cipher, NULL, NULL, NULL, NULL, 3141cb0ef41Sopenharmony_ci EVP_CIPHER_CTX_is_encrypting(ctx->cipher))) 3151cb0ef41Sopenharmony_ci return 0; 3161cb0ef41Sopenharmony_ci ret = BIO_ctrl(next, cmd, num, ptr); 3171cb0ef41Sopenharmony_ci break; 3181cb0ef41Sopenharmony_ci case BIO_CTRL_EOF: /* More to read */ 3191cb0ef41Sopenharmony_ci if (ctx->cont <= 0) 3201cb0ef41Sopenharmony_ci ret = 1; 3211cb0ef41Sopenharmony_ci else 3221cb0ef41Sopenharmony_ci ret = BIO_ctrl(next, cmd, num, ptr); 3231cb0ef41Sopenharmony_ci break; 3241cb0ef41Sopenharmony_ci case BIO_CTRL_WPENDING: 3251cb0ef41Sopenharmony_ci ret = ctx->buf_len - ctx->buf_off; 3261cb0ef41Sopenharmony_ci if (ret <= 0) 3271cb0ef41Sopenharmony_ci ret = BIO_ctrl(next, cmd, num, ptr); 3281cb0ef41Sopenharmony_ci break; 3291cb0ef41Sopenharmony_ci case BIO_CTRL_PENDING: /* More to read in buffer */ 3301cb0ef41Sopenharmony_ci ret = ctx->buf_len - ctx->buf_off; 3311cb0ef41Sopenharmony_ci if (ret <= 0) 3321cb0ef41Sopenharmony_ci ret = BIO_ctrl(next, cmd, num, ptr); 3331cb0ef41Sopenharmony_ci break; 3341cb0ef41Sopenharmony_ci case BIO_CTRL_FLUSH: 3351cb0ef41Sopenharmony_ci /* do a final write */ 3361cb0ef41Sopenharmony_ci again: 3371cb0ef41Sopenharmony_ci while (ctx->buf_len != ctx->buf_off) { 3381cb0ef41Sopenharmony_ci pend = ctx->buf_len - ctx->buf_off; 3391cb0ef41Sopenharmony_ci i = enc_write(b, NULL, 0); 3401cb0ef41Sopenharmony_ci /* 3411cb0ef41Sopenharmony_ci * i should never be > 0 here because we didn't ask to write any 3421cb0ef41Sopenharmony_ci * new data. We stop if we get an error or we failed to make any 3431cb0ef41Sopenharmony_ci * progress writing pending data. 3441cb0ef41Sopenharmony_ci */ 3451cb0ef41Sopenharmony_ci if (i < 0 || (ctx->buf_len - ctx->buf_off) == pend) 3461cb0ef41Sopenharmony_ci return i; 3471cb0ef41Sopenharmony_ci } 3481cb0ef41Sopenharmony_ci 3491cb0ef41Sopenharmony_ci if (!ctx->finished) { 3501cb0ef41Sopenharmony_ci ctx->finished = 1; 3511cb0ef41Sopenharmony_ci ctx->buf_off = 0; 3521cb0ef41Sopenharmony_ci ret = EVP_CipherFinal_ex(ctx->cipher, 3531cb0ef41Sopenharmony_ci (unsigned char *)ctx->buf, 3541cb0ef41Sopenharmony_ci &(ctx->buf_len)); 3551cb0ef41Sopenharmony_ci ctx->ok = (int)ret; 3561cb0ef41Sopenharmony_ci if (ret <= 0) 3571cb0ef41Sopenharmony_ci break; 3581cb0ef41Sopenharmony_ci 3591cb0ef41Sopenharmony_ci /* push out the bytes */ 3601cb0ef41Sopenharmony_ci goto again; 3611cb0ef41Sopenharmony_ci } 3621cb0ef41Sopenharmony_ci 3631cb0ef41Sopenharmony_ci /* Finally flush the underlying BIO */ 3641cb0ef41Sopenharmony_ci ret = BIO_ctrl(next, cmd, num, ptr); 3651cb0ef41Sopenharmony_ci break; 3661cb0ef41Sopenharmony_ci case BIO_C_GET_CIPHER_STATUS: 3671cb0ef41Sopenharmony_ci ret = (long)ctx->ok; 3681cb0ef41Sopenharmony_ci break; 3691cb0ef41Sopenharmony_ci case BIO_C_DO_STATE_MACHINE: 3701cb0ef41Sopenharmony_ci BIO_clear_retry_flags(b); 3711cb0ef41Sopenharmony_ci ret = BIO_ctrl(next, cmd, num, ptr); 3721cb0ef41Sopenharmony_ci BIO_copy_next_retry(b); 3731cb0ef41Sopenharmony_ci break; 3741cb0ef41Sopenharmony_ci case BIO_C_GET_CIPHER_CTX: 3751cb0ef41Sopenharmony_ci c_ctx = (EVP_CIPHER_CTX **)ptr; 3761cb0ef41Sopenharmony_ci *c_ctx = ctx->cipher; 3771cb0ef41Sopenharmony_ci BIO_set_init(b, 1); 3781cb0ef41Sopenharmony_ci break; 3791cb0ef41Sopenharmony_ci case BIO_CTRL_DUP: 3801cb0ef41Sopenharmony_ci dbio = (BIO *)ptr; 3811cb0ef41Sopenharmony_ci dctx = BIO_get_data(dbio); 3821cb0ef41Sopenharmony_ci dctx->cipher = EVP_CIPHER_CTX_new(); 3831cb0ef41Sopenharmony_ci if (dctx->cipher == NULL) 3841cb0ef41Sopenharmony_ci return 0; 3851cb0ef41Sopenharmony_ci ret = EVP_CIPHER_CTX_copy(dctx->cipher, ctx->cipher); 3861cb0ef41Sopenharmony_ci if (ret) 3871cb0ef41Sopenharmony_ci BIO_set_init(dbio, 1); 3881cb0ef41Sopenharmony_ci break; 3891cb0ef41Sopenharmony_ci default: 3901cb0ef41Sopenharmony_ci ret = BIO_ctrl(next, cmd, num, ptr); 3911cb0ef41Sopenharmony_ci break; 3921cb0ef41Sopenharmony_ci } 3931cb0ef41Sopenharmony_ci return ret; 3941cb0ef41Sopenharmony_ci} 3951cb0ef41Sopenharmony_ci 3961cb0ef41Sopenharmony_cistatic long enc_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) 3971cb0ef41Sopenharmony_ci{ 3981cb0ef41Sopenharmony_ci BIO *next = BIO_next(b); 3991cb0ef41Sopenharmony_ci 4001cb0ef41Sopenharmony_ci if (next == NULL) 4011cb0ef41Sopenharmony_ci return 0; 4021cb0ef41Sopenharmony_ci 4031cb0ef41Sopenharmony_ci return BIO_callback_ctrl(next, cmd, fp); 4041cb0ef41Sopenharmony_ci} 4051cb0ef41Sopenharmony_ci 4061cb0ef41Sopenharmony_ciint BIO_set_cipher(BIO *b, const EVP_CIPHER *c, const unsigned char *k, 4071cb0ef41Sopenharmony_ci const unsigned char *i, int e) 4081cb0ef41Sopenharmony_ci{ 4091cb0ef41Sopenharmony_ci BIO_ENC_CTX *ctx; 4101cb0ef41Sopenharmony_ci BIO_callback_fn_ex callback_ex; 4111cb0ef41Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_3_0 4121cb0ef41Sopenharmony_ci long (*callback) (struct bio_st *, int, const char *, int, long, long) = NULL; 4131cb0ef41Sopenharmony_ci#endif 4141cb0ef41Sopenharmony_ci 4151cb0ef41Sopenharmony_ci ctx = BIO_get_data(b); 4161cb0ef41Sopenharmony_ci if (ctx == NULL) 4171cb0ef41Sopenharmony_ci return 0; 4181cb0ef41Sopenharmony_ci 4191cb0ef41Sopenharmony_ci if ((callback_ex = BIO_get_callback_ex(b)) != NULL) { 4201cb0ef41Sopenharmony_ci if (callback_ex(b, BIO_CB_CTRL, (const char *)c, 0, BIO_CTRL_SET, 4211cb0ef41Sopenharmony_ci e, 1, NULL) <= 0) 4221cb0ef41Sopenharmony_ci return 0; 4231cb0ef41Sopenharmony_ci } 4241cb0ef41Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_3_0 4251cb0ef41Sopenharmony_ci else { 4261cb0ef41Sopenharmony_ci callback = BIO_get_callback(b); 4271cb0ef41Sopenharmony_ci 4281cb0ef41Sopenharmony_ci if ((callback != NULL) && 4291cb0ef41Sopenharmony_ci (callback(b, BIO_CB_CTRL, (const char *)c, BIO_CTRL_SET, e, 4301cb0ef41Sopenharmony_ci 0L) <= 0)) 4311cb0ef41Sopenharmony_ci return 0; 4321cb0ef41Sopenharmony_ci } 4331cb0ef41Sopenharmony_ci#endif 4341cb0ef41Sopenharmony_ci 4351cb0ef41Sopenharmony_ci BIO_set_init(b, 1); 4361cb0ef41Sopenharmony_ci 4371cb0ef41Sopenharmony_ci if (!EVP_CipherInit_ex(ctx->cipher, c, NULL, k, i, e)) 4381cb0ef41Sopenharmony_ci return 0; 4391cb0ef41Sopenharmony_ci 4401cb0ef41Sopenharmony_ci if (callback_ex != NULL) 4411cb0ef41Sopenharmony_ci return callback_ex(b, BIO_CB_CTRL | BIO_CB_RETURN, (const char *)c, 0, 4421cb0ef41Sopenharmony_ci BIO_CTRL_SET, e, 1, NULL); 4431cb0ef41Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_3_0 4441cb0ef41Sopenharmony_ci else if (callback != NULL) 4451cb0ef41Sopenharmony_ci return callback(b, BIO_CB_CTRL, (const char *)c, BIO_CTRL_SET, e, 1L); 4461cb0ef41Sopenharmony_ci#endif 4471cb0ef41Sopenharmony_ci return 1; 4481cb0ef41Sopenharmony_ci} 449