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