Annotation of embedaddon/strongswan/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 1998-2002 D. Hugh Redelmeier.
3: * Copyright (C) 1999, 2000, 2001 Henry Spencer.
4: * Copyright (C) 2010 Tobias Brunner
5: * Copyright (C) 2005-2008 Martin Willi
6: * Copyright (C) 2005 Jan Hutter
7: * HSR Hochschule fuer Technik Rapperswil
8: *
9: * This program is free software; you can redistribute it and/or modify it
10: * under the terms of the GNU General Public License as published by the
11: * Free Software Foundation; either version 2 of the License, or (at your
12: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
13: *
14: * This program is distributed in the hope that it will be useful, but
15: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17: * for more details.
18: */
19:
20: #include <gmp.h>
21:
22: #include "gmp_diffie_hellman.h"
23:
24: #include <utils/debug.h>
25:
26: #ifdef HAVE_MPZ_POWM_SEC
27: # undef mpz_powm
28: # define mpz_powm mpz_powm_sec
29: #endif
30:
31: typedef struct private_gmp_diffie_hellman_t private_gmp_diffie_hellman_t;
32:
33: /**
34: * Private data of an gmp_diffie_hellman_t object.
35: */
36: struct private_gmp_diffie_hellman_t {
37: /**
38: * Public gmp_diffie_hellman_t interface.
39: */
40: gmp_diffie_hellman_t public;
41:
42: /**
43: * Diffie Hellman group number.
44: */
45: diffie_hellman_group_t group;
46:
47: /*
48: * Generator value.
49: */
50: mpz_t g;
51:
52: /**
53: * My private value.
54: */
55: mpz_t xa;
56:
57: /**
58: * My public value.
59: */
60: mpz_t ya;
61:
62: /**
63: * Other public value.
64: */
65: mpz_t yb;
66:
67: /**
68: * Shared secret.
69: */
70: mpz_t zz;
71:
72: /**
73: * Modulus.
74: */
75: mpz_t p;
76:
77: /**
78: * Modulus length.
79: */
80: size_t p_len;
81:
82: /**
83: * True if shared secret is computed and stored in my_public_value.
84: */
85: bool computed;
86: };
87:
88: METHOD(diffie_hellman_t, set_other_public_value, bool,
89: private_gmp_diffie_hellman_t *this, chunk_t value)
90: {
91: mpz_t p_min_1;
92:
93: if (!diffie_hellman_verify_value(this->group, value))
94: {
95: return FALSE;
96: }
97:
98: mpz_init(p_min_1);
99: mpz_sub_ui(p_min_1, this->p, 1);
100:
101: mpz_import(this->yb, value.len, 1, 1, 1, 0, value.ptr);
102:
103: /* check public value:
104: * 1. 0 or 1 is invalid as 0^a = 0 and 1^a = 1
105: * 2. a public value larger or equal the modulus is invalid */
106: if (mpz_cmp_ui(this->yb, 1) > 0 &&
107: mpz_cmp(this->yb, p_min_1) < 0)
108: {
109: #ifdef EXTENDED_DH_TEST
110: /* 3. test if y ^ q mod p = 1, where q = (p - 1)/2. */
111: mpz_t q, one;
112: diffie_hellman_params_t *params;
113:
114: mpz_init(q);
115: mpz_init(one);
116:
117: params = diffie_hellman_get_params(this->group);
118: if (!params->subgroup.len)
119: {
120: mpz_fdiv_q_2exp(q, p_min_1, 1);
121: }
122: else
123: {
124: mpz_import(q, params->subgroup.len, 1, 1, 1, 0, params->subgroup.ptr);
125: }
126: mpz_powm(one, this->yb, q, this->p);
127: mpz_clear(q);
128: if (mpz_cmp_ui(one, 1) == 0)
129: {
130: mpz_powm(this->zz, this->yb, this->xa, this->p);
131: this->computed = TRUE;
132: }
133: else
134: {
135: DBG1(DBG_LIB, "public DH value verification failed:"
136: " y ^ q mod p != 1");
137: }
138: mpz_clear(one);
139: #else
140: mpz_powm(this->zz, this->yb, this->xa, this->p);
141: this->computed = TRUE;
142: #endif
143: }
144: else
145: {
146: DBG1(DBG_LIB, "public DH value verification failed:"
147: " y < 2 || y > p - 1 ");
148: }
149: mpz_clear(p_min_1);
150: return this->computed;
151: }
152:
153: METHOD(diffie_hellman_t, get_my_public_value, bool,
154: private_gmp_diffie_hellman_t *this,chunk_t *value)
155: {
156: value->len = this->p_len;
157: value->ptr = mpz_export(NULL, NULL, 1, value->len, 1, 0, this->ya);
158: if (value->ptr == NULL)
159: {
160: value->len = 0;
161: }
162: return TRUE;
163: }
164:
165: METHOD(diffie_hellman_t, set_private_value, bool,
166: private_gmp_diffie_hellman_t *this, chunk_t value)
167: {
168: mpz_import(this->xa, value.len, 1, 1, 1, 0, value.ptr);
169: mpz_powm(this->ya, this->g, this->xa, this->p);
170: this->computed = FALSE;
171: return TRUE;
172: }
173:
174: METHOD(diffie_hellman_t, get_shared_secret, bool,
175: private_gmp_diffie_hellman_t *this, chunk_t *secret)
176: {
177: if (!this->computed)
178: {
179: return FALSE;
180: }
181: secret->len = this->p_len;
182: secret->ptr = mpz_export(NULL, NULL, 1, secret->len, 1, 0, this->zz);
183: if (secret->ptr == NULL)
184: {
185: return FALSE;
186: }
187: return TRUE;
188: }
189:
190: METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t,
191: private_gmp_diffie_hellman_t *this)
192: {
193: return this->group;
194: }
195:
196: METHOD(diffie_hellman_t, destroy, void,
197: private_gmp_diffie_hellman_t *this)
198: {
199: mpz_clear(this->p);
200: mpz_clear(this->xa);
201: mpz_clear(this->ya);
202: mpz_clear(this->yb);
203: mpz_clear(this->zz);
204: mpz_clear(this->g);
205: free(this);
206: }
207:
208: /**
209: * Generic internal constructor
210: */
211: static gmp_diffie_hellman_t *create_generic(diffie_hellman_group_t group,
212: size_t exp_len, chunk_t g, chunk_t p)
213: {
214: private_gmp_diffie_hellman_t *this;
215: chunk_t random;
216: rng_t *rng;
217:
218: INIT(this,
219: .public = {
220: .dh = {
221: .get_shared_secret = _get_shared_secret,
222: .set_other_public_value = _set_other_public_value,
223: .get_my_public_value = _get_my_public_value,
224: .set_private_value = _set_private_value,
225: .get_dh_group = _get_dh_group,
226: .destroy = _destroy,
227: },
228: },
229: .group = group,
230: .p_len = p.len,
231: );
232:
233: mpz_init(this->p);
234: mpz_init(this->yb);
235: mpz_init(this->ya);
236: mpz_init(this->xa);
237: mpz_init(this->zz);
238: mpz_init(this->g);
239: mpz_import(this->g, g.len, 1, 1, 1, 0, g.ptr);
240: mpz_import(this->p, p.len, 1, 1, 1, 0, p.ptr);
241:
242: rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
243: if (!rng)
244: {
245: DBG1(DBG_LIB, "no RNG found for quality %N", rng_quality_names,
246: RNG_STRONG);
247: destroy(this);
248: return NULL;
249: }
250: if (!rng->allocate_bytes(rng, exp_len, &random))
251: {
252: DBG1(DBG_LIB, "failed to allocate DH secret");
253: rng->destroy(rng);
254: destroy(this);
255: return NULL;
256: }
257: rng->destroy(rng);
258:
259: if (exp_len == this->p_len)
260: {
261: /* achieve bitsof(p)-1 by setting MSB to 0 */
262: *random.ptr &= 0x7F;
263: }
264: mpz_import(this->xa, random.len, 1, 1, 1, 0, random.ptr);
265: chunk_clear(&random);
266: DBG2(DBG_LIB, "size of DH secret exponent: %u bits",
267: mpz_sizeinbase(this->xa, 2));
268:
269: mpz_powm(this->ya, this->g, this->xa, this->p);
270:
271: return &this->public;
272: }
273:
274: /*
275: * Described in header
276: */
277: gmp_diffie_hellman_t *gmp_diffie_hellman_create(diffie_hellman_group_t group)
278: {
279: diffie_hellman_params_t *params;
280:
281: params = diffie_hellman_get_params(group);
282: if (!params)
283: {
284: return NULL;
285: }
286: return create_generic(group, params->exp_len,
287: params->generator, params->prime);
288: }
289:
290: /*
291: * Described in header
292: */
293: gmp_diffie_hellman_t *gmp_diffie_hellman_create_custom(
294: diffie_hellman_group_t group, ...)
295: {
296: if (group == MODP_CUSTOM)
297: {
298: chunk_t g, p;
299:
300: VA_ARGS_GET(group, g, p);
301: return create_generic(MODP_CUSTOM, p.len, g, p);
302: }
303: return NULL;
304: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>