summaryrefslogtreecommitdiffstats
path: root/eBones/des/enc_read.c
blob: 1b77c4cf18b7e209f53faeafaf76808a16f55202 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/* enc_read.c */
/* Copyright (C) 1993 Eric Young - see README for more details */

/*-
 *	$Id: enc_read.c,v 1.2 1994/07/19 19:21:54 g89r4222 Exp $
 */

#include <errno.h>
#include "des_locl.h"

/* This has some uglies in it but it works - even over sockets. */
extern int errno;
int des_rw_mode=DES_PCBC_MODE;

int des_enc_read(fd,buf,len,sched,iv)
int fd;
char *buf;
int len;
des_key_schedule sched;
des_cblock *iv;
	{
	/* data to be unencrypted */
	int net_num=0;
	unsigned char net[BSIZE];
	/* extra unencrypted data 
	 * for when a block of 100 comes in but is des_read one byte at
	 * a time. */
	static char unnet[BSIZE];
	static int unnet_start=0;
	static int unnet_left=0;
	int i;
	long num=0,rnum;
	unsigned char *p;

	/* left over data from last decrypt */
	if (unnet_left != 0)
		{
		if (unnet_left < len)
			{
			/* we still still need more data but will return
			 * with the number of bytes we have - should always
			 * check the return value */
			bcopy(&(unnet[unnet_start]),buf,unnet_left);
			/* eay 26/08/92 I had the next 2 lines
			 * reversed :-( */
			i=unnet_left;
			unnet_start=unnet_left=0;
			}
		else
			{
			bcopy(&(unnet[unnet_start]),buf,len);
			unnet_start+=len;
			unnet_left-=len;
			i=len;
			}
		return(i);
		}

	/* We need to get more data. */
	if (len > MAXWRITE) len=MAXWRITE;

	/* first - get the length */
	net_num=0;
	while (net_num < HDRSIZE) 
		{
		i=read(fd,&(net[net_num]),HDRSIZE-net_num);
		if ((i == -1) && (errno == EINTR)) continue;
		if (i <= 0) return(0);
		net_num+=i;
		}

	/* we now have at net_num bytes in net */
	p=net;
	num=0;
	n2l(p,num);
	/* num should be rounded up to the next group of eight
	 * we make sure that we have read a multiple of 8 bytes from the net.
	 */
	if ((num > MAXWRITE) || (num < 0)) /* error */
		return(-1);
	rnum=(num < 8)?8:((num+7)/8*8);

	net_num=0;
	while (net_num < rnum)
		{
		i=read(fd,&(net[net_num]),rnum-net_num);
		if ((i == -1) && (errno == EINTR)) continue;
		if (i <= 0) return(0);
		net_num+=i;
		}

	/* Check if there will be data left over. */
	if (len < num)
		{
		if (des_rw_mode & DES_PCBC_MODE)
			pcbc_encrypt((des_cblock *)net,(des_cblock *)unnet,
				num,sched,iv,DES_DECRYPT);
		else
			cbc_encrypt((des_cblock *)net,(des_cblock *)unnet,
				num,sched,iv,DES_DECRYPT);
		bcopy(unnet,buf,len);
		unnet_start=len;
		unnet_left=num-len;

		/* The following line is done because we return num
		 * as the number of bytes read. */
		num=len;
		}
	else
		{
		/* >output is a multiple of 8 byes, if len < rnum
		 * >we must be careful.  The user must be aware that this
		 * >routine will write more bytes than he asked for.
		 * >The length of the buffer must be correct.
		 * FIXED - Should be ok now 18-9-90 - eay */
		if (len < rnum)
			{
			char tmpbuf[BSIZE];

			if (des_rw_mode & DES_PCBC_MODE)
				pcbc_encrypt((des_cblock *)net,
					(des_cblock *)tmpbuf,
					num,sched,iv,DES_DECRYPT);
			else
				cbc_encrypt((des_cblock *)net,
					(des_cblock *)tmpbuf,
					num,sched,iv,DES_DECRYPT);

			/* eay 26/08/92 fix a bug that returned more
			 * bytes than you asked for (returned len bytes :-( */
			bcopy(tmpbuf,buf,num);
			}
		else
			{
			if (des_rw_mode & DES_PCBC_MODE)
				pcbc_encrypt((des_cblock *)net,
					(des_cblock *)buf,num,sched,iv,
					DES_DECRYPT);
			else
				cbc_encrypt((des_cblock *)net,
					(des_cblock *)buf,num,sched,iv,
					DES_DECRYPT);
			}
		}
	return(num);
	}

OpenPOWER on IntegriCloud