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*46675Sbostic static char sccsid[] = "@(#)des_rw.c 5.8 (Berkeley) 02/25/91"; 1038677Skfall #endif /* not lint */ 1138677Skfall 12*46675Sbostic #ifdef CRYPT 13*46675Sbostic #ifdef KERBEROS 14*46675Sbostic #include <sys/param.h> 15*46675Sbostic #include <kerberosIV/des.h> 16*46675Sbostic #include <kerberosIV/krb.h> 17*46675Sbostic #include <time.h> 18*46675Sbostic #include <unistd.h> 19*46675Sbostic #include <stdlib.h> 20*46675Sbostic #include <string.h> 21*46675Sbostic 22*46675Sbostic extern long random(); 23*46675Sbostic static unsigned char des_inbuf[10240], storage[10240], *store_ptr; 24*46675Sbostic static bit_64 *key; 25*46675Sbostic static u_char *key_schedule; 26*46675Sbostic 27*46675Sbostic /* 28*46675Sbostic * NB: These routines will not function properly if NBIO 29*46675Sbostic * is set 30*46675Sbostic */ 31*46675Sbostic 32*46675Sbostic /* 33*46675Sbostic * des_set_key 34*46675Sbostic * 35*46675Sbostic * Set des encryption/decryption key for use by the des_read and 36*46675Sbostic * des_write routines 37*46675Sbostic * 38*46675Sbostic * The inkey parameter is actually the DES initial vector, 39*46675Sbostic * and the insched is the DES Key unwrapped for faster decryption 40*46675Sbostic */ 41*46675Sbostic 42*46675Sbostic void 43*46675Sbostic des_set_key(inkey, insched) 44*46675Sbostic bit_64 *inkey; 45*46675Sbostic u_char *insched; 46*46675Sbostic { 47*46675Sbostic key = inkey; 48*46675Sbostic key_schedule = insched; 49*46675Sbostic } 50*46675Sbostic 51*46675Sbostic void 52*46675Sbostic des_clear_key() 53*46675Sbostic { 54*46675Sbostic bzero((char *) key, sizeof(C_Block)); 55*46675Sbostic bzero((char *) key_schedule, sizeof(Key_schedule)); 56*46675Sbostic } 57*46675Sbostic 58*46675Sbostic 59*46675Sbostic int 60*46675Sbostic des_read(fd, buf, len) 61*46675Sbostic int fd; 62*46675Sbostic register char *buf; 63*46675Sbostic int len; 64*46675Sbostic { 65*46675Sbostic int nreturned = 0; 66*46675Sbostic long net_len, rd_len; 67*46675Sbostic int nstored = 0; 68*46675Sbostic 69*46675Sbostic if (nstored >= len) { 70*46675Sbostic (void) bcopy(store_ptr, buf, len); 71*46675Sbostic store_ptr += len; 72*46675Sbostic nstored -= len; 73*46675Sbostic return(len); 74*46675Sbostic } else if (nstored) { 75*46675Sbostic (void) bcopy(store_ptr, buf, nstored); 76*46675Sbostic nreturned += nstored; 77*46675Sbostic buf += nstored; 78*46675Sbostic len -= nstored; 79*46675Sbostic nstored = 0; 80*46675Sbostic } 81*46675Sbostic 82*46675Sbostic if (krb_net_read(fd, &net_len, sizeof(net_len)) != sizeof(net_len)) { 83*46675Sbostic /* XXX can't read enough, pipe 84*46675Sbostic must have closed */ 85*46675Sbostic return(0); 86*46675Sbostic } 87*46675Sbostic net_len = ntohl(net_len); 88*46675Sbostic if (net_len <= 0 || net_len > sizeof(des_inbuf)) { 89*46675Sbostic /* preposterous length; assume out-of-sync; only 90*46675Sbostic recourse is to close connection, so return 0 */ 91*46675Sbostic return(0); 92*46675Sbostic } 93*46675Sbostic /* the writer tells us how much real data we are getting, but 94*46675Sbostic we need to read the pad bytes (8-byte boundary) */ 95*46675Sbostic rd_len = roundup(net_len, 8); 96*46675Sbostic if (krb_net_read(fd, des_inbuf, rd_len) != rd_len) { 97*46675Sbostic /* pipe must have closed, return 0 */ 98*46675Sbostic return(0); 99*46675Sbostic } 100*46675Sbostic (void) des_pcbc_encrypt(des_inbuf, /* inbuf */ 101*46675Sbostic storage, /* outbuf */ 102*46675Sbostic net_len, /* length */ 103*46675Sbostic key_schedule, /* DES key */ 104*46675Sbostic key, /* IV */ 105*46675Sbostic DECRYPT); /* direction */ 106*46675Sbostic 107*46675Sbostic if(net_len < 8) 108*46675Sbostic store_ptr = storage + 8 - net_len; 109*46675Sbostic else 110*46675Sbostic store_ptr = storage; 111*46675Sbostic 112*46675Sbostic nstored = net_len; 113*46675Sbostic if (nstored > len) { 114*46675Sbostic (void) bcopy(store_ptr, buf, len); 115*46675Sbostic nreturned += len; 116*46675Sbostic store_ptr += len; 117*46675Sbostic nstored -= len; 118*46675Sbostic } else { 119*46675Sbostic (void) bcopy(store_ptr, buf, nstored); 120*46675Sbostic nreturned += nstored; 121*46675Sbostic nstored = 0; 122*46675Sbostic } 123*46675Sbostic 124*46675Sbostic return(nreturned); 125*46675Sbostic } 126*46675Sbostic 127*46675Sbostic static unsigned char des_outbuf[10240]; /* > longest write */ 128*46675Sbostic 129*46675Sbostic int 130*46675Sbostic des_write(fd, buf, len) 131*46675Sbostic int fd; 132*46675Sbostic char *buf; 133*46675Sbostic int len; 134*46675Sbostic { 135*46675Sbostic static int seeded = 0; 136*46675Sbostic static char garbage_buf[8]; 137*46675Sbostic long net_len, garbage; 138*46675Sbostic 139*46675Sbostic if(len < 8) { 140*46675Sbostic if(!seeded) { 141*46675Sbostic seeded = 1; 142*46675Sbostic srandom((int) time((long *)0)); 143*46675Sbostic } 144*46675Sbostic garbage = random(); 145*46675Sbostic /* insert random garbage */ 146*46675Sbostic (void) bcopy(&garbage, garbage_buf, MIN(sizeof(long),8)); 147*46675Sbostic /* this "right-justifies" the data in the buffer */ 148*46675Sbostic (void) bcopy(buf, garbage_buf + 8 - len, len); 149*46675Sbostic } 150*46675Sbostic /* pcbc_encrypt outputs in 8-byte (64 bit) increments */ 151*46675Sbostic 152*46675Sbostic (void) des_pcbc_encrypt((len < 8) ? garbage_buf : buf, 153*46675Sbostic des_outbuf, 154*46675Sbostic (len < 8) ? 8 : len, 155*46675Sbostic key_schedule, /* DES key */ 156*46675Sbostic key, /* IV */ 157*46675Sbostic ENCRYPT); 158*46675Sbostic 159*46675Sbostic /* tell the other end the real amount, but send an 8-byte padded 160*46675Sbostic packet */ 161*46675Sbostic net_len = htonl(len); 162*46675Sbostic (void) write(fd, &net_len, sizeof(net_len)); 163*46675Sbostic (void) write(fd, des_outbuf, roundup(len,8)); 164*46675Sbostic return(len); 165*46675Sbostic } 166*46675Sbostic #endif /* KERBEROS */ 167*46675Sbostic #endif /* CRYPT */ 168