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 * Hochschule fuer Technik Rapperswil
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>.
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
22 #include "gmp_diffie_hellman.h"
26 #ifdef HAVE_MPZ_POWM_SEC
28 # define mpz_powm mpz_powm_sec
31 typedef struct private_gmp_diffie_hellman_t private_gmp_diffie_hellman_t
;
34 * Private data of an gmp_diffie_hellman_t object.
36 struct private_gmp_diffie_hellman_t
{
38 * Public gmp_diffie_hellman_t interface.
40 gmp_diffie_hellman_t
public;
43 * Diffie Hellman group number.
83 * True if shared secret is computed and stored in my_public_value.
89 * Implementation of gmp_diffie_hellman_t.set_other_public_value.
91 static void set_other_public_value(private_gmp_diffie_hellman_t
*this, chunk_t value
)
96 mpz_sub_ui(p_min_1
, this->p
, 1);
98 mpz_import(this->yb
, value
.len
, 1, 1, 1, 0, value
.ptr
);
100 /* check public value:
101 * 1. 0 or 1 is invalid as 0^a = 0 and 1^a = 1
102 * 2. a public value larger or equal the modulus is invalid */
103 if (mpz_cmp_ui(this->yb
, 1) > 0 &&
104 mpz_cmp(this->yb
, p_min_1
) < 0)
106 #ifdef EXTENDED_DH_TEST
107 /* 3. test if y ^ q mod p = 1, where q = (p - 1)/2. */
112 mpz_fdiv_q_2exp(q
, p_min_1
, 1);
113 mpz_powm(one
, this->yb
, q
, this->p
);
115 if (mpz_cmp_ui(one
, 1) == 0)
117 mpz_powm(this->zz
, this->yb
, this->xa
, this->p
);
118 this->computed
= TRUE
;
122 DBG1(DBG_LIB
, "public DH value verification failed:"
123 " y ^ q mod p != 1");
127 mpz_powm(this->zz
, this->yb
, this->xa
, this->p
);
128 this->computed
= TRUE
;
133 DBG1(DBG_LIB
, "public DH value verification failed:"
134 " y < 2 || y > p - 1 ");
140 * Implementation of gmp_diffie_hellman_t.get_my_public_value.
142 static void get_my_public_value(private_gmp_diffie_hellman_t
*this,chunk_t
*value
)
144 value
->len
= this->p_len
;
145 value
->ptr
= mpz_export(NULL
, NULL
, 1, value
->len
, 1, 0, this->ya
);
146 if (value
->ptr
== NULL
)
153 * Implementation of gmp_diffie_hellman_t.get_shared_secret.
155 static status_t
get_shared_secret(private_gmp_diffie_hellman_t
*this, chunk_t
*secret
)
161 secret
->len
= this->p_len
;
162 secret
->ptr
= mpz_export(NULL
, NULL
, 1, secret
->len
, 1, 0, this->zz
);
163 if (secret
->ptr
== NULL
)
171 * Implementation of gmp_diffie_hellman_t.get_dh_group.
173 static diffie_hellman_group_t
get_dh_group(private_gmp_diffie_hellman_t
*this)
179 * Implementation of gmp_diffie_hellman_t.destroy.
181 static void destroy(private_gmp_diffie_hellman_t
*this)
193 * Described in header.
195 gmp_diffie_hellman_t
*gmp_diffie_hellman_create(diffie_hellman_group_t group
)
197 private_gmp_diffie_hellman_t
*this;
198 diffie_hellman_params_t
*params
;
202 params
= diffie_hellman_get_params(group
);
208 this = malloc_thing(private_gmp_diffie_hellman_t
);
210 /* public functions */
211 this->public.dh
.get_shared_secret
= (status_t (*)(diffie_hellman_t
*, chunk_t
*)) get_shared_secret
;
212 this->public.dh
.set_other_public_value
= (void (*)(diffie_hellman_t
*, chunk_t
)) set_other_public_value
;
213 this->public.dh
.get_my_public_value
= (void (*)(diffie_hellman_t
*, chunk_t
*)) get_my_public_value
;
214 this->public.dh
.get_dh_group
= (diffie_hellman_group_t (*)(diffie_hellman_t
*)) get_dh_group
;
215 this->public.dh
.destroy
= (void (*)(diffie_hellman_t
*)) destroy
;
217 /* private variables */
226 this->computed
= FALSE
;
227 this->p_len
= params
->prime
.len
;
228 mpz_import(this->p
, params
->prime
.len
, 1, 1, 1, 0, params
->prime
.ptr
);
229 mpz_import(this->g
, params
->generator
.len
, 1, 1, 1, 0, params
->generator
.ptr
);
231 rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_STRONG
);
234 DBG1(DBG_LIB
, "no RNG found for quality %N", rng_quality_names
,
240 rng
->allocate_bytes(rng
, params
->exp_len
, &random
);
243 if (params
->exp_len
== this->p_len
)
245 /* achieve bitsof(p)-1 by setting MSB to 0 */
248 mpz_import(this->xa
, random
.len
, 1, 1, 1, 0, random
.ptr
);
250 DBG2(DBG_LIB
, "size of DH secret exponent: %u bits",
251 mpz_sizeinbase(this->xa
, 2));
253 mpz_powm(this->ya
, this->g
, this->xa
, this->p
);
255 return &this->public;