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