xref: /netbsd-src/crypto/external/bsd/heimdal/dist/lib/hcrypto/dh-ltm.c (revision d3273b5b76f5afaafe308cead5511dbb8df8c5e9)
1 /*	$NetBSD: dh-ltm.c,v 1.2 2017/01/28 21:31:47 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 2006 Kungliga Tekniska Högskolan
5  * (Royal Institute of Technology, Stockholm, Sweden).
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * 3. Neither the name of the Institute nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39 #include <krb5/roken.h>
40 
41 #include <dh.h>
42 
43 #include "tommath.h"
44 
45 static void
BN2mpz(mp_int * s,const BIGNUM * bn)46 BN2mpz(mp_int *s, const BIGNUM *bn)
47 {
48     size_t len;
49     void *p;
50 
51     len = BN_num_bytes(bn);
52     p = malloc(len);
53     BN_bn2bin(bn, p);
54     mp_read_unsigned_bin(s, p, len);
55     free(p);
56 }
57 
58 
59 static BIGNUM *
mpz2BN(mp_int * s)60 mpz2BN(mp_int *s)
61 {
62     size_t size;
63     BIGNUM *bn;
64     void *p;
65 
66     size = mp_unsigned_bin_size(s);
67     p = malloc(size);
68     if (p == NULL && size != 0)
69 	return NULL;
70     mp_to_unsigned_bin(s, p);
71 
72     bn = BN_bin2bn(p, size, NULL);
73     free(p);
74     return bn;
75 }
76 
77 /*
78  *
79  */
80 
81 #define DH_NUM_TRIES 10
82 
83 static int
ltm_dh_generate_key(DH * dh)84 ltm_dh_generate_key(DH *dh)
85 {
86     mp_int pub, priv_key, g, p;
87     int have_private_key = (dh->priv_key != NULL);
88     int codes, times = 0;
89     int res;
90 
91     if (dh->p == NULL || dh->g == NULL)
92 	return 0;
93 
94     while (times++ < DH_NUM_TRIES) {
95 	if (!have_private_key) {
96 	    size_t bits = BN_num_bits(dh->p);
97 
98 	    if (dh->priv_key)
99 		BN_free(dh->priv_key);
100 
101 	    dh->priv_key = BN_new();
102 	    if (dh->priv_key == NULL)
103 		return 0;
104 	    if (!BN_rand(dh->priv_key, bits - 1, 0, 0)) {
105 		BN_clear_free(dh->priv_key);
106 		dh->priv_key = NULL;
107 		return 0;
108 	    }
109 	}
110 	if (dh->pub_key) {
111 	    BN_free(dh->pub_key);
112 	    dh->pub_key = NULL;
113 	}
114 
115 	mp_init_multi(&pub, &priv_key, &g, &p, NULL);
116 
117 	BN2mpz(&priv_key, dh->priv_key);
118 	BN2mpz(&g, dh->g);
119 	BN2mpz(&p, dh->p);
120 
121 	res = mp_exptmod(&g, &priv_key, &p, &pub);
122 
123 	mp_clear_multi(&priv_key, &g, &p, NULL);
124 	if (res != 0)
125 	    continue;
126 
127 	dh->pub_key = mpz2BN(&pub);
128 	mp_clear(&pub);
129 	if (dh->pub_key == NULL)
130 	    return 0;
131 
132 	if (DH_check_pubkey(dh, dh->pub_key, &codes) && codes == 0)
133 	    break;
134 	if (have_private_key)
135 	    return 0;
136     }
137 
138     if (times >= DH_NUM_TRIES) {
139 	if (!have_private_key && dh->priv_key) {
140 	    BN_free(dh->priv_key);
141 	    dh->priv_key = NULL;
142 	}
143 	if (dh->pub_key) {
144 	    BN_free(dh->pub_key);
145 	    dh->pub_key = NULL;
146 	}
147 	return 0;
148     }
149 
150     return 1;
151 }
152 
153 static int
ltm_dh_compute_key(unsigned char * shared,const BIGNUM * pub,DH * dh)154 ltm_dh_compute_key(unsigned char *shared, const BIGNUM * pub, DH *dh)
155 {
156     mp_int s, priv_key, p, peer_pub;
157     int ret;
158 
159     if (dh->pub_key == NULL || dh->g == NULL || dh->priv_key == NULL)
160 	return -1;
161 
162     mp_init_multi(&s, &priv_key, &p, &peer_pub, NULL);
163     BN2mpz(&p, dh->p);
164     BN2mpz(&peer_pub, pub);
165 
166     /* check if peers pubkey is reasonable */
167     if (mp_isneg(&peer_pub)
168 	|| mp_cmp(&peer_pub, &p) >= 0
169 	|| mp_cmp_d(&peer_pub, 1) <= 0)
170     {
171 	ret = -1;
172 	goto out;
173     }
174 
175     BN2mpz(&priv_key, dh->priv_key);
176 
177     ret = mp_exptmod(&peer_pub, &priv_key, &p, &s);
178 
179     if (ret != 0) {
180 	ret = -1;
181 	goto out;
182     }
183 
184     ret = mp_unsigned_bin_size(&s);
185     mp_to_unsigned_bin(&s, shared);
186 
187  out:
188     mp_clear_multi(&s, &priv_key, &p, &peer_pub, NULL);
189 
190     return ret;
191 }
192 
193 static int
ltm_dh_generate_params(DH * dh,int a,int b,BN_GENCB * callback)194 ltm_dh_generate_params(DH *dh, int a, int b, BN_GENCB *callback)
195 {
196     /* groups should already be known, we don't care about this */
197     return 0;
198 }
199 
200 static int
ltm_dh_init(DH * dh)201 ltm_dh_init(DH *dh)
202 {
203     return 1;
204 }
205 
206 static int
ltm_dh_finish(DH * dh)207 ltm_dh_finish(DH *dh)
208 {
209     return 1;
210 }
211 
212 
213 /*
214  *
215  */
216 
217 const DH_METHOD _hc_dh_ltm_method = {
218     "hcrypto ltm DH",
219     ltm_dh_generate_key,
220     ltm_dh_compute_key,
221     NULL,
222     ltm_dh_init,
223     ltm_dh_finish,
224     0,
225     NULL,
226     ltm_dh_generate_params
227 };
228 
229 /**
230  * DH implementation using libtommath.
231  *
232  * @return the DH_METHOD for the DH implementation using libtommath.
233  *
234  * @ingroup hcrypto_dh
235  */
236 
237 const DH_METHOD *
DH_ltm_method(void)238 DH_ltm_method(void)
239 {
240     return &_hc_dh_ltm_method;
241 }
242