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