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