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