2 * Copyright (C) 2008-2010 Tobias Brunner
3 * Copyright (C) 2008 Martin Willi
4 * Hochschule fuer Technik Rapperswil
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>.
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
17 #include <openssl/dh.h>
19 #include "openssl_diffie_hellman.h"
23 typedef struct private_openssl_diffie_hellman_t private_openssl_diffie_hellman_t
;
26 * Private data of an openssl_diffie_hellman_t object.
28 struct private_openssl_diffie_hellman_t
{
30 * Public openssl_diffie_hellman_t interface.
32 openssl_diffie_hellman_t
public;
35 * Diffie Hellman group number.
40 * Diffie Hellman object
52 chunk_t shared_secret
;
55 * True if shared secret is computed
60 METHOD(diffie_hellman_t
, get_my_public_value
, void,
61 private_openssl_diffie_hellman_t
*this, chunk_t
*value
)
63 *value
= chunk_alloc(DH_size(this->dh
));
64 memset(value
->ptr
, 0, value
->len
);
65 BN_bn2bin(this->dh
->pub_key
,
66 value
->ptr
+ value
->len
- BN_num_bytes(this->dh
->pub_key
));
69 METHOD(diffie_hellman_t
, get_shared_secret
, status_t
,
70 private_openssl_diffie_hellman_t
*this, chunk_t
*secret
)
76 /* shared secret should requires a len according the DH group */
77 *secret
= chunk_alloc(DH_size(this->dh
));
78 memset(secret
->ptr
, 0, secret
->len
);
79 memcpy(secret
->ptr
+ secret
->len
- this->shared_secret
.len
,
80 this->shared_secret
.ptr
, this->shared_secret
.len
);
85 METHOD(diffie_hellman_t
, set_other_public_value
, void,
86 private_openssl_diffie_hellman_t
*this, chunk_t value
)
90 BN_bin2bn(value
.ptr
, value
.len
, this->pub_key
);
91 chunk_clear(&this->shared_secret
);
92 this->shared_secret
.ptr
= malloc(DH_size(this->dh
));
93 memset(this->shared_secret
.ptr
, 0xFF, this->shared_secret
.len
);
94 len
= DH_compute_key(this->shared_secret
.ptr
, this->pub_key
, this->dh
);
97 DBG1(DBG_LIB
, "DH shared secret computation failed");
100 this->shared_secret
.len
= len
;
101 this->computed
= TRUE
;
104 METHOD(diffie_hellman_t
, get_dh_group
, diffie_hellman_group_t
,
105 private_openssl_diffie_hellman_t
*this)
111 * Lookup the modulus in modulo table
113 static status_t
set_modulus(private_openssl_diffie_hellman_t
*this)
115 diffie_hellman_params_t
*params
= diffie_hellman_get_params(this->group
);
120 this->dh
->p
= BN_bin2bn(params
->prime
.ptr
, params
->prime
.len
, NULL
);
121 this->dh
->g
= BN_bin2bn(params
->generator
.ptr
, params
->generator
.len
, NULL
);
122 if (params
->exp_len
!= params
->prime
.len
)
124 this->dh
->length
= params
->exp_len
* 8;
129 METHOD(diffie_hellman_t
, destroy
, void,
130 private_openssl_diffie_hellman_t
*this)
132 BN_clear_free(this->pub_key
);
134 chunk_clear(&this->shared_secret
);
139 * Described in header.
141 openssl_diffie_hellman_t
*openssl_diffie_hellman_create(
142 diffie_hellman_group_t group
, chunk_t g
, chunk_t p
)
144 private_openssl_diffie_hellman_t
*this;
149 .get_shared_secret
= _get_shared_secret
,
150 .set_other_public_value
= _set_other_public_value
,
151 .get_my_public_value
= _get_my_public_value
,
152 .get_dh_group
= _get_dh_group
,
166 this->computed
= FALSE
;
167 this->pub_key
= BN_new();
168 this->shared_secret
= chunk_empty
;
170 if (group
== MODP_CUSTOM
)
172 this->dh
->p
= BN_bin2bn(p
.ptr
, p
.len
, NULL
);
173 this->dh
->g
= BN_bin2bn(g
.ptr
, g
.len
, NULL
);
177 /* find a modulus according to group */
178 if (set_modulus(this) != SUCCESS
)
185 /* generate my public and private values */
186 if (!DH_generate_key(this->dh
))
191 DBG2(DBG_LIB
, "size of DH secret exponent: %d bits",
192 BN_num_bits(this->dh
->priv_key
));
194 return &this->public;