Annotation of embedaddon/strongswan/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2008-2010 Tobias Brunner
3: * Copyright (C) 2008 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 <openssl/opensslconf.h>
18:
19: #ifndef OPENSSL_NO_DH
20:
21: #include <openssl/bn.h>
22: #include <openssl/dh.h>
23:
24: #include "openssl_diffie_hellman.h"
25: #include "openssl_util.h"
26:
27: #include <utils/debug.h>
28:
29: /* these were added with 1.1.0 when DH was made opaque */
30: #if OPENSSL_VERSION_NUMBER < 0x10100000L
31: OPENSSL_KEY_FALLBACK(DH, key, pub_key, priv_key)
32: OPENSSL_KEY_FALLBACK(DH, pqg, p, q, g)
33: #define DH_set_length(dh, len) ({ (dh)->length = len; 1; })
34: #endif
35:
36: typedef struct private_openssl_diffie_hellman_t private_openssl_diffie_hellman_t;
37:
38: /**
39: * Private data of an openssl_diffie_hellman_t object.
40: */
41: struct private_openssl_diffie_hellman_t {
42: /**
43: * Public openssl_diffie_hellman_t interface.
44: */
45: openssl_diffie_hellman_t public;
46:
47: /**
48: * Diffie Hellman group number.
49: */
50: diffie_hellman_group_t group;
51:
52: /**
53: * Diffie Hellman object
54: */
55: DH *dh;
56:
57: /**
58: * Other public value
59: */
60: BIGNUM *pub_key;
61:
62: /**
63: * Shared secret
64: */
65: chunk_t shared_secret;
66:
67: /**
68: * True if shared secret is computed
69: */
70: bool computed;
71: };
72:
73: METHOD(diffie_hellman_t, get_my_public_value, bool,
74: private_openssl_diffie_hellman_t *this, chunk_t *value)
75: {
76: const BIGNUM *pubkey;
77:
78: *value = chunk_alloc(DH_size(this->dh));
79: memset(value->ptr, 0, value->len);
80: DH_get0_key(this->dh, &pubkey, NULL);
81: BN_bn2bin(pubkey, value->ptr + value->len - BN_num_bytes(pubkey));
82: return TRUE;
83: }
84:
85: METHOD(diffie_hellman_t, get_shared_secret, bool,
86: private_openssl_diffie_hellman_t *this, chunk_t *secret)
87: {
88: if (!this->computed)
89: {
90: return FALSE;
91: }
92: /* shared secret should requires a len according the DH group */
93: *secret = chunk_alloc(DH_size(this->dh));
94: memset(secret->ptr, 0, secret->len);
95: memcpy(secret->ptr + secret->len - this->shared_secret.len,
96: this->shared_secret.ptr, this->shared_secret.len);
97: return TRUE;
98: }
99:
100:
101: METHOD(diffie_hellman_t, set_other_public_value, bool,
102: private_openssl_diffie_hellman_t *this, chunk_t value)
103: {
104: int len;
105:
106: if (!diffie_hellman_verify_value(this->group, value))
107: {
108: return FALSE;
109: }
110:
111: BN_bin2bn(value.ptr, value.len, this->pub_key);
112: chunk_clear(&this->shared_secret);
113: this->shared_secret.ptr = malloc(DH_size(this->dh));
114: memset(this->shared_secret.ptr, 0xFF, this->shared_secret.len);
115: len = DH_compute_key(this->shared_secret.ptr, this->pub_key, this->dh);
116: if (len < 0)
117: {
118: DBG1(DBG_LIB, "DH shared secret computation failed");
119: return FALSE;
120: }
121: this->shared_secret.len = len;
122: this->computed = TRUE;
123: return TRUE;
124: }
125:
126: METHOD(diffie_hellman_t, set_private_value, bool,
127: private_openssl_diffie_hellman_t *this, chunk_t value)
128: {
129: BIGNUM *privkey;
130:
131: privkey = BN_bin2bn(value.ptr, value.len, NULL);
132: if (privkey)
133: {
134: if (!DH_set0_key(this->dh, NULL, privkey))
135: {
136: return FALSE;
137: }
138: chunk_clear(&this->shared_secret);
139: this->computed = FALSE;
140: return DH_generate_key(this->dh);
141: }
142: return FALSE;
143: }
144:
145: METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t,
146: private_openssl_diffie_hellman_t *this)
147: {
148: return this->group;
149: }
150:
151: /**
152: * Lookup the modulus in modulo table
153: */
154: static status_t set_modulus(private_openssl_diffie_hellman_t *this)
155: {
156: BIGNUM *p, *g;
157:
158: diffie_hellman_params_t *params = diffie_hellman_get_params(this->group);
159: if (!params)
160: {
161: return NOT_FOUND;
162: }
163: p = BN_bin2bn(params->prime.ptr, params->prime.len, NULL);
164: g = BN_bin2bn(params->generator.ptr, params->generator.len, NULL);
165: if (!DH_set0_pqg(this->dh, p, NULL, g))
166: {
167: return FAILED;
168: }
169: if (params->exp_len != params->prime.len)
170: {
171: #ifdef OPENSSL_IS_BORINGSSL
172: this->dh->priv_length = params->exp_len * 8;
173: #else
174: if (!DH_set_length(this->dh, params->exp_len * 8))
175: {
176: return FAILED;
177: }
178: #endif
179: }
180: return SUCCESS;
181: }
182:
183: METHOD(diffie_hellman_t, destroy, void,
184: private_openssl_diffie_hellman_t *this)
185: {
186: BN_clear_free(this->pub_key);
187: DH_free(this->dh);
188: chunk_clear(&this->shared_secret);
189: free(this);
190: }
191:
192: /*
193: * Described in header.
194: */
195: openssl_diffie_hellman_t *openssl_diffie_hellman_create(
196: diffie_hellman_group_t group, ...)
197: {
198: private_openssl_diffie_hellman_t *this;
199: const BIGNUM *privkey;
200:
201: INIT(this,
202: .public = {
203: .dh = {
204: .get_shared_secret = _get_shared_secret,
205: .set_other_public_value = _set_other_public_value,
206: .get_my_public_value = _get_my_public_value,
207: .set_private_value = _set_private_value,
208: .get_dh_group = _get_dh_group,
209: .destroy = _destroy,
210: },
211: },
212: );
213:
214: this->dh = DH_new();
215: if (!this->dh)
216: {
217: free(this);
218: return NULL;
219: }
220:
221: this->group = group;
222: this->computed = FALSE;
223: this->pub_key = BN_new();
224: this->shared_secret = chunk_empty;
225:
226: if (group == MODP_CUSTOM)
227: {
228: chunk_t g, p;
229:
230: VA_ARGS_GET(group, g, p);
231: if (!DH_set0_pqg(this->dh, BN_bin2bn(p.ptr, p.len, NULL), NULL,
232: BN_bin2bn(g.ptr, g.len, NULL)))
233: {
234: destroy(this);
235: return NULL;
236: }
237: }
238: else
239: {
240: /* find a modulus according to group */
241: if (set_modulus(this) != SUCCESS)
242: {
243: destroy(this);
244: return NULL;
245: }
246: }
247:
248: /* generate my public and private values */
249: if (!DH_generate_key(this->dh))
250: {
251: destroy(this);
252: return NULL;
253: }
254: DH_get0_key(this->dh, NULL, &privkey);
255: DBG2(DBG_LIB, "size of DH secret exponent: %d bits", BN_num_bits(privkey));
256: return &this->public;
257: }
258:
259: #endif /* OPENSSL_NO_DH */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>