Initial import from FreeBSD RELENG_4:
[dragonfly.git] / crypto / kerberosIV / appl / bsd / encrypt.c
1 /* Copyright (C) 1995 Eric Young (eay@mincom.oz.au)
2  * All rights reserved.
3  * 
4  * This file is part of an SSL implementation written
5  * by Eric Young (eay@mincom.oz.au).
6  * The implementation was written so as to conform with Netscapes SSL
7  * specification.  This library and applications are
8  * FREE FOR COMMERCIAL AND NON-COMMERCIAL USE
9  * as long as the following conditions are aheared to.
10  * 
11  * Copyright remains Eric Young's, and as such any Copyright notices in
12  * the code are not to be removed.  If this code is used in a product,
13  * Eric Young should be given attribution as the author of the parts used.
14  * This can be in the form of a textual message at program startup or
15  * in documentation (online or textual) provided with the package.
16  * 
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions
19  * are met:
20  * 1. Redistributions of source code must retain the copyright
21  *    notice, this list of conditions and the following disclaimer.
22  * 2. Redistributions in binary form must reproduce the above copyright
23  *    notice, this list of conditions and the following disclaimer in the
24  *    documentation and/or other materials provided with the distribution.
25  * 3. All advertising materials mentioning features or use of this software
26  *    must display the following acknowledgement:
27  *    This product includes software developed by Eric Young (eay@mincom.oz.au)
28  * 
29  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
30  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
33  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39  * SUCH DAMAGE.
40  * 
41  * The licence and distribution terms for any publically available version or
42  * derivative of this code cannot be changed.  i.e. this code cannot simply be
43  * copied and put under another distribution licence
44  * [including the GNU Public Licence.]
45  */
46
47 #include "bsd_locl.h"
48
49 RCSID("$Id: encrypt.c,v 1.4 1999/06/17 18:47:26 assar Exp $");
50
51 /* replacements for htonl and ntohl since I have no idea what to do
52  * when faced with machines with 8 byte longs. */
53 #define HDRSIZE 4
54
55 #define n2l(c,l)        (l =((u_int32_t)(*((c)++)))<<24, \
56                          l|=((u_int32_t)(*((c)++)))<<16, \
57                          l|=((u_int32_t)(*((c)++)))<< 8, \
58                          l|=((u_int32_t)(*((c)++))))
59
60 #define l2n(l,c)        (*((c)++)=(unsigned char)(((l)>>24)&0xff), \
61                          *((c)++)=(unsigned char)(((l)>>16)&0xff), \
62                          *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
63                          *((c)++)=(unsigned char)(((l)    )&0xff))
64
65 /* This has some uglies in it but it works - even over sockets. */
66 extern int errno;
67 int des_rw_mode=DES_PCBC_MODE;
68 int LEFT_JUSTIFIED = 0;
69
70 int
71 des_enc_read(int fd, char *buf, int len, struct des_ks_struct *sched, des_cblock *iv)
72 {
73   /* data to be unencrypted */
74   int net_num=0;
75   unsigned char net[DES_RW_BSIZE];
76   /* extra unencrypted data 
77    * for when a block of 100 comes in but is des_read one byte at
78    * a time. */
79   static char unnet[DES_RW_BSIZE];
80   static int unnet_start=0;
81   static int unnet_left=0;
82   int i;
83   long num=0,rnum;
84   unsigned char *p;
85
86   /* left over data from last decrypt */
87   if (unnet_left != 0)
88     {
89       if (unnet_left < len)
90         {
91           /* we still still need more data but will return
92            * with the number of bytes we have - should always
93            * check the return value */
94           memcpy(buf,&(unnet[unnet_start]),unnet_left);
95           /* eay 26/08/92 I had the next 2 lines
96            * reversed :-( */
97           i=unnet_left;
98           unnet_start=unnet_left=0;
99         }
100       else
101         {
102           memcpy(buf,&(unnet[unnet_start]),len);
103           unnet_start+=len;
104           unnet_left-=len;
105           i=len;
106         }
107       return(i);
108     }
109
110   /* We need to get more data. */
111   if (len > DES_RW_MAXWRITE) len=DES_RW_MAXWRITE;
112
113   /* first - get the length */
114   net_num=0;
115   while (net_num < HDRSIZE) 
116     {
117       i=read(fd,&(net[net_num]),(unsigned int)HDRSIZE-net_num);
118       if ((i == -1) && (errno == EINTR)) continue;
119       if (i <= 0) return(0);
120       net_num+=i;
121     }
122
123   /* we now have at net_num bytes in net */
124   p=net;
125   num=0;
126   n2l(p,num);
127   /* num should be rounded up to the next group of eight
128    * we make sure that we have read a multiple of 8 bytes from the net.
129    */
130   if ((num > DES_RW_MAXWRITE) || (num < 0)) /* error */
131     return(-1);
132   rnum=(num < 8)?8:((num+7)/8*8);
133
134   net_num=0;
135   while (net_num < rnum)
136     {
137       i=read(fd,&(net[net_num]),(unsigned int)rnum-net_num);
138       if ((i == -1) && (errno == EINTR)) continue;
139       if (i <= 0) return(0);
140       net_num+=i;
141     }
142
143   /* Check if there will be data left over. */
144   if (len < num)
145     {
146       if (des_rw_mode & DES_PCBC_MODE)
147         des_pcbc_encrypt((des_cblock *)net,(des_cblock *)unnet,
148                      num,sched,iv,DES_DECRYPT);
149       else
150         des_cbc_encrypt((des_cblock *)net,(des_cblock *)unnet,
151                     num,sched,iv,DES_DECRYPT);
152       memcpy(buf,unnet,len);
153       unnet_start=len;
154       unnet_left=num-len;
155
156       /* The following line is done because we return num
157        * as the number of bytes read. */
158       num=len;
159     }
160   else
161     {
162       /* >output is a multiple of 8 byes, if len < rnum
163        * >we must be careful.  The user must be aware that this
164        * >routine will write more bytes than he asked for.
165        * >The length of the buffer must be correct.
166        * FIXED - Should be ok now 18-9-90 - eay */
167       if (len < rnum)
168         {
169           char tmpbuf[DES_RW_BSIZE];
170
171           if (des_rw_mode & DES_PCBC_MODE)
172             des_pcbc_encrypt((des_cblock *)net,
173                          (des_cblock *)tmpbuf,
174                          num,sched,iv,DES_DECRYPT);
175           else
176             des_cbc_encrypt((des_cblock *)net,
177                         (des_cblock *)tmpbuf,
178                         num,sched,iv,DES_DECRYPT);
179
180           /* eay 26/08/92 fix a bug that returned more
181            * bytes than you asked for (returned len bytes :-( */
182           if (LEFT_JUSTIFIED || (len >= 8))
183               memcpy(buf,tmpbuf,num);
184           else
185               memcpy(buf,tmpbuf+(8-num),num); /* Right justified */
186         }
187       else if (num >= 8)
188         {
189           if (des_rw_mode & DES_PCBC_MODE)
190             des_pcbc_encrypt((des_cblock *)net,
191                          (des_cblock *)buf,num,sched,iv,
192                          DES_DECRYPT);
193           else
194             des_cbc_encrypt((des_cblock *)net,
195                         (des_cblock *)buf,num,sched,iv,
196                         DES_DECRYPT);
197         }
198       else
199         {
200           if (des_rw_mode & DES_PCBC_MODE)
201             des_pcbc_encrypt((des_cblock *)net,
202                          (des_cblock *)buf,8,sched,iv,
203                          DES_DECRYPT);
204           else
205             des_cbc_encrypt((des_cblock *)net,
206                         (des_cblock *)buf,8,sched,iv,
207                         DES_DECRYPT);
208           if (!LEFT_JUSTIFIED)
209               memcpy(buf, buf+(8-num), num); /* Right justified */
210         }
211     }
212   return(num);
213 }
214
215 int
216 des_enc_write(int fd, char *buf, int len, struct des_ks_struct *sched, des_cblock *iv)
217 {
218   long rnum;
219   int i,j,k,outnum;
220   char outbuf[DES_RW_BSIZE+HDRSIZE];
221   char shortbuf[8];
222   char *p;
223   static int start=1;
224
225   /* If we are sending less than 8 bytes, the same char will look
226    * the same if we don't pad it out with random bytes */
227   if (start)
228     {
229       start=0;
230       srand(time(NULL));
231     }
232
233   /* lets recurse if we want to send the data in small chunks */
234   if (len > DES_RW_MAXWRITE)
235     {
236       j=0;
237       for (i=0; i<len; i+=k)
238         {
239           k=des_enc_write(fd,&(buf[i]),
240                           ((len-i) > DES_RW_MAXWRITE)?DES_RW_MAXWRITE:(len-i),sched,iv);
241           if (k < 0)
242             return(k);
243           else
244             j+=k;
245         }
246       return(j);
247     }
248
249   /* write length first */
250   p=outbuf;
251   l2n(len,p);
252
253   /* pad short strings */
254   if (len < 8)
255     {
256         if (LEFT_JUSTIFIED)
257             {
258                 p=shortbuf;
259                 memcpy(shortbuf,buf,(unsigned int)len);
260                 for (i=len; i<8; i++)
261                     shortbuf[i]=rand();
262                 rnum=8;
263             }
264         else
265             {
266                 p=shortbuf;
267                 for (i=0; i<8-len; i++)
268                     shortbuf[i]=rand();
269                 memcpy(shortbuf + 8 - len, buf, len);
270                 rnum=8;
271             }
272     }
273   else
274     {
275       p=buf;
276       rnum=((len+7)/8*8);       /* round up to nearest eight */
277     }
278
279   if (des_rw_mode & DES_PCBC_MODE)
280     des_pcbc_encrypt((des_cblock *)p,(des_cblock *)&(outbuf[HDRSIZE]),
281                  (long)((len<8)?8:len),sched,iv,DES_ENCRYPT); 
282   else
283     des_cbc_encrypt((des_cblock *)p,(des_cblock *)&(outbuf[HDRSIZE]),
284                 (long)((len<8)?8:len),sched,iv,DES_ENCRYPT); 
285
286   /* output */
287   outnum=rnum+HDRSIZE;
288
289   for (j=0; j<outnum; j+=i)
290     {
291       /* eay 26/08/92 I was not doing writing from where we
292        * got upto. */
293       i=write(fd,&(outbuf[j]),(unsigned int)(outnum-j));
294       if (i == -1)
295         {
296           if (errno == EINTR)
297             i=0;
298           else                  /* This is really a bad error - very bad
299                                  * It will stuff-up both ends. */
300             return(-1);
301         }
302     }
303
304   return(len);
305 }