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