155714Skris/* crypto/des/enc_read.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 "des_locl.h"
6355714Skris
6455714Skris/* This has some uglies in it but it works - even over sockets. */
65280304Sjkim/*
66280304Sjkim * extern int errno;
67280304Sjkim */
68280304SjkimOPENSSL_IMPLEMENT_GLOBAL(int, DES_rw_mode, DES_PCBC_MODE)
6955714Skris
70280304Sjkim/*-
7155714Skris * WARNINGS:
7255714Skris *
73109998Smarkm *  -  The data format used by DES_enc_write() and DES_enc_read()
7455714Skris *     has a cryptographic weakness: When asked to write more
75109998Smarkm *     than MAXWRITE bytes, DES_enc_write will split the data
7655714Skris *     into several chunks that are all encrypted
7755714Skris *     using the same IV.  So don't use these functions unless you
7855714Skris *     are sure you know what you do (in which case you might
7955714Skris *     not want to use them anyway).
8055714Skris *
8155714Skris *  -  This code cannot handle non-blocking sockets.
8255714Skris *
8355714Skris *  -  This function uses an internal state and thus cannot be
8455714Skris *     used on multiple files.
8555714Skris */
86109998Smarkmint DES_enc_read(int fd, void *buf, int len, DES_key_schedule *sched,
87280304Sjkim                 DES_cblock *iv)
88280304Sjkim{
89238405Sjkim#if defined(OPENSSL_NO_POSIX_IO)
90280304Sjkim    return (0);
91238405Sjkim#else
92280304Sjkim    /* data to be unencrypted */
93280304Sjkim    int net_num = 0;
94280304Sjkim    static unsigned char *net = NULL;
95280304Sjkim    /*
96280304Sjkim     * extra unencrypted data for when a block of 100 comes in but is
97280304Sjkim     * des_read one byte at a time.
98280304Sjkim     */
99280304Sjkim    static unsigned char *unnet = NULL;
100280304Sjkim    static int unnet_start = 0;
101280304Sjkim    static int unnet_left = 0;
102280304Sjkim    static unsigned char *tmpbuf = NULL;
103280304Sjkim    int i;
104280304Sjkim    long num = 0, rnum;
105280304Sjkim    unsigned char *p;
10655714Skris
107280304Sjkim    if (tmpbuf == NULL) {
108280304Sjkim        tmpbuf = OPENSSL_malloc(BSIZE);
109280304Sjkim        if (tmpbuf == NULL)
110280304Sjkim            return (-1);
111280304Sjkim    }
112280304Sjkim    if (net == NULL) {
113280304Sjkim        net = OPENSSL_malloc(BSIZE);
114280304Sjkim        if (net == NULL)
115280304Sjkim            return (-1);
116280304Sjkim    }
117280304Sjkim    if (unnet == NULL) {
118280304Sjkim        unnet = OPENSSL_malloc(BSIZE);
119280304Sjkim        if (unnet == NULL)
120280304Sjkim            return (-1);
121280304Sjkim    }
122280304Sjkim    /* left over data from last decrypt */
123280304Sjkim    if (unnet_left != 0) {
124280304Sjkim        if (unnet_left < len) {
125280304Sjkim            /*
126280304Sjkim             * we still still need more data but will return with the number
127280304Sjkim             * of bytes we have - should always check the return value
128280304Sjkim             */
129280304Sjkim            memcpy(buf, &(unnet[unnet_start]), unnet_left);
130280304Sjkim            /*
131280304Sjkim             * eay 26/08/92 I had the next 2 lines reversed :-(
132280304Sjkim             */
133280304Sjkim            i = unnet_left;
134280304Sjkim            unnet_start = unnet_left = 0;
135280304Sjkim        } else {
136280304Sjkim            memcpy(buf, &(unnet[unnet_start]), len);
137280304Sjkim            unnet_start += len;
138280304Sjkim            unnet_left -= len;
139280304Sjkim            i = len;
140280304Sjkim        }
141280304Sjkim        return (i);
142280304Sjkim    }
14355714Skris
144280304Sjkim    /* We need to get more data. */
145280304Sjkim    if (len > MAXWRITE)
146280304Sjkim        len = MAXWRITE;
14755714Skris
148280304Sjkim    /* first - get the length */
149280304Sjkim    while (net_num < HDRSIZE) {
150280304Sjkim# ifndef OPENSSL_SYS_WIN32
151280304Sjkim        i = read(fd, (void *)&(net[net_num]), HDRSIZE - net_num);
152280304Sjkim# else
153280304Sjkim        i = _read(fd, (void *)&(net[net_num]), HDRSIZE - net_num);
154280304Sjkim# endif
155280304Sjkim# ifdef EINTR
156280304Sjkim        if ((i == -1) && (errno == EINTR))
157280304Sjkim            continue;
158280304Sjkim# endif
159280304Sjkim        if (i <= 0)
160280304Sjkim            return (0);
161280304Sjkim        net_num += i;
162280304Sjkim    }
16355714Skris
164280304Sjkim    /* we now have at net_num bytes in net */
165280304Sjkim    p = net;
166280304Sjkim    /* num=0;  */
167280304Sjkim    n2l(p, num);
168280304Sjkim    /*
169280304Sjkim     * num should be rounded up to the next group of eight we make sure that
170280304Sjkim     * we have read a multiple of 8 bytes from the net.
171280304Sjkim     */
172280304Sjkim    if ((num > MAXWRITE) || (num < 0)) /* error */
173280304Sjkim        return (-1);
174280304Sjkim    rnum = (num < 8) ? 8 : ((num + 7) / 8 * 8);
17555714Skris
176280304Sjkim    net_num = 0;
177280304Sjkim    while (net_num < rnum) {
178280304Sjkim# ifndef OPENSSL_SYS_WIN32
179280304Sjkim        i = read(fd, (void *)&(net[net_num]), rnum - net_num);
180280304Sjkim# else
181280304Sjkim        i = _read(fd, (void *)&(net[net_num]), rnum - net_num);
182280304Sjkim# endif
183280304Sjkim# ifdef EINTR
184280304Sjkim        if ((i == -1) && (errno == EINTR))
185280304Sjkim            continue;
186280304Sjkim# endif
187280304Sjkim        if (i <= 0)
188280304Sjkim            return (0);
189280304Sjkim        net_num += i;
190280304Sjkim    }
19155714Skris
192280304Sjkim    /* Check if there will be data left over. */
193280304Sjkim    if (len < num) {
194280304Sjkim        if (DES_rw_mode & DES_PCBC_MODE)
195280304Sjkim            DES_pcbc_encrypt(net, unnet, num, sched, iv, DES_DECRYPT);
196280304Sjkim        else
197280304Sjkim            DES_cbc_encrypt(net, unnet, num, sched, iv, DES_DECRYPT);
198280304Sjkim        memcpy(buf, unnet, len);
199280304Sjkim        unnet_start = len;
200280304Sjkim        unnet_left = num - len;
20155714Skris
202280304Sjkim        /*
203280304Sjkim         * The following line is done because we return num as the number of
204280304Sjkim         * bytes read.
205280304Sjkim         */
206280304Sjkim        num = len;
207280304Sjkim    } else {
208280304Sjkim        /*-
209280304Sjkim         * >output is a multiple of 8 byes, if len < rnum
210280304Sjkim         * >we must be careful.  The user must be aware that this
211280304Sjkim         * >routine will write more bytes than he asked for.
212280304Sjkim         * >The length of the buffer must be correct.
213280304Sjkim         * FIXED - Should be ok now 18-9-90 - eay */
214280304Sjkim        if (len < rnum) {
21555714Skris
216280304Sjkim            if (DES_rw_mode & DES_PCBC_MODE)
217280304Sjkim                DES_pcbc_encrypt(net, tmpbuf, num, sched, iv, DES_DECRYPT);
218280304Sjkim            else
219280304Sjkim                DES_cbc_encrypt(net, tmpbuf, num, sched, iv, DES_DECRYPT);
22055714Skris
221280304Sjkim            /*
222280304Sjkim             * eay 26/08/92 fix a bug that returned more bytes than you asked
223280304Sjkim             * for (returned len bytes :-(
224280304Sjkim             */
225280304Sjkim            memcpy(buf, tmpbuf, num);
226280304Sjkim        } else {
227280304Sjkim            if (DES_rw_mode & DES_PCBC_MODE)
228280304Sjkim                DES_pcbc_encrypt(net, buf, num, sched, iv, DES_DECRYPT);
229280304Sjkim            else
230280304Sjkim                DES_cbc_encrypt(net, buf, num, sched, iv, DES_DECRYPT);
231280304Sjkim        }
232280304Sjkim    }
233280304Sjkim    return num;
234280304Sjkim#endif                          /* OPENSSL_NO_POSIX_IO */
235280304Sjkim}
236