pk.c revision 84305
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 <sys/cdefs.h> 13__FBSDID("$FreeBSD: head/contrib/telnet/libtelnet/pk.c 84305 2001-10-01 16:04:55Z markm $"); 14 15#include <sys/time.h> 16#include <openssl/des.h> 17#include <fcntl.h> 18#include <stdio.h> 19#include <string.h> 20#include "mp.h" 21#include "pk.h" 22#if defined(SOLARIS2) || defined(LINUX) || defined(__FreeBSD__) 23#include <stdlib.h> 24#endif 25 26static void adjust(char keyout[HEXKEYBYTES+1], char *keyin); 27 28/* 29 * Choose top 128 bits of the common key to use as our idea key. 30 */ 31static void 32extractideakey(MINT *ck, IdeaData *ideakey) 33{ 34 MINT *a; 35 MINT *z; 36 short r; 37 int i; 38 short base = (1 << 8); 39 char *k; 40 41 z = itom(0); 42 a = itom(0); 43 madd(ck, z, a); 44 for (i = 0; i < ((KEYSIZE - 128) / 8); i++) { 45 sdiv(a, base, a, &r); 46 } 47 k = (char *)ideakey; 48 for (i = 0; i < 16; i++) { 49 sdiv(a, base, a, &r); 50 *k++ = r; 51 } 52 mfree(z); 53 mfree(a); 54} 55 56/* 57 * Choose middle 64 bits of the common key to use as our des key, possibly 58 * overwriting the lower order bits by setting parity. 59 */ 60static void 61extractdeskey(MINT *ck, 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 */ 88void 89common_key(char *xsecret, char *xpublic, IdeaData *ideakey, DesData *deskey) 90{ 91 MINT *public; 92 MINT *secret; 93 MINT *common; 94 MINT *modulus = xtom(HEXMODULUS); 95 96 public = xtom(xpublic); 97 secret = xtom(xsecret); 98 common = itom(0); 99 pow(public, secret, modulus, common); 100 extractdeskey(common, deskey); 101 extractideakey(common, ideakey); 102#if DES_OSTHOLM 103 des_fixup_key_parity(deskey); 104#else 105 des_set_odd_parity(deskey); 106#endif 107 mfree(common); 108 mfree(secret); 109 mfree(public); 110 mfree(modulus); 111} 112 113/* 114 * Generate a seed 115 */ 116void 117getseed(char *seed, int seedsize) 118{ 119 int i; 120 121 srandomdev(); 122 for (i = 0; i < seedsize; i++) { 123 seed[i] = random() & 0xff; 124 } 125} 126 127/* 128 * Generate a random public/secret key pair 129 */ 130void 131genkeys(char *public, char *secret) 132{ 133 int i; 134 135# define BASEBITS (8*sizeof(short) - 1) 136# define BASE (1 << BASEBITS) 137 138 MINT *pk = itom(0); 139 MINT *sk = itom(0); 140 MINT *tmp; 141 MINT *base = itom(BASE); 142 MINT *root = itom(PROOT); 143 MINT *modulus = xtom(HEXMODULUS); 144 short r; 145 unsigned short seed[KEYSIZE/BASEBITS + 1]; 146 char *xkey; 147 148 getseed((char *)seed, sizeof(seed)); 149 for (i = 0; i < KEYSIZE/BASEBITS + 1; i++) { 150 r = seed[i] % BASE; 151 tmp = itom(r); 152 mult(sk, base, sk); 153 madd(sk, tmp, sk); 154 mfree(tmp); 155 } 156 tmp = itom(0); 157 mdiv(sk, modulus, tmp, sk); 158 mfree(tmp); 159 pow(root, sk, modulus, pk); 160 xkey = mtox(sk); 161 adjust(secret, xkey); 162 xkey = mtox(pk); 163 adjust(public, xkey); 164 mfree(sk); 165 mfree(base); 166 mfree(pk); 167 mfree(root); 168 mfree(modulus); 169} 170 171/* 172 * Adjust the input key so that it is 0-filled on the left 173 */ 174static void 175adjust(char keyout[HEXKEYBYTES+1], char *keyin) 176{ 177 char *p; 178 char *s; 179 180 for (p = keyin; *p; p++) 181 ; 182 for (s = keyout + HEXKEYBYTES; p >= keyin; p--, s--) { 183 *s = *p; 184 } 185 while (s >= keyout) { 186 *s-- = '0'; 187 } 188} 189 190static char hextab[17] = "0123456789ABCDEF"; 191 192/* given a DES key, cbc encrypt and translate input to terminated hex */ 193void 194pk_encode(char *in, char *out, DesData *key) 195{ 196 char buf[256]; 197 DesData i; 198 des_key_schedule k; 199 int l,op,deslen; 200 201 memset(&i,0,sizeof(i)); 202 memset(buf,0,sizeof(buf)); 203 deslen = ((strlen(in) + 7)/8)*8; 204 des_key_sched(key, k); 205 des_cbc_encrypt(in,buf,deslen, k,&i,DES_ENCRYPT); 206 for (l=0,op=0;l<deslen;l++) { 207 out[op++] = hextab[(buf[l] & 0xf0) >> 4]; 208 out[op++] = hextab[(buf[l] & 0x0f)]; 209 } 210 out[op] = '\0'; 211} 212 213/* given a DES key, translate input from hex and decrypt */ 214void 215pk_decode(char *in, char *out, DesData *key) 216{ 217 char buf[256]; 218 DesData i; 219 des_key_schedule k; 220 int l,n1,n2,op; 221 222 memset(&i,0,sizeof(i)); 223 memset(buf,0,sizeof(buf)); 224 for (l=0,op=0;l<strlen(in)/2;l++,op+=2) { 225 if(in[op] == '0' && in[op+1] == '0') { 226 buf[l] = '\0'; 227 break; 228 } 229 if (in[op] > '9') 230 n1 = in[op] - 'A' + 10; 231 else 232 n1 = in[op] - '0'; 233 if (in[op+1] > '9') 234 n2 = in[op+1] - 'A' + 10; 235 else 236 n2 = in[op+1] - '0'; 237 buf[l] = n1*16 +n2; 238 } 239 des_key_sched(key, k); 240 des_cbc_encrypt(buf,out,strlen(in)/2, k,&i,DES_DECRYPT); 241 out[strlen(in)/2] = '\0'; 242} 243