1 /* public key routines */ 2 /* functions: 3 genkeys(char *public, char *secret) 4 common_key(char *secret, char *public, desData *deskey) 5 pk_encode(char *in, *out, DesData *deskey); 6 pk_decode(char *in, *out, DesData *deskey); 7 where 8 char public[HEXKEYBYTES + 1]; 9 char secret[HEXKEYBYTES + 1]; 10 */ 11 12 #include <stdio.h> 13 #include <sys/time.h> 14 #include <string.h> 15 #include <fcntl.h> 16 #include <des.h> 17 #include "mp.h" 18 #include "pk.h" 19 #if defined(SOLARIS2) || defined(LINUX) 20 #include <stdlib.h> 21 #endif 22 23 /* 24 * Choose top 128 bits of the common key to use as our idea key. 25 */ 26 static 27 extractideakey(ck, ideakey) 28 MINT *ck; 29 IdeaData *ideakey; 30 { 31 MINT *a; 32 MINT *z; 33 short r; 34 int i; 35 short base = (1 << 8); 36 char *k; 37 38 z = itom(0); 39 a = itom(0); 40 madd(ck, z, a); 41 for (i = 0; i < ((KEYSIZE - 128) / 8); i++) { 42 sdiv(a, base, a, &r); 43 } 44 k = (char *)ideakey; 45 for (i = 0; i < 16; i++) { 46 sdiv(a, base, a, &r); 47 *k++ = r; 48 } 49 mfree(z); 50 mfree(a); 51 } 52 53 /* 54 * Choose middle 64 bits of the common key to use as our des key, possibly 55 * overwriting the lower order bits by setting parity. 56 */ 57 static 58 extractdeskey(ck, deskey) 59 MINT *ck; 60 DesData *deskey; 61 { 62 MINT *a; 63 MINT *z; 64 short r; 65 int i; 66 short base = (1 << 8); 67 char *k; 68 69 z = itom(0); 70 a = itom(0); 71 madd(ck, z, a); 72 for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) { 73 sdiv(a, base, a, &r); 74 } 75 k = (char *)deskey; 76 for (i = 0; i < 8; i++) { 77 sdiv(a, base, a, &r); 78 *k++ = r; 79 } 80 mfree(z); 81 mfree(a); 82 } 83 84 /* 85 * get common key from my secret key and his public key 86 */ 87 void common_key(char *xsecret, char *xpublic, IdeaData *ideakey, DesData *deskey) 88 { 89 MINT *public; 90 MINT *secret; 91 MINT *common; 92 MINT *modulus = xtom(HEXMODULUS); 93 94 public = xtom(xpublic); 95 secret = xtom(xsecret); 96 common = itom(0); 97 pow(public, secret, modulus, common); 98 extractdeskey(common, deskey); 99 extractideakey(common, ideakey); 100 #if DES_OSTHOLM 101 des_fixup_key_parity(deskey); 102 #else 103 des_set_odd_parity(deskey); 104 #endif 105 mfree(common); 106 mfree(secret); 107 mfree(public); 108 mfree(modulus); 109 } 110 111 112 /* 113 * Generate a seed 114 */ 115 void getseed(seed, seedsize) 116 char *seed; 117 int seedsize; 118 { 119 int i,f; 120 int rseed; 121 struct timeval tv; 122 long devrand; 123 124 (void)gettimeofday(&tv, (struct timezone *)NULL); 125 rseed = tv.tv_sec + tv.tv_usec; 126 /* XXX What the hell is this?! */ 127 for (i = 0; i < 8; i++) { 128 rseed ^= (rseed << 8); 129 } 130 131 f=open("/dev/random",O_NONBLOCK|O_RDONLY); 132 if (f>=0) 133 { 134 read(f,&devrand,sizeof(devrand)); 135 close(f); 136 } 137 srand48((long)rseed^devrand); 138 139 for (i = 0; i < seedsize; i++) { 140 seed[i] = (lrand48() & 0xff); 141 } 142 } 143 144 145 /* 146 * Generate a random public/secret key pair 147 */ 148 void genkeys(public, secret) 149 char *public; 150 char *secret; 151 { 152 int i; 153 154 # define BASEBITS (8*sizeof(short) - 1) 155 # define BASE (1 << BASEBITS) 156 157 MINT *pk = itom(0); 158 MINT *sk = itom(0); 159 MINT *tmp; 160 MINT *base = itom(BASE); 161 MINT *root = itom(PROOT); 162 MINT *modulus = xtom(HEXMODULUS); 163 short r; 164 unsigned short seed[KEYSIZE/BASEBITS + 1]; 165 char *xkey; 166 167 getseed((char *)seed, sizeof(seed)); 168 for (i = 0; i < KEYSIZE/BASEBITS + 1; i++) { 169 r = seed[i] % BASE; 170 tmp = itom(r); 171 mult(sk, base, sk); 172 madd(sk, tmp, sk); 173 mfree(tmp); 174 } 175 tmp = itom(0); 176 mdiv(sk, modulus, tmp, sk); 177 mfree(tmp); 178 pow(root, sk, modulus, pk); 179 xkey = mtox(sk); 180 adjust(secret, xkey); 181 xkey = mtox(pk); 182 adjust(public, xkey); 183 mfree(sk); 184 mfree(base); 185 mfree(pk); 186 mfree(root); 187 mfree(modulus); 188 } 189 190 /* 191 * Adjust the input key so that it is 0-filled on the left 192 */ 193 adjust(keyout, keyin) 194 char keyout[HEXKEYBYTES+1]; 195 char *keyin; 196 { 197 char *p; 198 char *s; 199 200 for (p = keyin; *p; p++) 201 ; 202 for (s = keyout + HEXKEYBYTES; p >= keyin; p--, s--) { 203 *s = *p; 204 } 205 while (s >= keyout) { 206 *s-- = '0'; 207 } 208 } 209 210 static char hextab[17] = "0123456789ABCDEF"; 211 212 /* given a DES key, cbc encrypt and translate input to terminated hex */ 213 void pk_encode(in, out, key) 214 char *in,*out; 215 DesData *key; 216 { 217 char buf[256]; 218 DesData i; 219 des_key_schedule k; 220 int l,op,deslen; 221 222 memset(&i,0,sizeof(i)); 223 memset(buf,0,sizeof(buf)); 224 deslen = ((strlen(in) + 7)/8)*8; 225 des_key_sched(key, k); 226 des_cbc_encrypt((des_cblock *)in,(des_cblock *)buf,deslen, 227 k,&i,DES_ENCRYPT); 228 for (l=0,op=0;l<deslen;l++) { 229 out[op++] = hextab[(buf[l] & 0xf0) >> 4]; 230 out[op++] = hextab[(buf[l] & 0x0f)]; 231 } 232 out[op] = '\0'; 233 } 234 235 /* given a DES key, translate input from hex and decrypt */ 236 void pk_decode(in, out, key) 237 char *in,*out; 238 DesData *key; 239 { 240 char buf[256]; 241 DesData i; 242 des_key_schedule k; 243 int l,n1,n2,op; 244 245 memset(&i,0,sizeof(i)); 246 memset(buf,0,sizeof(buf)); 247 for (l=0,op=0;l<strlen(in)/2;l++,op+=2) { 248 if(in[op] == '0' && in[op+1] == '0') { 249 buf[l] = '\0'; 250 break; 251 } 252 if (in[op] > '9') 253 n1 = in[op] - 'A' + 10; 254 else 255 n1 = in[op] - '0'; 256 if (in[op+1] > '9') 257 n2 = in[op+1] - 'A' + 10; 258 else 259 n2 = in[op+1] - '0'; 260 buf[l] = n1*16 +n2; 261 } 262 des_key_sched(key, k); 263 des_cbc_encrypt((des_cblock *)buf,(des_cblock *)out,strlen(in)/2, 264 k,&i,DES_DECRYPT); 265 out[strlen(in)/2] = '\0'; 266 } 267