1*42763Sbostic /*- 238677Skfall * Copyright (c) 1989 The Regents of the University of California. 338677Skfall * All rights reserved. 438677Skfall * 542761Sbostic * %sccs.include.redist.c% 638677Skfall */ 738677Skfall 838677Skfall #ifndef lint 9*42763Sbostic static char sccsid[] = "@(#)des_rw.c 5.5 (Berkeley) 06/01/90"; 1038677Skfall #endif /* not lint */ 1138677Skfall 1238677Skfall #include <sys/param.h> 1341760Skfall #include <kerberosIV/des.h> 1440683Sbostic #include <kerberosIV/krb.h> 1538677Skfall 1638677Skfall extern long random(); 1738677Skfall static unsigned char des_inbuf[10240], storage[10240], *store_ptr; 1838677Skfall static bit_64 *key; 1938677Skfall static u_char *key_schedule; 2038677Skfall 2138677Skfall /* 2238677Skfall * NB: These routines will not function properly if NBIO 2338677Skfall * is set 2438677Skfall */ 2538677Skfall 2638677Skfall /* 2738677Skfall * des_set_key 2838677Skfall * 2938677Skfall * Set des encryption/decryption key for use by the des_read and 3038677Skfall * des_write routines 3138677Skfall * 3238677Skfall * The inkey parameter is actually the DES initial vector, 3338677Skfall * and the insched is the DES Key unwrapped for faster decryption 3438677Skfall */ 3538677Skfall 3638677Skfall void 3738677Skfall des_set_key(inkey, insched) 3838677Skfall bit_64 *inkey; 3938677Skfall u_char *insched; 4038677Skfall { 4138677Skfall key = inkey; 4238677Skfall key_schedule = insched; 4338677Skfall } 4438677Skfall 4538677Skfall void 4638677Skfall des_clear_key() 4738677Skfall { 4838677Skfall bzero((char *) key, sizeof(C_Block)); 4938677Skfall bzero((char *) key_schedule, sizeof(Key_schedule)); 5038677Skfall } 5138677Skfall 5238677Skfall 5338677Skfall int 5438677Skfall des_read(fd, buf, len) 5538677Skfall int fd; 5638677Skfall register char *buf; 5738677Skfall int len; 5838677Skfall { 5938677Skfall int nreturned = 0; 6038677Skfall long net_len, rd_len; 6138677Skfall int nstored = 0; 6238677Skfall 6338677Skfall if (nstored >= len) { 6438677Skfall (void) bcopy(store_ptr, buf, len); 6538677Skfall store_ptr += len; 6638677Skfall nstored -= len; 6738677Skfall return(len); 6838677Skfall } else if (nstored) { 6938677Skfall (void) bcopy(store_ptr, buf, nstored); 7038677Skfall nreturned += nstored; 7138677Skfall buf += nstored; 7238677Skfall len -= nstored; 7338677Skfall nstored = 0; 7438677Skfall } 7538677Skfall 7638677Skfall if (krb_net_read(fd, &net_len, sizeof(net_len)) != sizeof(net_len)) { 7738677Skfall /* XXX can't read enough, pipe 7838677Skfall must have closed */ 7938677Skfall return(0); 8038677Skfall } 8138677Skfall net_len = ntohl(net_len); 8238677Skfall if (net_len <= 0 || net_len > sizeof(des_inbuf)) { 8338677Skfall /* preposterous length; assume out-of-sync; only 8438677Skfall recourse is to close connection, so return 0 */ 8538677Skfall return(0); 8638677Skfall } 8738677Skfall /* the writer tells us how much real data we are getting, but 8838677Skfall we need to read the pad bytes (8-byte boundary) */ 8938677Skfall rd_len = roundup(net_len, 8); 9038677Skfall if (krb_net_read(fd, des_inbuf, rd_len) != rd_len) { 9138677Skfall /* pipe must have closed, return 0 */ 9238677Skfall return(0); 9338677Skfall } 9438677Skfall (void) des_pcbc_encrypt(des_inbuf, /* inbuf */ 9538677Skfall storage, /* outbuf */ 9638677Skfall net_len, /* length */ 9738677Skfall key_schedule, /* DES key */ 9838677Skfall key, /* IV */ 9938677Skfall DECRYPT); /* direction */ 10038677Skfall 10138677Skfall if(net_len < 8) 10238677Skfall store_ptr = storage + 8 - net_len; 10338677Skfall else 10438677Skfall store_ptr = storage; 10538677Skfall 10638677Skfall nstored = net_len; 10738677Skfall if (nstored > len) { 10838677Skfall (void) bcopy(store_ptr, buf, len); 10938677Skfall nreturned += len; 11038677Skfall store_ptr += len; 11138677Skfall nstored -= len; 11238677Skfall } else { 11338677Skfall (void) bcopy(store_ptr, buf, nstored); 11438677Skfall nreturned += nstored; 11538677Skfall nstored = 0; 11638677Skfall } 11738677Skfall 11838677Skfall return(nreturned); 11938677Skfall } 12038677Skfall 12138677Skfall static unsigned char des_outbuf[10240]; /* > longest write */ 12238677Skfall 12338677Skfall int 12438677Skfall des_write(fd, buf, len) 12538677Skfall int fd; 12638677Skfall char *buf; 12738677Skfall int len; 12838677Skfall { 12938677Skfall static int seeded = 0; 13038677Skfall static char garbage_buf[8]; 13138677Skfall long net_len, garbage; 13238677Skfall 13338677Skfall if(len < 8) { 13438677Skfall if(!seeded) { 13538677Skfall seeded = 1; 13638677Skfall srandom((int) time((long *)0)); 13738677Skfall } 13838677Skfall garbage = random(); 13938677Skfall /* insert random garbage */ 14038677Skfall (void) bcopy(&garbage, garbage_buf, MIN(sizeof(long),8)); 14138677Skfall /* this "right-justifies" the data in the buffer */ 14238677Skfall (void) bcopy(buf, garbage_buf + 8 - len, len); 14338677Skfall } 14438677Skfall /* pcbc_encrypt outputs in 8-byte (64 bit) increments */ 14538677Skfall 14638677Skfall (void) des_pcbc_encrypt((len < 8) ? garbage_buf : buf, 14738677Skfall des_outbuf, 14838677Skfall (len < 8) ? 8 : len, 14938677Skfall key_schedule, /* DES key */ 15038677Skfall key, /* IV */ 15138677Skfall ENCRYPT); 15238677Skfall 15338677Skfall /* tell the other end the real amount, but send an 8-byte padded 15438677Skfall packet */ 15538677Skfall net_len = htonl(len); 15638677Skfall (void) write(fd, &net_len, sizeof(net_len)); 15738677Skfall (void) write(fd, des_outbuf, roundup(len,8)); 15838677Skfall return(len); 15938677Skfall } 160