1185393efSchristos /*-
2185393efSchristos * Copyright (c) 1991, 1993
3185393efSchristos * Dave Safford. All rights reserved.
4185393efSchristos *
5185393efSchristos * Redistribution and use in source and binary forms, with or without
6185393efSchristos * modification, are permitted provided that the following conditions
7185393efSchristos * are met:
8185393efSchristos * 1. Redistributions of source code must retain the above copyright
9185393efSchristos * notice, this list of conditions and the following disclaimer.
10185393efSchristos * 2. Redistributions in binary form must reproduce the above copyright
11185393efSchristos * notice, this list of conditions and the following disclaimer in the
12185393efSchristos * documentation and/or other materials provided with the distribution.
13185393efSchristos * 3. Neither the name of the University nor the names of its contributors
14185393efSchristos * may be used to endorse or promote products derived from this software
15185393efSchristos * without specific prior written permission.
16185393efSchristos *
17185393efSchristos * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18185393efSchristos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19185393efSchristos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20185393efSchristos * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21185393efSchristos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22185393efSchristos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23185393efSchristos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24185393efSchristos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25185393efSchristos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26185393efSchristos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27185393efSchristos * SUCH DAMAGE.
28185393efSchristos *
29185393efSchristos */
30185393efSchristos
31185393efSchristos #include <sys/cdefs.h>
32185393efSchristos
33185393efSchristos #ifdef notdef
34185393efSchristos __FBSDID("$FreeBSD: src/contrib/telnet/libtelnet/pk.c,v 1.10 2002/08/22 06:19:07 nsayer Exp $");
35185393efSchristos #else
36*a6d2304bSchristos __RCSID("$NetBSD: pk.c,v 1.4 2005/02/19 22:55:35 christos Exp $");
37185393efSchristos #endif
38185393efSchristos
39185393efSchristos /* public key routines */
40185393efSchristos /* functions:
41185393efSchristos genkeys(char *public, char *secret)
42185393efSchristos common_key(char *secret, char *public, desData *deskey)
43185393efSchristos pk_encode(char *in, *out, DesData *deskey);
44185393efSchristos pk_decode(char *in, *out, DesData *deskey);
45185393efSchristos where
46185393efSchristos char public[HEXKEYBYTES + 1];
47185393efSchristos char secret[HEXKEYBYTES + 1];
48185393efSchristos */
49185393efSchristos
50185393efSchristos #include <sys/time.h>
51c8127943Schristos #include <des.h>
52c8127943Schristos #include <openssl/bn.h>
53185393efSchristos #include <fcntl.h>
54185393efSchristos #include <stdio.h>
55185393efSchristos #include <stdlib.h>
56185393efSchristos #include <string.h>
57185393efSchristos
58185393efSchristos #include "pk.h"
59185393efSchristos
60*a6d2304bSchristos static void adjust(char *, const char *);
61185393efSchristos
62185393efSchristos /*
63185393efSchristos * Choose top 128 bits of the common key to use as our idea key.
64185393efSchristos */
65185393efSchristos static void
extractideakey(BIGNUM * ck,IdeaData * ideakey)66c8127943Schristos extractideakey(BIGNUM *ck, IdeaData *ideakey)
67185393efSchristos {
68c8127943Schristos BIGNUM *a = BN_new();
69c8127943Schristos BIGNUM *z = BN_new();
70c8127943Schristos BIGNUM *base = BN_new();
71c8127943Schristos BN_CTX *ctx = BN_CTX_new();
72*a6d2304bSchristos size_t i;
73185393efSchristos char *k;
74185393efSchristos
75c8127943Schristos (void)BN_zero(a);
76c8127943Schristos (void)BN_zero(z);
77c8127943Schristos (void)BN_set_word(base, 1 << 8);
78c8127943Schristos BN_add(a, ck, z);
79c8127943Schristos
80c8127943Schristos for (i = 0; i < ((KEYSIZE - 128) / 8); i++)
81c8127943Schristos BN_div(a, z, a, base, ctx);
82c8127943Schristos
83*a6d2304bSchristos k = (char *)(void *)ideakey;
84185393efSchristos for (i = 0; i < 16; i++) {
85c8127943Schristos BN_div(a, z, a, base, ctx);
86c8127943Schristos *k++ = (char)BN_get_word(z);
87185393efSchristos }
88c8127943Schristos
89c8127943Schristos BN_CTX_free(ctx);
90c8127943Schristos BN_free(base);
91c8127943Schristos BN_free(z);
92c8127943Schristos BN_free(a);
93185393efSchristos }
94185393efSchristos
95185393efSchristos /*
96185393efSchristos * Choose middle 64 bits of the common key to use as our des key, possibly
97185393efSchristos * overwriting the lower order bits by setting parity.
98185393efSchristos */
99185393efSchristos static void
extractdeskey(BIGNUM * ck,DesData * deskey)100c8127943Schristos extractdeskey(BIGNUM *ck, DesData *deskey)
101185393efSchristos {
102c8127943Schristos BIGNUM *a = BN_new();
103c8127943Schristos BIGNUM *z = BN_new();
104c8127943Schristos BIGNUM *base = BN_new();
105c8127943Schristos BN_CTX *ctx = BN_CTX_new();
106*a6d2304bSchristos size_t i;
107185393efSchristos char *k;
108185393efSchristos
109c8127943Schristos (void)BN_zero(z);
110c8127943Schristos (void)BN_zero(a);
111c8127943Schristos (void)BN_set_word(base, 1 << 8);
112c8127943Schristos BN_add(a, ck, z);
113c8127943Schristos
114c8127943Schristos for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++)
115c8127943Schristos BN_div(a, z, a, base, ctx);
116c8127943Schristos
117185393efSchristos k = (char *)deskey;
118185393efSchristos for (i = 0; i < 8; i++) {
119c8127943Schristos BN_div(a, z, a, base, ctx);
120c8127943Schristos *k++ = (char)BN_get_word(z);
121185393efSchristos }
122c8127943Schristos
123c8127943Schristos BN_CTX_free(ctx);
124c8127943Schristos BN_free(base);
125c8127943Schristos BN_free(z);
126c8127943Schristos BN_free(a);
127185393efSchristos }
128185393efSchristos
129185393efSchristos /*
130185393efSchristos * get common key from my secret key and his public key
131185393efSchristos */
132185393efSchristos void
common_key(char * xsecret,char * xpublic,IdeaData * ideakey,DesData * deskey)133185393efSchristos common_key(char *xsecret, char *xpublic, IdeaData *ideakey, DesData *deskey)
134185393efSchristos {
135c8127943Schristos BIGNUM *public = BN_new();
136c8127943Schristos BIGNUM *secret = BN_new();
137c8127943Schristos BIGNUM *common = BN_new();
138c8127943Schristos BIGNUM *modulus = BN_new();
139c8127943Schristos BN_CTX *ctx = BN_CTX_new();
140185393efSchristos
141c8127943Schristos (void)BN_hex2bn(&modulus, HEXMODULUS);
142c8127943Schristos (void)BN_hex2bn(&public, xpublic);
143c8127943Schristos (void)BN_hex2bn(&secret, xsecret);
144c8127943Schristos (void)BN_zero(common);
145c8127943Schristos
146c8127943Schristos BN_mod_exp(common, public, secret, modulus, ctx);
147185393efSchristos extractdeskey(common, deskey);
148185393efSchristos extractideakey(common, ideakey);
149185393efSchristos des_set_odd_parity(deskey);
150c8127943Schristos
151c8127943Schristos BN_CTX_free(ctx);
152c8127943Schristos BN_free(common);
153c8127943Schristos BN_free(secret);
154c8127943Schristos BN_free(public);
155c8127943Schristos BN_free(modulus);
156185393efSchristos }
157185393efSchristos
158185393efSchristos /*
159185393efSchristos * Generate a seed
160185393efSchristos */
161185393efSchristos static void
getseed(char * seed,size_t seedsize)162*a6d2304bSchristos getseed(char *seed, size_t seedsize)
163185393efSchristos {
164*a6d2304bSchristos size_t i;
165185393efSchristos
166c8127943Schristos for (i = 0; i < seedsize; i++)
167c8127943Schristos seed[i] = arc4random() & 0xff;
168185393efSchristos }
169185393efSchristos
170185393efSchristos /*
171185393efSchristos * Generate a random public/secret key pair
172185393efSchristos */
173185393efSchristos void
genkeys(char * public,char * secret)174185393efSchristos genkeys(char *public, char *secret)
175185393efSchristos {
176185393efSchristos size_t i;
177185393efSchristos
178185393efSchristos # define BASEBITS (8 * sizeof(short) - 1)
179185393efSchristos # define BASE (1 << BASEBITS)
180185393efSchristos
181c8127943Schristos BIGNUM *pk = BN_new();
182c8127943Schristos BIGNUM *sk = BN_new();
183c8127943Schristos BIGNUM *tmp = BN_new();
184c8127943Schristos BIGNUM *base = BN_new();
185c8127943Schristos BIGNUM *root = BN_new();
186c8127943Schristos BIGNUM *modulus = BN_new();
187c8127943Schristos BN_CTX *ctx = BN_CTX_new();
188185393efSchristos short r;
189185393efSchristos unsigned short seed[KEYSIZE/BASEBITS + 1];
190185393efSchristos char *xkey;
191185393efSchristos
192c8127943Schristos (void)BN_zero(pk);
193c8127943Schristos (void)BN_zero(sk);
194c8127943Schristos (void)BN_set_word(base, BASE);
195c8127943Schristos (void)BN_set_word(root, PROOT);
196c8127943Schristos (void)BN_hex2bn(&modulus, HEXMODULUS);
197c8127943Schristos
198185393efSchristos getseed((char *)seed, sizeof(seed));
199185393efSchristos for (i = 0; i < KEYSIZE/BASEBITS + 1; i++) {
200185393efSchristos r = seed[i] % BASE;
201c8127943Schristos (void)BN_set_word(tmp, r);
202c8127943Schristos BN_mul(sk, tmp, sk, ctx);
203c8127943Schristos BN_add(sk, tmp, sk);
204185393efSchristos }
205c8127943Schristos
206c8127943Schristos (void)BN_zero(tmp);
207c8127943Schristos BN_div(tmp, sk, sk, modulus, ctx);
208c8127943Schristos BN_mod_exp(pk, root, sk, modulus, ctx);
209c8127943Schristos
210c8127943Schristos xkey = BN_bn2hex(sk);
211185393efSchristos adjust(secret, xkey);
212c8127943Schristos xkey = BN_bn2hex(pk);
213185393efSchristos adjust(public, xkey);
214c8127943Schristos
215c8127943Schristos BN_CTX_free(ctx);
216c8127943Schristos BN_free(sk);
217c8127943Schristos BN_free(base);
218c8127943Schristos BN_free(pk);
219c8127943Schristos BN_free(tmp);
220c8127943Schristos BN_free(root);
221c8127943Schristos BN_free(modulus);
222185393efSchristos }
223185393efSchristos
224185393efSchristos /*
225185393efSchristos * Adjust the input key so that it is 0-filled on the left
226185393efSchristos */
227185393efSchristos static void
adjust(char * keyout,const char * keyin)228*a6d2304bSchristos adjust(char *keyout, const char *keyin)
229185393efSchristos {
230*a6d2304bSchristos const char *p;
231185393efSchristos char *s;
232185393efSchristos
233185393efSchristos for (p = keyin; *p; p++)
234*a6d2304bSchristos continue;
235*a6d2304bSchristos for (s = keyout + HEXKEYBYTES; p >= keyin; p--, s--)
236185393efSchristos *s = *p;
237*a6d2304bSchristos while (s >= keyout)
238185393efSchristos *s-- = '0';
239185393efSchristos }
240185393efSchristos
241*a6d2304bSchristos static const char hextab[] = "0123456789ABCDEF";
242185393efSchristos
243185393efSchristos /* given a DES key, cbc encrypt and translate input to terminated hex */
244185393efSchristos void
pk_encode(const char * in,char * out,DesData * key)245*a6d2304bSchristos pk_encode(const char *in, char *out, DesData *key)
246185393efSchristos {
247185393efSchristos char buf[256];
248185393efSchristos DesData i;
249185393efSchristos des_key_schedule k;
250*a6d2304bSchristos size_t l, op, deslen;
251185393efSchristos
252*a6d2304bSchristos (void)memset(&i, 0, sizeof(i));
253*a6d2304bSchristos (void)memset(buf, 0, sizeof(buf));
254185393efSchristos deslen = ((strlen(in) + 7) / 8) * 8;
255185393efSchristos des_key_sched(key, k);
256185393efSchristos des_cbc_encrypt(in, buf, deslen, k, &i, DES_ENCRYPT);
257185393efSchristos for (l = 0, op = 0; l < deslen; l++) {
258185393efSchristos out[op++] = hextab[(buf[l] & 0xf0) >> 4];
259185393efSchristos out[op++] = hextab[(buf[l] & 0x0f)];
260185393efSchristos }
261185393efSchristos out[op] = '\0';
262185393efSchristos }
263185393efSchristos
264185393efSchristos /* given a DES key, translate input from hex and decrypt */
265185393efSchristos void
pk_decode(const char * in,char * out,DesData * key)266*a6d2304bSchristos pk_decode(const char *in, char *out, DesData *key)
267185393efSchristos {
268185393efSchristos char buf[256];
269185393efSchristos DesData i;
270185393efSchristos des_key_schedule k;
271185393efSchristos int n1, n2, op;
272185393efSchristos size_t l;
273*a6d2304bSchristos size_t len = strlen(in) / 2;
274185393efSchristos
275*a6d2304bSchristos (void)memset(&i, 0, sizeof(i));
276*a6d2304bSchristos (void)memset(buf, 0, sizeof(buf));
277*a6d2304bSchristos
278*a6d2304bSchristos for (l = 0, op = 0; l < len; l++, op += 2) {
279185393efSchristos if (in[op] > '9')
280185393efSchristos n1 = in[op] - 'A' + 10;
281185393efSchristos else
282185393efSchristos n1 = in[op] - '0';
283185393efSchristos if (in[op + 1] > '9')
284185393efSchristos n2 = in[op + 1] - 'A' + 10;
285185393efSchristos else
286185393efSchristos n2 = in[op + 1] - '0';
287*a6d2304bSchristos buf[l] = (char)(n1 * 16 + n2);
288185393efSchristos }
289185393efSchristos des_key_sched(key, k);
290*a6d2304bSchristos des_cbc_encrypt(buf, out, len, k, &i, DES_DECRYPT);
291*a6d2304bSchristos out[len] = '\0';
292185393efSchristos }
293