1 /*- 2 * Copyright (c) 1991, 1993 3 * Dave Safford. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 */ 30 31 #include <sys/cdefs.h> 32 33 __FBSDID("$FreeBSD$"); 34 35 /* public key routines */ 36 /* functions: 37 genkeys(char *public, char *secret) 38 common_key(char *secret, char *public, desData *deskey) 39 pk_encode(char *in, *out, DesData *deskey); 40 pk_decode(char *in, *out, DesData *deskey); 41 where 42 char public[HEXKEYBYTES + 1]; 43 char secret[HEXKEYBYTES + 1]; 44 */ 45 46 #include <sys/time.h> 47 #include <openssl/des.h> 48 #include <fcntl.h> 49 #include <stdio.h> 50 #include <stdlib.h> 51 #include <string.h> 52 53 #include "mp.h" 54 #include "pk.h" 55 56 static void adjust(char keyout[HEXKEYBYTES+1], char *keyin); 57 58 /* 59 * Choose top 128 bits of the common key to use as our idea key. 60 */ 61 static void 62 extractideakey(MINT *ck, IdeaData *ideakey) 63 { 64 MINT *a; 65 MINT *z; 66 short r; 67 int i; 68 short base = (1 << 8); 69 char *k; 70 71 z = mp_itom(0); 72 a = mp_itom(0); 73 mp_madd(ck, z, a); 74 for (i = 0; i < ((KEYSIZE - 128) / 8); i++) { 75 mp_sdiv(a, base, a, &r); 76 } 77 k = (char *)ideakey; 78 for (i = 0; i < 16; i++) { 79 mp_sdiv(a, base, a, &r); 80 *k++ = r; 81 } 82 mp_mfree(z); 83 mp_mfree(a); 84 } 85 86 /* 87 * Choose middle 64 bits of the common key to use as our des key, possibly 88 * overwriting the lower order bits by setting parity. 89 */ 90 static void 91 extractdeskey(MINT *ck, DesData *deskey) 92 { 93 MINT *a; 94 MINT *z; 95 short r; 96 int i; 97 short base = (1 << 8); 98 char *k; 99 100 z = mp_itom(0); 101 a = mp_itom(0); 102 mp_madd(ck, z, a); 103 for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) { 104 mp_sdiv(a, base, a, &r); 105 } 106 k = (char *)deskey; 107 for (i = 0; i < 8; i++) { 108 mp_sdiv(a, base, a, &r); 109 *k++ = r; 110 } 111 mp_mfree(z); 112 mp_mfree(a); 113 } 114 115 /* 116 * get common key from my secret key and his public key 117 */ 118 void 119 common_key(char *xsecret, char *xpublic, IdeaData *ideakey, DesData *deskey) 120 { 121 MINT *public; 122 MINT *secret; 123 MINT *common; 124 MINT *modulus = mp_xtom(HEXMODULUS); 125 126 public = mp_xtom(xpublic); 127 secret = mp_xtom(xsecret); 128 common = mp_itom(0); 129 mp_pow(public, secret, modulus, common); 130 extractdeskey(common, deskey); 131 extractideakey(common, ideakey); 132 des_set_odd_parity(deskey); 133 mp_mfree(common); 134 mp_mfree(secret); 135 mp_mfree(public); 136 mp_mfree(modulus); 137 } 138 139 /* 140 * Generate a seed 141 */ 142 static void 143 getseed(char *seed, int seedsize) 144 { 145 int i; 146 147 srandomdev(); 148 for (i = 0; i < seedsize; i++) { 149 seed[i] = random() & 0xff; 150 } 151 } 152 153 /* 154 * Generate a random public/secret key pair 155 */ 156 void 157 genkeys(char *public, char *secret) 158 { 159 size_t i; 160 161 # define BASEBITS (8*sizeof(short) - 1) 162 # define BASE (1 << BASEBITS) 163 164 MINT *pk = mp_itom(0); 165 MINT *sk = mp_itom(0); 166 MINT *tmp; 167 MINT *base = mp_itom((short)BASE); 168 MINT *root = mp_itom(PROOT); 169 MINT *modulus = mp_xtom(HEXMODULUS); 170 short r; 171 unsigned short seed[KEYSIZE/BASEBITS + 1]; 172 char *xkey; 173 174 getseed((char *)seed, sizeof(seed)); 175 for (i = 0; i < KEYSIZE/BASEBITS + 1; i++) { 176 r = seed[i] % BASE; 177 tmp = mp_itom(r); 178 mp_mult(sk, base, sk); 179 mp_madd(sk, tmp, sk); 180 mp_mfree(tmp); 181 } 182 tmp = mp_itom(0); 183 mp_mdiv(sk, modulus, tmp, sk); 184 mp_mfree(tmp); 185 mp_pow(root, sk, modulus, pk); 186 xkey = mp_mtox(sk); 187 adjust(secret, xkey); 188 xkey = mp_mtox(pk); 189 adjust(public, xkey); 190 mp_mfree(sk); 191 mp_mfree(base); 192 mp_mfree(pk); 193 mp_mfree(root); 194 mp_mfree(modulus); 195 } 196 197 /* 198 * Adjust the input key so that it is 0-filled on the left 199 */ 200 static void 201 adjust(char keyout[HEXKEYBYTES+1], char *keyin) 202 { 203 char *p; 204 char *s; 205 206 for (p = keyin; *p; p++) 207 ; 208 for (s = keyout + HEXKEYBYTES; p >= keyin; p--, s--) { 209 *s = *p; 210 } 211 while (s >= keyout) { 212 *s-- = '0'; 213 } 214 } 215 216 static char hextab[17] = "0123456789ABCDEF"; 217 218 /* given a DES key, cbc encrypt and translate input to terminated hex */ 219 void 220 pk_encode(char *in, char *out, DesData *key) 221 { 222 char buf[256]; 223 DesData i; 224 des_key_schedule k; 225 int l,op,deslen; 226 227 memset(&i,0,sizeof(i)); 228 memset(buf,0,sizeof(buf)); 229 deslen = ((strlen(in) + 7)/8)*8; 230 des_key_sched(key, k); 231 des_cbc_encrypt(in,buf,deslen, k,&i,DES_ENCRYPT); 232 for (l=0,op=0;l<deslen;l++) { 233 out[op++] = hextab[(buf[l] & 0xf0) >> 4]; 234 out[op++] = hextab[(buf[l] & 0x0f)]; 235 } 236 out[op] = '\0'; 237 } 238 239 /* given a DES key, translate input from hex and decrypt */ 240 void 241 pk_decode(char *in, char *out, DesData *key) 242 { 243 char buf[256]; 244 DesData i; 245 des_key_schedule k; 246 int n1,n2,op; 247 size_t l; 248 249 memset(&i,0,sizeof(i)); 250 memset(buf,0,sizeof(buf)); 251 for (l=0,op=0;l<strlen(in)/2;l++,op+=2) { 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(buf,out,strlen(in)/2, k,&i,DES_DECRYPT); 264 out[strlen(in)/2] = '\0'; 265 } 266