2 * Copyright (c) 1991, 1993
3 * Dave Safford. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
31 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD: src/contrib/telnet/libtelnet/pk.c,v 1.10 2002/08/22 06:19:07 nsayer Exp $");
36 __RCSID("$NetBSD: pk.c,v 1.3 2005/02/19 22:47:51 christos Exp $");
39 /* public key routines */
41 genkeys(char *public, char *secret)
42 common_key(char *secret, char *public, desData *deskey)
43 pk_encode(char *in, *out, DesData *deskey);
44 pk_decode(char *in, *out, DesData *deskey);
46 char public[HEXKEYBYTES + 1];
47 char secret[HEXKEYBYTES + 1];
52 #include <openssl/bn.h>
60 static void adjust(char *, const char *);
63 * Choose top 128 bits of the common key to use as our idea key.
66 extractideakey(BIGNUM
*ck
, IdeaData
*ideakey
)
70 BIGNUM
*base
= BN_new();
71 BN_CTX
*ctx
= BN_CTX_new();
77 (void)BN_set_word(base
, 1 << 8);
80 for (i
= 0; i
< ((KEYSIZE
- 128) / 8); i
++)
81 BN_div(a
, z
, a
, base
, ctx
);
83 k
= (char *)(void *)ideakey
;
84 for (i
= 0; i
< 16; i
++) {
85 BN_div(a
, z
, a
, base
, ctx
);
86 *k
++ = (char)BN_get_word(z
);
96 * Choose middle 64 bits of the common key to use as our des key, possibly
97 * overwriting the lower order bits by setting parity.
100 extractdeskey(BIGNUM
*ck
, DesData
*deskey
)
102 BIGNUM
*a
= BN_new();
103 BIGNUM
*z
= BN_new();
104 BIGNUM
*base
= BN_new();
105 BN_CTX
*ctx
= BN_CTX_new();
111 (void)BN_set_word(base
, 1 << 8);
114 for (i
= 0; i
< ((KEYSIZE
- 64) / 2) / 8; i
++)
115 BN_div(a
, z
, a
, base
, ctx
);
118 for (i
= 0; i
< 8; i
++) {
119 BN_div(a
, z
, a
, base
, ctx
);
120 *k
++ = (char)BN_get_word(z
);
130 * get common key from my secret key and his public key
133 common_key(char *xsecret
, char *xpublic
, IdeaData
*ideakey
, DesData
*deskey
)
135 BIGNUM
*public = BN_new();
136 BIGNUM
*secret
= BN_new();
137 BIGNUM
*common
= BN_new();
138 BIGNUM
*modulus
= BN_new();
139 BN_CTX
*ctx
= BN_CTX_new();
141 (void)BN_hex2bn(&modulus
, HEXMODULUS
);
142 (void)BN_hex2bn(&public, xpublic
);
143 (void)BN_hex2bn(&secret
, xsecret
);
144 (void)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
);
162 getseed(char *seed
, size_t seedsize
)
166 for (i
= 0; i
< seedsize
; i
++)
167 seed
[i
] = arc4random() & 0xff;
171 * Generate a random public/secret key pair
174 genkeys(char *public, char *secret
)
178 # define BASEBITS (8 * sizeof(short) - 1)
179 # define BASE (1 << BASEBITS)
181 BIGNUM
*pk
= BN_new();
182 BIGNUM
*sk
= BN_new();
183 BIGNUM
*tmp
= BN_new();
184 BIGNUM
*base
= BN_new();
185 BIGNUM
*root
= BN_new();
186 BIGNUM
*modulus
= BN_new();
187 BN_CTX
*ctx
= BN_CTX_new();
189 unsigned short seed
[KEYSIZE
/BASEBITS
+ 1];
194 (void)BN_set_word(base
, BASE
);
195 (void)BN_set_word(root
, PROOT
);
196 (void)BN_hex2bn(&modulus
, HEXMODULUS
);
198 getseed((char *)seed
, sizeof(seed
));
199 for (i
= 0; i
< KEYSIZE
/BASEBITS
+ 1; i
++) {
201 (void)BN_set_word(tmp
, r
);
202 BN_mul(sk
, tmp
, sk
, ctx
);
207 BN_div(tmp
, sk
, sk
, modulus
, ctx
);
208 BN_mod_exp(pk
, root
, sk
, modulus
, ctx
);
210 xkey
= BN_bn2hex(sk
);
211 adjust(secret
, xkey
);
212 xkey
= BN_bn2hex(pk
);
213 adjust(public, xkey
);
225 * Adjust the input key so that it is 0-filled on the left
228 adjust(char *keyout
, const char *keyin
)
233 for (p
= keyin
; *p
; p
++)
235 for (s
= keyout
+ HEXKEYBYTES
; p
>= keyin
; p
--, s
--)
241 static const char hextab
[] = "0123456789ABCDEF";
243 /* given a DES key, cbc encrypt and translate input to terminated hex */
245 pk_encode(const char *in
, char *out
, DesData
*key
)
250 size_t l
, op
, deslen
;
252 (void)memset(&i
, 0, sizeof(i
));
253 (void)memset(buf
, 0, sizeof(buf
));
254 deslen
= ((strlen(in
) + 7) / 8) * 8;
255 des_key_sched(key
, k
);
256 des_cbc_encrypt(in
, buf
, deslen
, k
, &i
, DES_ENCRYPT
);
257 for (l
= 0, op
= 0; l
< deslen
; l
++) {
258 out
[op
++] = hextab
[(buf
[l
] & 0xf0) >> 4];
259 out
[op
++] = hextab
[(buf
[l
] & 0x0f)];
264 /* given a DES key, translate input from hex and decrypt */
266 pk_decode(const char *in
, char *out
, DesData
*key
)
273 size_t len
= strlen(in
) / 2;
275 (void)memset(&i
, 0, sizeof(i
));
276 (void)memset(buf
, 0, sizeof(buf
));
278 for (l
= 0, op
= 0; l
< len
; l
++, op
+= 2) {
280 n1
= in
[op
] - 'A' + 10;
283 if (in
[op
+ 1] > '9')
284 n2
= in
[op
+ 1] - 'A' + 10;
286 n2
= in
[op
+ 1] - '0';
287 buf
[l
] = (char)(n1
* 16 + n2
);
289 des_key_sched(key
, k
);
290 des_cbc_encrypt(buf
, out
, len
, k
, &i
, DES_DECRYPT
);