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