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 * $FreeBSD: src/crypto/telnet/libtelnet/pk.c,v 1.2.2.4 2002/08/24 07:28:35 nsayer Exp $ 31 */ 32 33 /* public key routines */ 34 /* functions: 35 genkeys(char *public, char *secret) 36 common_key(char *secret, char *public, desData *deskey) 37 pk_encode(char *in, *out, DesData *deskey); 38 pk_decode(char *in, *out, DesData *deskey); 39 where 40 char public[HEXKEYBYTES + 1]; 41 char secret[HEXKEYBYTES + 1]; 42 */ 43 44 #include <sys/time.h> 45 #include <err.h> 46 #include <fcntl.h> 47 #include <stdio.h> 48 #include <stdlib.h> 49 #include <string.h> 50 51 #include <openssl/bn.h> 52 #include <openssl/crypto.h> 53 #include <openssl/des.h> 54 #include <openssl/err.h> 55 56 #include "pk.h" 57 58 static void adjust(char keyout[HEXKEYBYTES+1], char *keyin); 59 60 /* 61 * Choose top 128 bits of the common key to use as our idea key. 62 */ 63 static void 64 extractideakey(BIGNUM *ck, IdeaData *ideakey) 65 { 66 BIGNUM *a, *z; 67 int i; 68 BN_ULONG r, base = (1 << 8); 69 char *k; 70 71 if ((z = BN_new()) == NULL) 72 errx(1, "could not create BIGNUM"); 73 BN_zero(z); 74 if ((a = BN_new()) == NULL) 75 errx(1, "could not create BIGNUM"); 76 BN_zero(a); 77 BN_add(a, ck, z); 78 for (i = 0; i < ((KEYSIZE - 128) / 8); i++) { 79 r = BN_div_word(a, base); 80 } 81 k = (char *)ideakey; 82 for (i = 0; i < 16; i++) { 83 r = BN_div_word(a, base); 84 *k++ = r; 85 } 86 BN_free(z); 87 BN_free(a); 88 } 89 90 /* 91 * Choose middle 64 bits of the common key to use as our des key, possibly 92 * overwriting the lower order bits by setting parity. 93 */ 94 static void 95 extractdeskey(BIGNUM *ck, DesData *deskey) 96 { 97 BIGNUM *a, *z; 98 int i; 99 BN_ULONG r, base = (1 << 8); 100 char *k; 101 102 if ((z = BN_new()) == NULL) 103 errx(1, "could not create BIGNUM"); 104 BN_zero(z); 105 if ((a = BN_new()) == NULL) 106 errx(1, "could not create BIGNUM"); 107 BN_zero(a); 108 BN_add(a, ck, z); 109 for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) { 110 r = BN_div_word(a, base); 111 } 112 k = (char *)deskey; 113 for (i = 0; i < 8; i++) { 114 r = BN_div_word(a, base); 115 *k++ = r; 116 } 117 BN_free(z); 118 BN_free(a); 119 } 120 121 /* 122 * get common key from my secret key and his public key 123 */ 124 void 125 common_key(char *xsecret, char *xpublic, IdeaData *ideakey, DesData *deskey) 126 { 127 BIGNUM *public, *secret, *common, *modulus; 128 BN_CTX *ctx; 129 130 if ((ctx = BN_CTX_new()) == NULL) 131 errx(1, "could not create BN_CTX"); 132 modulus = NULL; 133 if (BN_hex2bn(&modulus, HEXMODULUS) == 0) 134 errx(1, "could not convert modulus"); 135 public = NULL; 136 if (BN_hex2bn(&public, xpublic) == 0) 137 errx(1, "could not convert public"); 138 secret = NULL; 139 if (BN_hex2bn(&secret, xsecret) == 0) 140 errx(1, "could not convert secret"); 141 142 if ((common = BN_new()) == NULL) 143 errx(1, "could not create BIGNUM"); 144 BN_zero(common); 145 BN_mod_exp(common, public, secret, modulus, ctx); 146 extractdeskey(common, deskey); 147 extractideakey(common, ideakey); 148 DES_set_odd_parity(deskey); 149 BN_free(common); 150 BN_free(secret); 151 BN_free(public); 152 BN_free(modulus); 153 BN_CTX_free(ctx); 154 } 155 156 /* 157 * Generate a seed 158 */ 159 static void 160 getseed(char *seed, int seedsize) 161 { 162 int i; 163 164 for (i = 0; i < seedsize; i++) { 165 seed[i] = arc4random() & 0xff; 166 } 167 } 168 169 static BIGNUM * 170 itobn(long i) 171 { 172 BIGNUM *n = NULL; 173 174 if ((n = BN_new()) == NULL) 175 errx(1, "could not create BIGNUM: %s", 176 ERR_error_string(ERR_get_error(), 0)); 177 BN_init(n); 178 if (i > 0) 179 BN_add_word(n, (u_long)i); 180 else 181 BN_sub_word(n, (u_long)(-i)); 182 return(n); 183 } 184 185 /* 186 * Generate a random public/secret key pair 187 */ 188 void 189 genkeys(char *public, char *secret) 190 { 191 #define BASEBITS (8*sizeof (short) - 1) 192 #define BASE (short)(1 << BASEBITS) 193 194 unsigned int i; 195 short r; 196 unsigned short seed[KEYSIZE/BASEBITS + 1]; 197 char *xkey; 198 199 BN_CTX *ctx; 200 BIGNUM *pk, *sk, *tmp, *base, *root, *modulus; 201 202 pk = itobn(0); 203 sk = itobn(0); 204 tmp = itobn(0); 205 base = itobn(BASE); 206 root = itobn(PROOT); 207 modulus = NULL; 208 if (BN_hex2bn(&modulus, HEXMODULUS) == 0) 209 errx(1, "could not convert modulus to BIGNUM: %s", 210 ERR_error_string(ERR_get_error(), 0)); 211 212 if ((ctx = BN_CTX_new()) == NULL) 213 errx(1, "could not create BN_CTX: %s", 214 ERR_error_string(ERR_get_error(), 0)); 215 216 getseed((char *)seed, sizeof (seed)); 217 for (i = 0; i < KEYSIZE/BASEBITS + 1; i++) { 218 r = seed[i] % BASE; 219 BN_zero(tmp); 220 BN_add_word(tmp, r); 221 BN_mul(sk, base, sk, ctx); 222 BN_add(sk, tmp, sk); 223 } 224 BN_zero(tmp); 225 BN_div(tmp, sk, sk, modulus, ctx); 226 BN_mod_exp(pk, root, sk, modulus, ctx); 227 228 if ((xkey = BN_bn2hex(sk)) == NULL) 229 errx(1, "could convert sk to hex: %s", 230 ERR_error_string(ERR_get_error(), 0)); 231 adjust(secret, xkey); 232 OPENSSL_free(xkey); 233 234 if ((xkey = BN_bn2hex(pk)) == NULL) 235 errx(1, "could convert pk to hex: %s", 236 ERR_error_string(ERR_get_error(), 0)); 237 adjust(public, xkey); 238 OPENSSL_free(xkey); 239 240 BN_free(base); 241 BN_free(modulus); 242 BN_free(pk); 243 BN_free(sk); 244 BN_free(root); 245 BN_free(tmp); 246 } 247 248 /* 249 * Adjust the input key so that it is 0-filled on the left 250 */ 251 static void 252 adjust(char keyout[HEXKEYBYTES+1], char *keyin) 253 { 254 char *p; 255 char *s; 256 257 for (p = keyin; *p; p++) 258 ; 259 for (s = keyout + HEXKEYBYTES; p >= keyin; p--, s--) { 260 *s = *p; 261 } 262 while (s >= keyout) { 263 *s-- = '0'; 264 } 265 } 266 267 static char hextab[17] = "0123456789ABCDEF"; 268 269 /* given a DES key, cbc encrypt and translate input to terminated hex */ 270 void 271 pk_encode(char *in, char *out, DesData *key) 272 { 273 char buf[256]; 274 DesData i; 275 DES_key_schedule k; 276 int l,op,deslen; 277 278 memset(&i,0,sizeof(i)); 279 memset(buf,0,sizeof(buf)); 280 deslen = ((strlen(in) + 7)/8)*8; 281 DES_key_sched(key, &k); 282 DES_cbc_encrypt(in,buf,deslen, &k,&i,DES_ENCRYPT); 283 for (l=0,op=0;l<deslen;l++) { 284 out[op++] = hextab[(buf[l] & 0xf0) >> 4]; 285 out[op++] = hextab[(buf[l] & 0x0f)]; 286 } 287 out[op] = '\0'; 288 } 289 290 /* given a DES key, translate input from hex and decrypt */ 291 void 292 pk_decode(char *in, char *out, DesData *key) 293 { 294 char buf[256]; 295 DesData i; 296 DES_key_schedule k; 297 int n1,n2,op; 298 size_t l; 299 300 memset(&i,0,sizeof(i)); 301 memset(buf,0,sizeof(buf)); 302 for (l=0,op=0;l<strlen(in)/2;l++,op+=2) { 303 if (in[op] > '9') 304 n1 = in[op] - 'A' + 10; 305 else 306 n1 = in[op] - '0'; 307 if (in[op+1] > '9') 308 n2 = in[op+1] - 'A' + 10; 309 else 310 n2 = in[op+1] - '0'; 311 buf[l] = n1*16 +n2; 312 } 313 DES_key_sched(key, &k); 314 DES_cbc_encrypt(buf,out,strlen(in)/2, &k,&i,DES_DECRYPT); 315 out[strlen(in)/2] = '\0'; 316 } 317