2 * Copyright (C) 2008 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 #include <openssl/dh.h>
20 #include "openssl_diffie_hellman.h"
24 typedef struct modulus_entry_t modulus_entry_t
;
27 * Entry of the modulus list.
29 struct modulus_entry_t
{
31 * Group number as it is defined in file transform_substructure.h.
33 diffie_hellman_group_t group
;
36 * Pointer to the function to get the modulus.
38 BIGNUM
*(*get_prime
)(BIGNUM
*bn
);
47 * All supported modulus values.
49 static modulus_entry_t modulus_entries
[] = {
50 {MODP_768_BIT
, get_rfc2409_prime_768
, 2},
51 {MODP_1024_BIT
, get_rfc2409_prime_1024
, 2},
52 {MODP_1536_BIT
, get_rfc3526_prime_1536
, 2},
53 {MODP_2048_BIT
, get_rfc3526_prime_2048
, 2},
54 {MODP_3072_BIT
, get_rfc3526_prime_3072
, 2},
55 {MODP_4096_BIT
, get_rfc3526_prime_4096
, 2},
56 {MODP_6144_BIT
, get_rfc3526_prime_6144
, 2},
57 {MODP_8192_BIT
, get_rfc3526_prime_8192
, 2},
60 typedef struct private_openssl_diffie_hellman_t private_openssl_diffie_hellman_t
;
63 * Private data of an openssl_diffie_hellman_t object.
65 struct private_openssl_diffie_hellman_t
{
67 * Public openssl_diffie_hellman_t interface.
69 openssl_diffie_hellman_t
public;
72 * Diffie Hellman group number.
77 * Diffie Hellman object
89 chunk_t shared_secret
;
92 * True if shared secret is computed
98 * Convert a BIGNUM to a chunk
100 static void bn2chunk(BIGNUM
*bn
, chunk_t
*chunk
)
102 chunk
->len
= BN_num_bytes(bn
);
103 chunk
->ptr
= malloc(chunk
->len
);
104 BN_bn2bin(bn
, chunk
->ptr
);
108 * Implementation of openssl_diffie_hellman_t.set_other_public_value.
110 static void set_other_public_value(private_openssl_diffie_hellman_t
*this, chunk_t value
)
113 BN_bin2bn(value
.ptr
, value
.len
, this->pub_key
);
115 len
= DH_size(this->dh
);
116 chunk_free(&this->shared_secret
);
117 this->shared_secret
= chunk_alloc(len
);
119 if (DH_compute_key(this->shared_secret
.ptr
, this->pub_key
, this->dh
) < 0) {
120 DBG1("DH shared secret computation failed");
124 this->computed
= TRUE
;
128 * Implementation of openssl_diffie_hellman_t.get_other_public_value.
130 static status_t
get_other_public_value(private_openssl_diffie_hellman_t
*this,
137 bn2chunk(this->pub_key
, value
);
142 * Implementation of openssl_diffie_hellman_t.get_my_public_value.
144 static void get_my_public_value(private_openssl_diffie_hellman_t
*this,chunk_t
*value
)
146 bn2chunk(this->dh
->pub_key
, value
);
150 * Implementation of openssl_diffie_hellman_t.get_shared_secret.
152 static status_t
get_shared_secret(private_openssl_diffie_hellman_t
*this, chunk_t
*secret
)
158 *secret
= chunk_clone(this->shared_secret
);
163 * Implementation of openssl_diffie_hellman_t.get_dh_group.
165 static diffie_hellman_group_t
get_dh_group(private_openssl_diffie_hellman_t
*this)
171 * Lookup the modulus in modulo table
173 static status_t
set_modulus(private_openssl_diffie_hellman_t
*this)
176 for (i
= 0; i
< (sizeof(modulus_entries
) / sizeof(modulus_entry_t
)); i
++)
178 if (modulus_entries
[i
].group
== this->group
)
180 this->dh
->p
= modulus_entries
[i
].get_prime(NULL
);
181 this->dh
->g
= BN_new();
182 BN_set_word(this->dh
->g
, modulus_entries
[i
].generator
);
190 * Implementation of openssl_diffie_hellman_t.destroy.
192 static void destroy(private_openssl_diffie_hellman_t
*this)
194 BN_clear_free(this->pub_key
);
196 chunk_free(&this->shared_secret
);
201 * Described in header.
203 openssl_diffie_hellman_t
*openssl_diffie_hellman_create(diffie_hellman_group_t group
)
205 private_openssl_diffie_hellman_t
*this = malloc_thing(private_openssl_diffie_hellman_t
);
207 this->public.dh
.get_shared_secret
= (status_t (*)(diffie_hellman_t
*, chunk_t
*)) get_shared_secret
;
208 this->public.dh
.set_other_public_value
= (void (*)(diffie_hellman_t
*, chunk_t
)) set_other_public_value
;
209 this->public.dh
.get_other_public_value
= (status_t (*)(diffie_hellman_t
*, chunk_t
*)) get_other_public_value
;
210 this->public.dh
.get_my_public_value
= (void (*)(diffie_hellman_t
*, chunk_t
*)) get_my_public_value
;
211 this->public.dh
.get_dh_group
= (diffie_hellman_group_t (*)(diffie_hellman_t
*)) get_dh_group
;
212 this->public.dh
.destroy
= (void (*)(diffie_hellman_t
*)) destroy
;
220 this->dh
->length
= DH_EXPONENT_ENTROPY_SIZE
;
223 this->computed
= FALSE
;
225 this->pub_key
= BN_new();
226 this->shared_secret
= chunk_empty
;
228 /* find a modulus according to group */
229 if (set_modulus(this) != SUCCESS
)
235 /* generate my public and private values */
236 if (!DH_generate_key(this->dh
))
242 return &this->public;