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.
8296465Sdelphij *
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).
15296465Sdelphij *
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.
22296465Sdelphij *
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 :-).
37296465Sdelphij * 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)"
40296465Sdelphij *
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.
52296465Sdelphij *
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. */
65296465Sdelphij/*
66296465Sdelphij * extern int errno;
67296465Sdelphij */
68296465SdelphijOPENSSL_IMPLEMENT_GLOBAL(int, DES_rw_mode) = DES_PCBC_MODE;
6955714Skris
70296465Sdelphij/*-
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 */
8655714Skris
87109998Smarkmint DES_enc_read(int fd, void *buf, int len, DES_key_schedule *sched,
88296465Sdelphij                 DES_cblock *iv)
89296465Sdelphij{
90296465Sdelphij    /* data to be unencrypted */
91296465Sdelphij    int net_num = 0;
92296465Sdelphij    static unsigned char *net = NULL;
93296465Sdelphij    /*
94296465Sdelphij     * extra unencrypted data for when a block of 100 comes in but is
95296465Sdelphij     * des_read one byte at a time.
96296465Sdelphij     */
97296465Sdelphij    static unsigned char *unnet = NULL;
98296465Sdelphij    static int unnet_start = 0;
99296465Sdelphij    static int unnet_left = 0;
100296465Sdelphij    static unsigned char *tmpbuf = NULL;
101296465Sdelphij    int i;
102296465Sdelphij    long num = 0, rnum;
103296465Sdelphij    unsigned char *p;
10455714Skris
105296465Sdelphij    if (tmpbuf == NULL) {
106296465Sdelphij        tmpbuf = OPENSSL_malloc(BSIZE);
107296465Sdelphij        if (tmpbuf == NULL)
108296465Sdelphij            return (-1);
109296465Sdelphij    }
110296465Sdelphij    if (net == NULL) {
111296465Sdelphij        net = OPENSSL_malloc(BSIZE);
112296465Sdelphij        if (net == NULL)
113296465Sdelphij            return (-1);
114296465Sdelphij    }
115296465Sdelphij    if (unnet == NULL) {
116296465Sdelphij        unnet = OPENSSL_malloc(BSIZE);
117296465Sdelphij        if (unnet == NULL)
118296465Sdelphij            return (-1);
119296465Sdelphij    }
120296465Sdelphij    /* left over data from last decrypt */
121296465Sdelphij    if (unnet_left != 0) {
122296465Sdelphij        if (unnet_left < len) {
123296465Sdelphij            /*
124296465Sdelphij             * we still still need more data but will return with the number
125296465Sdelphij             * of bytes we have - should always check the return value
126296465Sdelphij             */
127296465Sdelphij            memcpy(buf, &(unnet[unnet_start]), unnet_left);
128296465Sdelphij            /*
129296465Sdelphij             * eay 26/08/92 I had the next 2 lines reversed :-(
130296465Sdelphij             */
131296465Sdelphij            i = unnet_left;
132296465Sdelphij            unnet_start = unnet_left = 0;
133296465Sdelphij        } else {
134296465Sdelphij            memcpy(buf, &(unnet[unnet_start]), len);
135296465Sdelphij            unnet_start += len;
136296465Sdelphij            unnet_left -= len;
137296465Sdelphij            i = len;
138296465Sdelphij        }
139296465Sdelphij        return (i);
140296465Sdelphij    }
14155714Skris
142296465Sdelphij    /* We need to get more data. */
143296465Sdelphij    if (len > MAXWRITE)
144296465Sdelphij        len = MAXWRITE;
14555714Skris
146296465Sdelphij    /* first - get the length */
147296465Sdelphij    while (net_num < HDRSIZE) {
148194206Ssimon#ifndef _WIN32
149296465Sdelphij        i = read(fd, (void *)&(net[net_num]), HDRSIZE - net_num);
150194206Ssimon#else
151296465Sdelphij        i = _read(fd, (void *)&(net[net_num]), HDRSIZE - net_num);
152194206Ssimon#endif
15355714Skris#ifdef EINTR
154296465Sdelphij        if ((i == -1) && (errno == EINTR))
155296465Sdelphij            continue;
15655714Skris#endif
157296465Sdelphij        if (i <= 0)
158296465Sdelphij            return (0);
159296465Sdelphij        net_num += i;
160296465Sdelphij    }
16155714Skris
162296465Sdelphij    /* we now have at net_num bytes in net */
163296465Sdelphij    p = net;
164296465Sdelphij    /* num=0;  */
165296465Sdelphij    n2l(p, num);
166296465Sdelphij    /*
167296465Sdelphij     * num should be rounded up to the next group of eight we make sure that
168296465Sdelphij     * we have read a multiple of 8 bytes from the net.
169296465Sdelphij     */
170296465Sdelphij    if ((num > MAXWRITE) || (num < 0)) /* error */
171296465Sdelphij        return (-1);
172296465Sdelphij    rnum = (num < 8) ? 8 : ((num + 7) / 8 * 8);
17355714Skris
174296465Sdelphij    net_num = 0;
175296465Sdelphij    while (net_num < rnum) {
176296465Sdelphij        i = read(fd, (void *)&(net[net_num]), rnum - net_num);
17755714Skris#ifdef EINTR
178296465Sdelphij        if ((i == -1) && (errno == EINTR))
179296465Sdelphij            continue;
18055714Skris#endif
181296465Sdelphij        if (i <= 0)
182296465Sdelphij            return (0);
183296465Sdelphij        net_num += i;
184296465Sdelphij    }
18555714Skris
186296465Sdelphij    /* Check if there will be data left over. */
187296465Sdelphij    if (len < num) {
188296465Sdelphij        if (DES_rw_mode & DES_PCBC_MODE)
189296465Sdelphij            DES_pcbc_encrypt(net, unnet, num, sched, iv, DES_DECRYPT);
190296465Sdelphij        else
191296465Sdelphij            DES_cbc_encrypt(net, unnet, num, sched, iv, DES_DECRYPT);
192296465Sdelphij        memcpy(buf, unnet, len);
193296465Sdelphij        unnet_start = len;
194296465Sdelphij        unnet_left = num - len;
19555714Skris
196296465Sdelphij        /*
197296465Sdelphij         * The following line is done because we return num as the number of
198296465Sdelphij         * bytes read.
199296465Sdelphij         */
200296465Sdelphij        num = len;
201296465Sdelphij    } else {
202296465Sdelphij        /*-
203296465Sdelphij         * >output is a multiple of 8 byes, if len < rnum
204296465Sdelphij         * >we must be careful.  The user must be aware that this
205296465Sdelphij         * >routine will write more bytes than he asked for.
206296465Sdelphij         * >The length of the buffer must be correct.
207296465Sdelphij         * FIXED - Should be ok now 18-9-90 - eay */
208296465Sdelphij        if (len < rnum) {
20955714Skris
210296465Sdelphij            if (DES_rw_mode & DES_PCBC_MODE)
211296465Sdelphij                DES_pcbc_encrypt(net, tmpbuf, num, sched, iv, DES_DECRYPT);
212296465Sdelphij            else
213296465Sdelphij                DES_cbc_encrypt(net, tmpbuf, num, sched, iv, DES_DECRYPT);
21455714Skris
215296465Sdelphij            /*
216296465Sdelphij             * eay 26/08/92 fix a bug that returned more bytes than you asked
217296465Sdelphij             * for (returned len bytes :-(
218296465Sdelphij             */
219296465Sdelphij            memcpy(buf, tmpbuf, num);
220296465Sdelphij        } else {
221296465Sdelphij            if (DES_rw_mode & DES_PCBC_MODE)
222296465Sdelphij                DES_pcbc_encrypt(net, buf, num, sched, iv, DES_DECRYPT);
223296465Sdelphij            else
224296465Sdelphij                DES_cbc_encrypt(net, buf, num, sched, iv, DES_DECRYPT);
225296465Sdelphij        }
226296465Sdelphij    }
227296465Sdelphij    return num;
228296465Sdelphij}
229