138677Skfall /* 238677Skfall * Copyright (c) 1989 The Regents of the University of California. 338677Skfall * All rights reserved. 438677Skfall * 538677Skfall * Redistribution and use in source and binary forms are permitted 638677Skfall * provided that the above copyright notice and this paragraph are 738677Skfall * duplicated in all such forms and that any documentation, 838677Skfall * advertising materials, and other materials related to such 938677Skfall * distribution and use acknowledge that the software was developed 1038677Skfall * by the University of California, Berkeley. The name of the 1138677Skfall * University may not be used to endorse or promote products derived 1238677Skfall * from this software without specific prior written permission. 1338677Skfall * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1438677Skfall * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1538677Skfall * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1638677Skfall */ 1738677Skfall 1838677Skfall 1938677Skfall #ifndef lint 2038677Skfall static char sccsid[] = "@(#)des_rw.c 1.7 (Berkeley) 2/6/89"; 2138677Skfall #endif /* not lint */ 2238677Skfall 2338677Skfall #include <sys/param.h> 24*41760Skfall #include <kerberosIV/des.h> 2540683Sbostic #include <kerberosIV/krb.h> 2638677Skfall 2738677Skfall extern long random(); 2838677Skfall static unsigned char des_inbuf[10240], storage[10240], *store_ptr; 2938677Skfall static bit_64 *key; 3038677Skfall static u_char *key_schedule; 3138677Skfall 3238677Skfall /* 3338677Skfall * NB: These routines will not function properly if NBIO 3438677Skfall * is set 3538677Skfall */ 3638677Skfall 3738677Skfall /* 3838677Skfall * des_set_key 3938677Skfall * 4038677Skfall * Set des encryption/decryption key for use by the des_read and 4138677Skfall * des_write routines 4238677Skfall * 4338677Skfall * The inkey parameter is actually the DES initial vector, 4438677Skfall * and the insched is the DES Key unwrapped for faster decryption 4538677Skfall */ 4638677Skfall 4738677Skfall void 4838677Skfall des_set_key(inkey, insched) 4938677Skfall bit_64 *inkey; 5038677Skfall u_char *insched; 5138677Skfall { 5238677Skfall key = inkey; 5338677Skfall key_schedule = insched; 5438677Skfall } 5538677Skfall 5638677Skfall void 5738677Skfall des_clear_key() 5838677Skfall { 5938677Skfall bzero((char *) key, sizeof(C_Block)); 6038677Skfall bzero((char *) key_schedule, sizeof(Key_schedule)); 6138677Skfall } 6238677Skfall 6338677Skfall 6438677Skfall int 6538677Skfall des_read(fd, buf, len) 6638677Skfall int fd; 6738677Skfall register char *buf; 6838677Skfall int len; 6938677Skfall { 7038677Skfall int nreturned = 0; 7138677Skfall long net_len, rd_len; 7238677Skfall int nstored = 0; 7338677Skfall 7438677Skfall if (nstored >= len) { 7538677Skfall (void) bcopy(store_ptr, buf, len); 7638677Skfall store_ptr += len; 7738677Skfall nstored -= len; 7838677Skfall return(len); 7938677Skfall } else if (nstored) { 8038677Skfall (void) bcopy(store_ptr, buf, nstored); 8138677Skfall nreturned += nstored; 8238677Skfall buf += nstored; 8338677Skfall len -= nstored; 8438677Skfall nstored = 0; 8538677Skfall } 8638677Skfall 8738677Skfall if (krb_net_read(fd, &net_len, sizeof(net_len)) != sizeof(net_len)) { 8838677Skfall /* XXX can't read enough, pipe 8938677Skfall must have closed */ 9038677Skfall return(0); 9138677Skfall } 9238677Skfall net_len = ntohl(net_len); 9338677Skfall if (net_len <= 0 || net_len > sizeof(des_inbuf)) { 9438677Skfall /* preposterous length; assume out-of-sync; only 9538677Skfall recourse is to close connection, so return 0 */ 9638677Skfall return(0); 9738677Skfall } 9838677Skfall /* the writer tells us how much real data we are getting, but 9938677Skfall we need to read the pad bytes (8-byte boundary) */ 10038677Skfall rd_len = roundup(net_len, 8); 10138677Skfall if (krb_net_read(fd, des_inbuf, rd_len) != rd_len) { 10238677Skfall /* pipe must have closed, return 0 */ 10338677Skfall return(0); 10438677Skfall } 10538677Skfall (void) des_pcbc_encrypt(des_inbuf, /* inbuf */ 10638677Skfall storage, /* outbuf */ 10738677Skfall net_len, /* length */ 10838677Skfall key_schedule, /* DES key */ 10938677Skfall key, /* IV */ 11038677Skfall DECRYPT); /* direction */ 11138677Skfall 11238677Skfall if(net_len < 8) 11338677Skfall store_ptr = storage + 8 - net_len; 11438677Skfall else 11538677Skfall store_ptr = storage; 11638677Skfall 11738677Skfall nstored = net_len; 11838677Skfall if (nstored > len) { 11938677Skfall (void) bcopy(store_ptr, buf, len); 12038677Skfall nreturned += len; 12138677Skfall store_ptr += len; 12238677Skfall nstored -= len; 12338677Skfall } else { 12438677Skfall (void) bcopy(store_ptr, buf, nstored); 12538677Skfall nreturned += nstored; 12638677Skfall nstored = 0; 12738677Skfall } 12838677Skfall 12938677Skfall return(nreturned); 13038677Skfall } 13138677Skfall 13238677Skfall static unsigned char des_outbuf[10240]; /* > longest write */ 13338677Skfall 13438677Skfall int 13538677Skfall des_write(fd, buf, len) 13638677Skfall int fd; 13738677Skfall char *buf; 13838677Skfall int len; 13938677Skfall { 14038677Skfall static int seeded = 0; 14138677Skfall static char garbage_buf[8]; 14238677Skfall long net_len, garbage; 14338677Skfall 14438677Skfall if(len < 8) { 14538677Skfall if(!seeded) { 14638677Skfall seeded = 1; 14738677Skfall srandom((int) time((long *)0)); 14838677Skfall } 14938677Skfall garbage = random(); 15038677Skfall /* insert random garbage */ 15138677Skfall (void) bcopy(&garbage, garbage_buf, MIN(sizeof(long),8)); 15238677Skfall /* this "right-justifies" the data in the buffer */ 15338677Skfall (void) bcopy(buf, garbage_buf + 8 - len, len); 15438677Skfall } 15538677Skfall /* pcbc_encrypt outputs in 8-byte (64 bit) increments */ 15638677Skfall 15738677Skfall (void) des_pcbc_encrypt((len < 8) ? garbage_buf : buf, 15838677Skfall des_outbuf, 15938677Skfall (len < 8) ? 8 : len, 16038677Skfall key_schedule, /* DES key */ 16138677Skfall key, /* IV */ 16238677Skfall ENCRYPT); 16338677Skfall 16438677Skfall /* tell the other end the real amount, but send an 8-byte padded 16538677Skfall packet */ 16638677Skfall net_len = htonl(len); 16738677Skfall (void) write(fd, &net_len, sizeof(net_len)); 16838677Skfall (void) write(fd, des_outbuf, roundup(len,8)); 16938677Skfall return(len); 17038677Skfall } 171