155714Skris/* crypto/evp/bio_enc.c */ 255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 355714Skris * All rights reserved. 455714Skris * 555714Skris * This package is an SSL implementation written 655714Skris * by Eric Young (eay@cryptsoft.com). 755714Skris * The implementation was written so as to conform with Netscapes SSL. 8280304Sjkim * 955714Skris * This library is free for commercial and non-commercial use as long as 1055714Skris * the following conditions are aheared to. The following conditions 1155714Skris * apply to all code found in this distribution, be it the RC4, RSA, 1255714Skris * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1355714Skris * included with this distribution is covered by the same copyright terms 1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15280304Sjkim * 1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in 1755714Skris * the code are not to be removed. 1855714Skris * If this package is used in a product, Eric Young should be given attribution 1955714Skris * as the author of the parts of the library used. 2055714Skris * This can be in the form of a textual message at program startup or 2155714Skris * in documentation (online or textual) provided with the package. 22280304Sjkim * 2355714Skris * Redistribution and use in source and binary forms, with or without 2455714Skris * modification, are permitted provided that the following conditions 2555714Skris * are met: 2655714Skris * 1. Redistributions of source code must retain the copyright 2755714Skris * notice, this list of conditions and the following disclaimer. 2855714Skris * 2. Redistributions in binary form must reproduce the above copyright 2955714Skris * notice, this list of conditions and the following disclaimer in the 3055714Skris * documentation and/or other materials provided with the distribution. 3155714Skris * 3. All advertising materials mentioning features or use of this software 3255714Skris * must display the following acknowledgement: 3355714Skris * "This product includes cryptographic software written by 3455714Skris * Eric Young (eay@cryptsoft.com)" 3555714Skris * The word 'cryptographic' can be left out if the rouines from the library 3655714Skris * being used are not cryptographic related :-). 37280304Sjkim * 4. If you include any Windows specific code (or a derivative thereof) from 3855714Skris * the apps directory (application code) you must include an acknowledgement: 3955714Skris * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40280304Sjkim * 4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4455714Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5155714Skris * SUCH DAMAGE. 52280304Sjkim * 5355714Skris * The licence and distribution terms for any publically available version or 5455714Skris * derivative of this code cannot be changed. i.e. this code cannot simply be 5555714Skris * copied and put under another distribution licence 5655714Skris * [including the GNU Public Licence.] 5755714Skris */ 5855714Skris 5955714Skris#include <stdio.h> 6055714Skris#include <errno.h> 6155714Skris#include "cryptlib.h" 6255714Skris#include <openssl/buffer.h> 6355714Skris#include <openssl/evp.h> 6455714Skris 6568651Skrisstatic int enc_write(BIO *h, const char *buf, int num); 6668651Skrisstatic int enc_read(BIO *h, char *buf, int size); 67280304Sjkim/* 68280304Sjkim * static int enc_puts(BIO *h, const char *str); 69280304Sjkim */ 70280304Sjkim/* 71280304Sjkim * static int enc_gets(BIO *h, char *str, int size); 72280304Sjkim */ 7368651Skrisstatic long enc_ctrl(BIO *h, int cmd, long arg1, void *arg2); 7455714Skrisstatic int enc_new(BIO *h); 7555714Skrisstatic int enc_free(BIO *data); 7668651Skrisstatic long enc_callback_ctrl(BIO *h, int cmd, bio_info_cb *fps); 77280304Sjkim#define ENC_BLOCK_SIZE (1024*4) 78280304Sjkim#define BUF_OFFSET (EVP_MAX_BLOCK_LENGTH*2) 7955714Skris 80280304Sjkimtypedef struct enc_struct { 81280304Sjkim int buf_len; 82280304Sjkim int buf_off; 83280304Sjkim int cont; /* <= 0 when finished */ 84280304Sjkim int finished; 85280304Sjkim int ok; /* bad decrypt */ 86280304Sjkim EVP_CIPHER_CTX cipher; 87280304Sjkim /* 88280304Sjkim * buf is larger than ENC_BLOCK_SIZE because EVP_DecryptUpdate can return 89280304Sjkim * up to a block more data than is presented to it 90280304Sjkim */ 91280304Sjkim char buf[ENC_BLOCK_SIZE + BUF_OFFSET + 2]; 92280304Sjkim} BIO_ENC_CTX; 9355714Skris 94280304Sjkimstatic BIO_METHOD methods_enc = { 95280304Sjkim BIO_TYPE_CIPHER, "cipher", 96280304Sjkim enc_write, 97280304Sjkim enc_read, 98280304Sjkim NULL, /* enc_puts, */ 99280304Sjkim NULL, /* enc_gets, */ 100280304Sjkim enc_ctrl, 101280304Sjkim enc_new, 102280304Sjkim enc_free, 103280304Sjkim enc_callback_ctrl, 104280304Sjkim}; 10555714Skris 10655714SkrisBIO_METHOD *BIO_f_cipher(void) 107280304Sjkim{ 108280304Sjkim return (&methods_enc); 109280304Sjkim} 11055714Skris 11155714Skrisstatic int enc_new(BIO *bi) 112280304Sjkim{ 113280304Sjkim BIO_ENC_CTX *ctx; 11455714Skris 115280304Sjkim ctx = (BIO_ENC_CTX *)OPENSSL_malloc(sizeof(BIO_ENC_CTX)); 116280304Sjkim if (ctx == NULL) 117280304Sjkim return (0); 118280304Sjkim EVP_CIPHER_CTX_init(&ctx->cipher); 11955714Skris 120280304Sjkim ctx->buf_len = 0; 121280304Sjkim ctx->buf_off = 0; 122280304Sjkim ctx->cont = 1; 123280304Sjkim ctx->finished = 0; 124280304Sjkim ctx->ok = 1; 12555714Skris 126280304Sjkim bi->init = 0; 127280304Sjkim bi->ptr = (char *)ctx; 128280304Sjkim bi->flags = 0; 129280304Sjkim return (1); 130280304Sjkim} 13155714Skris 13255714Skrisstatic int enc_free(BIO *a) 133280304Sjkim{ 134280304Sjkim BIO_ENC_CTX *b; 13555714Skris 136280304Sjkim if (a == NULL) 137280304Sjkim return (0); 138280304Sjkim b = (BIO_ENC_CTX *)a->ptr; 139280304Sjkim EVP_CIPHER_CTX_cleanup(&(b->cipher)); 140280304Sjkim OPENSSL_cleanse(a->ptr, sizeof(BIO_ENC_CTX)); 141280304Sjkim OPENSSL_free(a->ptr); 142280304Sjkim a->ptr = NULL; 143280304Sjkim a->init = 0; 144280304Sjkim a->flags = 0; 145280304Sjkim return (1); 146280304Sjkim} 147280304Sjkim 14855714Skrisstatic int enc_read(BIO *b, char *out, int outl) 149280304Sjkim{ 150280304Sjkim int ret = 0, i; 151280304Sjkim BIO_ENC_CTX *ctx; 15255714Skris 153280304Sjkim if (out == NULL) 154280304Sjkim return (0); 155280304Sjkim ctx = (BIO_ENC_CTX *)b->ptr; 15655714Skris 157280304Sjkim if ((ctx == NULL) || (b->next_bio == NULL)) 158280304Sjkim return (0); 15955714Skris 160280304Sjkim /* First check if there are bytes decoded/encoded */ 161280304Sjkim if (ctx->buf_len > 0) { 162280304Sjkim i = ctx->buf_len - ctx->buf_off; 163280304Sjkim if (i > outl) 164280304Sjkim i = outl; 165280304Sjkim memcpy(out, &(ctx->buf[ctx->buf_off]), i); 166280304Sjkim ret = i; 167280304Sjkim out += i; 168280304Sjkim outl -= i; 169280304Sjkim ctx->buf_off += i; 170280304Sjkim if (ctx->buf_len == ctx->buf_off) { 171280304Sjkim ctx->buf_len = 0; 172280304Sjkim ctx->buf_off = 0; 173280304Sjkim } 174280304Sjkim } 17555714Skris 176280304Sjkim /* 177280304Sjkim * At this point, we have room of outl bytes and an empty buffer, so we 178280304Sjkim * should read in some more. 179280304Sjkim */ 18055714Skris 181280304Sjkim while (outl > 0) { 182280304Sjkim if (ctx->cont <= 0) 183280304Sjkim break; 18455714Skris 185280304Sjkim /* 186280304Sjkim * read in at IV offset, read the EVP_Cipher documentation about why 187280304Sjkim */ 188280304Sjkim i = BIO_read(b->next_bio, &(ctx->buf[BUF_OFFSET]), ENC_BLOCK_SIZE); 18955714Skris 190280304Sjkim if (i <= 0) { 191280304Sjkim /* Should be continue next time we are called? */ 192280304Sjkim if (!BIO_should_retry(b->next_bio)) { 193280304Sjkim ctx->cont = i; 194280304Sjkim i = EVP_CipherFinal_ex(&(ctx->cipher), 195280304Sjkim (unsigned char *)ctx->buf, 196280304Sjkim &(ctx->buf_len)); 197280304Sjkim ctx->ok = i; 198280304Sjkim ctx->buf_off = 0; 199280304Sjkim } else { 200280304Sjkim ret = (ret == 0) ? i : ret; 201280304Sjkim break; 202280304Sjkim } 203280304Sjkim } else { 204280304Sjkim EVP_CipherUpdate(&(ctx->cipher), 205280304Sjkim (unsigned char *)ctx->buf, &ctx->buf_len, 206280304Sjkim (unsigned char *)&(ctx->buf[BUF_OFFSET]), i); 207280304Sjkim ctx->cont = 1; 208280304Sjkim /* 209280304Sjkim * Note: it is possible for EVP_CipherUpdate to decrypt zero 210280304Sjkim * bytes because this is or looks like the final block: if this 211280304Sjkim * happens we should retry and either read more data or decrypt 212280304Sjkim * the final block 213280304Sjkim */ 214280304Sjkim if (ctx->buf_len == 0) 215280304Sjkim continue; 216280304Sjkim } 21755714Skris 218280304Sjkim if (ctx->buf_len <= outl) 219280304Sjkim i = ctx->buf_len; 220280304Sjkim else 221280304Sjkim i = outl; 222280304Sjkim if (i <= 0) 223280304Sjkim break; 224280304Sjkim memcpy(out, ctx->buf, i); 225280304Sjkim ret += i; 226280304Sjkim ctx->buf_off = i; 227280304Sjkim outl -= i; 228280304Sjkim out += i; 229280304Sjkim } 23055714Skris 231280304Sjkim BIO_clear_retry_flags(b); 232280304Sjkim BIO_copy_next_retry(b); 233280304Sjkim return ((ret == 0) ? ctx->cont : ret); 234280304Sjkim} 23555714Skris 23668651Skrisstatic int enc_write(BIO *b, const char *in, int inl) 237280304Sjkim{ 238280304Sjkim int ret = 0, n, i; 239280304Sjkim BIO_ENC_CTX *ctx; 24055714Skris 241280304Sjkim ctx = (BIO_ENC_CTX *)b->ptr; 242280304Sjkim ret = inl; 24355714Skris 244280304Sjkim BIO_clear_retry_flags(b); 245280304Sjkim n = ctx->buf_len - ctx->buf_off; 246280304Sjkim while (n > 0) { 247280304Sjkim i = BIO_write(b->next_bio, &(ctx->buf[ctx->buf_off]), n); 248280304Sjkim if (i <= 0) { 249280304Sjkim BIO_copy_next_retry(b); 250280304Sjkim return (i); 251280304Sjkim } 252280304Sjkim ctx->buf_off += i; 253280304Sjkim n -= i; 254280304Sjkim } 255280304Sjkim /* at this point all pending data has been written */ 25655714Skris 257280304Sjkim if ((in == NULL) || (inl <= 0)) 258280304Sjkim return (0); 25955714Skris 260280304Sjkim ctx->buf_off = 0; 261280304Sjkim while (inl > 0) { 262280304Sjkim n = (inl > ENC_BLOCK_SIZE) ? ENC_BLOCK_SIZE : inl; 263280304Sjkim EVP_CipherUpdate(&(ctx->cipher), 264280304Sjkim (unsigned char *)ctx->buf, &ctx->buf_len, 265280304Sjkim (unsigned char *)in, n); 266280304Sjkim inl -= n; 267280304Sjkim in += n; 26855714Skris 269280304Sjkim ctx->buf_off = 0; 270280304Sjkim n = ctx->buf_len; 271280304Sjkim while (n > 0) { 272280304Sjkim i = BIO_write(b->next_bio, &(ctx->buf[ctx->buf_off]), n); 273280304Sjkim if (i <= 0) { 274280304Sjkim BIO_copy_next_retry(b); 275280304Sjkim return (ret == inl) ? i : ret - inl; 276280304Sjkim } 277280304Sjkim n -= i; 278280304Sjkim ctx->buf_off += i; 279280304Sjkim } 280280304Sjkim ctx->buf_len = 0; 281280304Sjkim ctx->buf_off = 0; 282280304Sjkim } 283280304Sjkim BIO_copy_next_retry(b); 284280304Sjkim return (ret); 285280304Sjkim} 28655714Skris 28768651Skrisstatic long enc_ctrl(BIO *b, int cmd, long num, void *ptr) 288280304Sjkim{ 289280304Sjkim BIO *dbio; 290280304Sjkim BIO_ENC_CTX *ctx, *dctx; 291280304Sjkim long ret = 1; 292280304Sjkim int i; 293280304Sjkim EVP_CIPHER_CTX **c_ctx; 29455714Skris 295280304Sjkim ctx = (BIO_ENC_CTX *)b->ptr; 29655714Skris 297280304Sjkim switch (cmd) { 298280304Sjkim case BIO_CTRL_RESET: 299280304Sjkim ctx->ok = 1; 300280304Sjkim ctx->finished = 0; 301280304Sjkim EVP_CipherInit_ex(&(ctx->cipher), NULL, NULL, NULL, NULL, 302280304Sjkim ctx->cipher.encrypt); 303280304Sjkim ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 304280304Sjkim break; 305280304Sjkim case BIO_CTRL_EOF: /* More to read */ 306280304Sjkim if (ctx->cont <= 0) 307280304Sjkim ret = 1; 308280304Sjkim else 309280304Sjkim ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 310280304Sjkim break; 311280304Sjkim case BIO_CTRL_WPENDING: 312280304Sjkim ret = ctx->buf_len - ctx->buf_off; 313280304Sjkim if (ret <= 0) 314280304Sjkim ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 315280304Sjkim break; 316280304Sjkim case BIO_CTRL_PENDING: /* More to read in buffer */ 317280304Sjkim ret = ctx->buf_len - ctx->buf_off; 318280304Sjkim if (ret <= 0) 319280304Sjkim ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 320280304Sjkim break; 321280304Sjkim case BIO_CTRL_FLUSH: 322280304Sjkim /* do a final write */ 323280304Sjkim again: 324280304Sjkim while (ctx->buf_len != ctx->buf_off) { 325280304Sjkim i = enc_write(b, NULL, 0); 326280304Sjkim if (i < 0) 327280304Sjkim return i; 328280304Sjkim } 32955714Skris 330280304Sjkim if (!ctx->finished) { 331280304Sjkim ctx->finished = 1; 332280304Sjkim ctx->buf_off = 0; 333280304Sjkim ret = EVP_CipherFinal_ex(&(ctx->cipher), 334280304Sjkim (unsigned char *)ctx->buf, 335280304Sjkim &(ctx->buf_len)); 336280304Sjkim ctx->ok = (int)ret; 337280304Sjkim if (ret <= 0) 338280304Sjkim break; 33955714Skris 340280304Sjkim /* push out the bytes */ 341280304Sjkim goto again; 342280304Sjkim } 34355714Skris 344280304Sjkim /* Finally flush the underlying BIO */ 345280304Sjkim ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 346280304Sjkim break; 347280304Sjkim case BIO_C_GET_CIPHER_STATUS: 348280304Sjkim ret = (long)ctx->ok; 349280304Sjkim break; 350280304Sjkim case BIO_C_DO_STATE_MACHINE: 351280304Sjkim BIO_clear_retry_flags(b); 352280304Sjkim ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 353280304Sjkim BIO_copy_next_retry(b); 354280304Sjkim break; 355280304Sjkim case BIO_C_GET_CIPHER_CTX: 356280304Sjkim c_ctx = (EVP_CIPHER_CTX **)ptr; 357280304Sjkim (*c_ctx) = &(ctx->cipher); 358280304Sjkim b->init = 1; 359280304Sjkim break; 360280304Sjkim case BIO_CTRL_DUP: 361280304Sjkim dbio = (BIO *)ptr; 362280304Sjkim dctx = (BIO_ENC_CTX *)dbio->ptr; 363280304Sjkim EVP_CIPHER_CTX_init(&dctx->cipher); 364280304Sjkim ret = EVP_CIPHER_CTX_copy(&dctx->cipher, &ctx->cipher); 365280304Sjkim if (ret) 366280304Sjkim dbio->init = 1; 367280304Sjkim break; 368280304Sjkim default: 369280304Sjkim ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 370280304Sjkim break; 371280304Sjkim } 372280304Sjkim return (ret); 373280304Sjkim} 374280304Sjkim 37568651Skrisstatic long enc_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) 376280304Sjkim{ 377280304Sjkim long ret = 1; 37859191Skris 379280304Sjkim if (b->next_bio == NULL) 380280304Sjkim return (0); 381280304Sjkim switch (cmd) { 382280304Sjkim default: 383280304Sjkim ret = BIO_callback_ctrl(b->next_bio, cmd, fp); 384280304Sjkim break; 385280304Sjkim } 386280304Sjkim return (ret); 387280304Sjkim} 38859191Skris 389280304Sjkim/*- 39055714Skrisvoid BIO_set_cipher_ctx(b,c) 39155714SkrisBIO *b; 39255714SkrisEVP_CIPHER_ctx *c; 393280304Sjkim { 394280304Sjkim if (b == NULL) return; 39555714Skris 396280304Sjkim if ((b->callback != NULL) && 397280304Sjkim (b->callback(b,BIO_CB_CTRL,(char *)c,BIO_CTRL_SET,e,0L) <= 0)) 398280304Sjkim return; 39955714Skris 400280304Sjkim b->init=1; 401280304Sjkim ctx=(BIO_ENC_CTX *)b->ptr; 402280304Sjkim memcpy(ctx->cipher,c,sizeof(EVP_CIPHER_CTX)); 403280304Sjkim 404280304Sjkim if (b->callback != NULL) 405280304Sjkim b->callback(b,BIO_CB_CTRL,(char *)c,BIO_CTRL_SET,e,1L); 406280304Sjkim } 40755714Skris*/ 40855714Skris 409160814Ssimonvoid BIO_set_cipher(BIO *b, const EVP_CIPHER *c, const unsigned char *k, 410280304Sjkim const unsigned char *i, int e) 411280304Sjkim{ 412280304Sjkim BIO_ENC_CTX *ctx; 41355714Skris 414280304Sjkim if (b == NULL) 415280304Sjkim return; 41655714Skris 417280304Sjkim if ((b->callback != NULL) && 418280304Sjkim (b->callback(b, BIO_CB_CTRL, (const char *)c, BIO_CTRL_SET, e, 0L) <= 419280304Sjkim 0)) 420280304Sjkim return; 42155714Skris 422280304Sjkim b->init = 1; 423280304Sjkim ctx = (BIO_ENC_CTX *)b->ptr; 424280304Sjkim EVP_CipherInit_ex(&(ctx->cipher), c, NULL, k, i, e); 42555714Skris 426280304Sjkim if (b->callback != NULL) 427280304Sjkim b->callback(b, BIO_CB_CTRL, (const char *)c, BIO_CTRL_SET, e, 1L); 428280304Sjkim} 429