142763Sbostic /*- 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*58470Sbostic static char sccsid[] = "@(#)des_rw.c 5.9 (Berkeley) 03/04/93"; 1038677Skfall #endif /* not lint */ 1138677Skfall 1246675Sbostic #ifdef CRYPT 1346675Sbostic #ifdef KERBEROS 1446675Sbostic #include <sys/param.h> 15*58470Sbostic 1646675Sbostic #include <kerberosIV/des.h> 1746675Sbostic #include <kerberosIV/krb.h> 18*58470Sbostic 19*58470Sbostic #include <stdlib.h> 20*58470Sbostic #include <string.h> 2146675Sbostic #include <time.h> 2246675Sbostic #include <unistd.h> 2346675Sbostic 2446675Sbostic static unsigned char des_inbuf[10240], storage[10240], *store_ptr; 2546675Sbostic static bit_64 *key; 2646675Sbostic static u_char *key_schedule; 2746675Sbostic 28*58470Sbostic /* XXX these should be in a kerberos include file */ 29*58470Sbostic int krb_net_read __P((int, char *, int)); 30*58470Sbostic #ifdef notdef 31*58470Sbostic /* XXX too hard to make this work */ 32*58470Sbostic int des_pcbc_encrypt __P((des_cblock *, des_cblock *, long, 33*58470Sbostic des_key_schedule, des_cblock *, int)); 34*58470Sbostic #endif 35*58470Sbostic 3646675Sbostic /* 3746675Sbostic * NB: These routines will not function properly if NBIO 3846675Sbostic * is set 3946675Sbostic */ 4046675Sbostic 4146675Sbostic /* 4246675Sbostic * des_set_key 4346675Sbostic * 4446675Sbostic * Set des encryption/decryption key for use by the des_read and 4546675Sbostic * des_write routines 4646675Sbostic * 4746675Sbostic * The inkey parameter is actually the DES initial vector, 4846675Sbostic * and the insched is the DES Key unwrapped for faster decryption 4946675Sbostic */ 5046675Sbostic 5146675Sbostic void 5246675Sbostic des_set_key(inkey, insched) 5346675Sbostic bit_64 *inkey; 5446675Sbostic u_char *insched; 5546675Sbostic { 5646675Sbostic key = inkey; 5746675Sbostic key_schedule = insched; 5846675Sbostic } 5946675Sbostic 6046675Sbostic void 6146675Sbostic des_clear_key() 6246675Sbostic { 6346675Sbostic bzero((char *) key, sizeof(C_Block)); 6446675Sbostic bzero((char *) key_schedule, sizeof(Key_schedule)); 6546675Sbostic } 6646675Sbostic 6746675Sbostic 6846675Sbostic int 6946675Sbostic des_read(fd, buf, len) 7046675Sbostic int fd; 7146675Sbostic register char *buf; 7246675Sbostic int len; 7346675Sbostic { 7446675Sbostic int nreturned = 0; 7546675Sbostic long net_len, rd_len; 7646675Sbostic int nstored = 0; 7746675Sbostic 7846675Sbostic if (nstored >= len) { 7946675Sbostic (void) bcopy(store_ptr, buf, len); 8046675Sbostic store_ptr += len; 8146675Sbostic nstored -= len; 8246675Sbostic return(len); 8346675Sbostic } else if (nstored) { 8446675Sbostic (void) bcopy(store_ptr, buf, nstored); 8546675Sbostic nreturned += nstored; 8646675Sbostic buf += nstored; 8746675Sbostic len -= nstored; 8846675Sbostic nstored = 0; 8946675Sbostic } 9046675Sbostic 91*58470Sbostic if (krb_net_read(fd, (char *)&net_len, sizeof(net_len)) != 92*58470Sbostic sizeof(net_len)) { 9346675Sbostic /* XXX can't read enough, pipe 9446675Sbostic must have closed */ 9546675Sbostic return(0); 9646675Sbostic } 9746675Sbostic net_len = ntohl(net_len); 9846675Sbostic if (net_len <= 0 || net_len > sizeof(des_inbuf)) { 9946675Sbostic /* preposterous length; assume out-of-sync; only 10046675Sbostic recourse is to close connection, so return 0 */ 10146675Sbostic return(0); 10246675Sbostic } 10346675Sbostic /* the writer tells us how much real data we are getting, but 10446675Sbostic we need to read the pad bytes (8-byte boundary) */ 10546675Sbostic rd_len = roundup(net_len, 8); 106*58470Sbostic if (krb_net_read(fd, (char *)des_inbuf, rd_len) != rd_len) { 10746675Sbostic /* pipe must have closed, return 0 */ 10846675Sbostic return(0); 10946675Sbostic } 11046675Sbostic (void) des_pcbc_encrypt(des_inbuf, /* inbuf */ 11146675Sbostic storage, /* outbuf */ 11246675Sbostic net_len, /* length */ 11346675Sbostic key_schedule, /* DES key */ 11446675Sbostic key, /* IV */ 11546675Sbostic DECRYPT); /* direction */ 11646675Sbostic 11746675Sbostic if(net_len < 8) 11846675Sbostic store_ptr = storage + 8 - net_len; 11946675Sbostic else 12046675Sbostic store_ptr = storage; 12146675Sbostic 12246675Sbostic nstored = net_len; 12346675Sbostic if (nstored > len) { 12446675Sbostic (void) bcopy(store_ptr, buf, len); 12546675Sbostic nreturned += len; 12646675Sbostic store_ptr += len; 12746675Sbostic nstored -= len; 12846675Sbostic } else { 12946675Sbostic (void) bcopy(store_ptr, buf, nstored); 13046675Sbostic nreturned += nstored; 13146675Sbostic nstored = 0; 13246675Sbostic } 13346675Sbostic 13446675Sbostic return(nreturned); 13546675Sbostic } 13646675Sbostic 13746675Sbostic static unsigned char des_outbuf[10240]; /* > longest write */ 13846675Sbostic 13946675Sbostic int 14046675Sbostic des_write(fd, buf, len) 14146675Sbostic int fd; 14246675Sbostic char *buf; 14346675Sbostic int len; 14446675Sbostic { 14546675Sbostic static int seeded = 0; 14646675Sbostic static char garbage_buf[8]; 14746675Sbostic long net_len, garbage; 14846675Sbostic 14946675Sbostic if(len < 8) { 15046675Sbostic if(!seeded) { 15146675Sbostic seeded = 1; 15246675Sbostic srandom((int) time((long *)0)); 15346675Sbostic } 15446675Sbostic garbage = random(); 15546675Sbostic /* insert random garbage */ 15646675Sbostic (void) bcopy(&garbage, garbage_buf, MIN(sizeof(long),8)); 15746675Sbostic /* this "right-justifies" the data in the buffer */ 15846675Sbostic (void) bcopy(buf, garbage_buf + 8 - len, len); 15946675Sbostic } 16046675Sbostic /* pcbc_encrypt outputs in 8-byte (64 bit) increments */ 16146675Sbostic 16246675Sbostic (void) des_pcbc_encrypt((len < 8) ? garbage_buf : buf, 16346675Sbostic des_outbuf, 16446675Sbostic (len < 8) ? 8 : len, 16546675Sbostic key_schedule, /* DES key */ 16646675Sbostic key, /* IV */ 16746675Sbostic ENCRYPT); 16846675Sbostic 16946675Sbostic /* tell the other end the real amount, but send an 8-byte padded 17046675Sbostic packet */ 17146675Sbostic net_len = htonl(len); 17246675Sbostic (void) write(fd, &net_len, sizeof(net_len)); 17346675Sbostic (void) write(fd, des_outbuf, roundup(len,8)); 17446675Sbostic return(len); 17546675Sbostic } 17646675Sbostic #endif /* KERBEROS */ 17746675Sbostic #endif /* CRYPT */ 178