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