xref: /netbsd-src/crypto/external/bsd/heimdal/dist/lib/hcrypto/dh-tfm.c (revision d3273b5b76f5afaafe308cead5511dbb8df8c5e9)
1 /*	$NetBSD: dh-tfm.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 #include <config.h>
37 #include <krb5/roken.h>
38 
39 #include <dh.h>
40 
41 #ifdef USE_HCRYPTO_TFM
42 
43 #include "tfm.h"
44 
45 static void
BN2mpz(fp_int * s,const BIGNUM * bn)46 BN2mpz(fp_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     fp_read_unsigned_bin(s, p, len);
55     free(p);
56 }
57 
58 
59 static BIGNUM *
mpz2BN(fp_int * s)60 mpz2BN(fp_int *s)
61 {
62     size_t size;
63     BIGNUM *bn;
64     void *p;
65 
66     size = fp_unsigned_bin_size(s);
67     p = malloc(size);
68     if (p == NULL && size != 0)
69 	return NULL;
70     fp_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
tfm_dh_generate_key(DH * dh)84 tfm_dh_generate_key(DH *dh)
85 {
86     fp_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 
113 	fp_init_multi(&pub, &priv_key, &g, &p, NULL);
114 
115 	BN2mpz(&priv_key, dh->priv_key);
116 	BN2mpz(&g, dh->g);
117 	BN2mpz(&p, dh->p);
118 
119 	res = fp_exptmod(&g, &priv_key, &p, &pub);
120 
121 	fp_zero(&priv_key);
122 	fp_zero(&g);
123 	fp_zero(&p);
124 	if (res != 0)
125 	    continue;
126 
127 	dh->pub_key = mpz2BN(&pub);
128 	fp_zero(&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
tfm_dh_compute_key(unsigned char * shared,const BIGNUM * pub,DH * dh)154 tfm_dh_compute_key(unsigned char *shared, const BIGNUM * pub, DH *dh)
155 {
156     fp_int s, priv_key, p, peer_pub;
157     size_t size = 0;
158     int ret;
159 
160     if (dh->pub_key == NULL || dh->g == NULL || dh->priv_key == NULL)
161 	return -1;
162 
163     fp_init(&p);
164     BN2mpz(&p, dh->p);
165 
166     fp_init(&peer_pub);
167     BN2mpz(&peer_pub, pub);
168 
169     /* check if peers pubkey is reasonable */
170     if (fp_isneg(&peer_pub)
171 	|| fp_cmp(&peer_pub, &p) >= 0
172 	|| fp_cmp_d(&peer_pub, 1) <= 0)
173     {
174 	fp_zero(&p);
175 	fp_zero(&peer_pub);
176 	return -1;
177     }
178 
179     fp_init(&priv_key);
180     BN2mpz(&priv_key, dh->priv_key);
181 
182     fp_init(&s);
183 
184     ret = fp_exptmod(&peer_pub, &priv_key, &p, &s);
185 
186     fp_zero(&p);
187     fp_zero(&peer_pub);
188     fp_zero(&priv_key);
189 
190     if (ret != 0)
191 	return -1;
192 
193     size = fp_unsigned_bin_size(&s);
194     fp_to_unsigned_bin(&s, shared);
195     fp_zero(&s);
196 
197     return size;
198 }
199 
200 static int
tfm_dh_generate_params(DH * dh,int a,int b,BN_GENCB * callback)201 tfm_dh_generate_params(DH *dh, int a, int b, BN_GENCB *callback)
202 {
203     /* groups should already be known, we don't care about this */
204     return 0;
205 }
206 
207 static int
tfm_dh_init(DH * dh)208 tfm_dh_init(DH *dh)
209 {
210     return 1;
211 }
212 
213 static int
tfm_dh_finish(DH * dh)214 tfm_dh_finish(DH *dh)
215 {
216     return 1;
217 }
218 
219 
220 /*
221  *
222  */
223 
224 const DH_METHOD _hc_dh_tfm_method = {
225     "hcrypto tfm DH",
226     tfm_dh_generate_key,
227     tfm_dh_compute_key,
228     NULL,
229     tfm_dh_init,
230     tfm_dh_finish,
231     0,
232     NULL,
233     tfm_dh_generate_params
234 };
235 
236 /**
237  * DH implementation using tfm.
238  *
239  * @return the DH_METHOD for the DH implementation using tfm.
240  *
241  * @ingroup hcrypto_dh
242  */
243 
244 const DH_METHOD *
DH_tfm_method(void)245 DH_tfm_method(void)
246 {
247     return &_hc_dh_tfm_method;
248 }
249 
250 #endif
251