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 int i,f; 121 int rseed; 122 struct timeval tv; 123 long devrand; 124 125 (void)gettimeofday(&tv, (struct timezone *)NULL); 126 rseed = tv.tv_sec + tv.tv_usec; 127 /* XXX What the hell is this?! */ 128 for (i = 0; i < 8; i++) { 129 rseed ^= (rseed << 8); 130 } 131 132 f=open("/dev/random",O_NONBLOCK|O_RDONLY); 133 if (f>=0) 134 { 135 read(f,&devrand,sizeof(devrand)); 136 close(f); 137 } 138 srand48((long)rseed^devrand); 139 140 for (i = 0; i < seedsize; i++) { 141 seed[i] = (lrand48() & 0xff); 142 } 143 } 144 145 146 /* 147 * Generate a random public/secret key pair 148 */ 149 void genkeys(public, secret) 150 char *public; 151 char *secret; 152 { 153 int i; 154 155 # define BASEBITS (8*sizeof(short) - 1) 156 # define BASE (1 << BASEBITS) 157 158 MINT *pk = itom(0); 159 MINT *sk = itom(0); 160 MINT *tmp; 161 MINT *base = itom(BASE); 162 MINT *root = itom(PROOT); 163 MINT *modulus = xtom(HEXMODULUS); 164 short r; 165 unsigned short seed[KEYSIZE/BASEBITS + 1]; 166 char *xkey; 167 168 getseed((char *)seed, sizeof(seed)); 169 for (i = 0; i < KEYSIZE/BASEBITS + 1; i++) { 170 r = seed[i] % BASE; 171 tmp = itom(r); 172 mult(sk, base, sk); 173 madd(sk, tmp, sk); 174 mfree(tmp); 175 } 176 tmp = itom(0); 177 mdiv(sk, modulus, tmp, sk); 178 mfree(tmp); 179 pow(root, sk, modulus, pk); 180 xkey = mtox(sk); 181 adjust(secret, xkey); 182 xkey = mtox(pk); 183 adjust(public, xkey); 184 mfree(sk); 185 mfree(base); 186 mfree(pk); 187 mfree(root); 188 mfree(modulus); 189 } 190 191 /* 192 * Adjust the input key so that it is 0-filled on the left 193 */ 194 adjust(keyout, keyin) 195 char keyout[HEXKEYBYTES+1]; 196 char *keyin; 197 { 198 char *p; 199 char *s; 200 201 for (p = keyin; *p; p++) 202 ; 203 for (s = keyout + HEXKEYBYTES; p >= keyin; p--, s--) { 204 *s = *p; 205 } 206 while (s >= keyout) { 207 *s-- = '0'; 208 } 209 } 210 211 static char hextab[17] = "0123456789ABCDEF"; 212 213 /* given a DES key, cbc encrypt and translate input to terminated hex */ 214 void pk_encode(in, out, key) 215 char *in,*out; 216 DesData *key; 217 { 218 char buf[256]; 219 DesData i; 220 des_key_schedule k; 221 int l,op,deslen; 222 223 memset(&i,0,sizeof(i)); 224 memset(buf,0,sizeof(buf)); 225 deslen = ((strlen(in) + 7)/8)*8; 226 des_key_sched(key, k); 227 des_cbc_encrypt((des_cblock *)in,(des_cblock *)buf,deslen, 228 k,&i,DES_ENCRYPT); 229 for (l=0,op=0;l<deslen;l++) { 230 out[op++] = hextab[(buf[l] & 0xf0) >> 4]; 231 out[op++] = hextab[(buf[l] & 0x0f)]; 232 } 233 out[op] = '\0'; 234 } 235 236 /* given a DES key, translate input from hex and decrypt */ 237 void pk_decode(in, out, key) 238 char *in,*out; 239 DesData *key; 240 { 241 char buf[256]; 242 DesData i; 243 des_key_schedule k; 244 int l,n1,n2,op; 245 246 memset(&i,0,sizeof(i)); 247 memset(buf,0,sizeof(buf)); 248 for (l=0,op=0;l<strlen(in)/2;l++,op+=2) { 249 if(in[op] == '0' && in[op+1] == '0') { 250 buf[l] = '\0'; 251 break; 252 } 253 if (in[op] > '9') 254 n1 = in[op] - 'A' + 10; 255 else 256 n1 = in[op] - '0'; 257 if (in[op+1] > '9') 258 n2 = in[op+1] - 'A' + 10; 259 else 260 n2 = in[op+1] - '0'; 261 buf[l] = n1*16 +n2; 262 } 263 des_key_sched(key, k); 264 des_cbc_encrypt((des_cblock *)buf,(des_cblock *)out,strlen(in)/2, 265 k,&i,DES_DECRYPT); 266 out[strlen(in)/2] = '\0'; 267 } 268