2 * Copyright (C) 2000-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
8 * The GnuTLS is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 3 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 #include <gnutls_int.h>
24 #include <gnutls_errors.h>
25 #include <gnutls_dh.h>
33 your_key = Y ^ x mod p;
34 his_key = X ^ y mod p;
36 // generate our secret and the public value (X) for it
37 X = gnutls_calc_dh_secret(&x, g, p);
38 // now we can calculate the shared secret
39 key = gnutls_calc_dh_key(Y, x, g, p);
40 _gnutls_mpi_release(x);
41 _gnutls_mpi_release(g);
44 #define MAX_BITS 18000
46 /* returns the public value (X), and the secret (ret_x).
49 gnutls_calc_dh_secret (bigint_t
* ret_y
, bigint_t
* ret_x
, bigint_t g
, bigint_t prime
,
52 bigint_t e
=NULL
, x
= NULL
;
58 x_size
= _gnutls_mpi_get_nbits (prime
);
59 if (x_size
> 0) x_size
--;
64 if (x_size
> MAX_BITS
|| x_size
== 0)
67 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER
;
70 x
= _gnutls_mpi_new(x_size
);
74 ret
= GNUTLS_E_MEMORY_ERROR
;
78 e
= _gnutls_mpi_alloc_like (prime
);
82 ret
= GNUTLS_E_MEMORY_ERROR
;
88 if (_gnutls_mpi_randomize (x
, x_size
, GNUTLS_RND_RANDOM
) == NULL
)
91 ret
= GNUTLS_E_INTERNAL_ERROR
;
95 _gnutls_mpi_powm (e
, g
, x
, prime
);
97 while(_gnutls_mpi_cmp_ui(e
, 1) == 0);
105 if (x
) _gnutls_mpi_release (&x
);
106 if (e
) _gnutls_mpi_release (&e
);
111 /* returns f^x mod prime
114 gnutls_calc_dh_key (bigint_t
*key
, bigint_t f
, bigint_t x
, bigint_t prime
)
120 ff
= _gnutls_mpi_mod(f
, prime
);
121 _gnutls_mpi_add_ui(ff
, ff
, 1);
123 /* check if f==0,1,p-1.
124 * or (ff=f+1) equivalently ff==1,2,p */
125 if ((_gnutls_mpi_cmp_ui(ff
, 2) == 0) || (_gnutls_mpi_cmp_ui(ff
, 1) == 0) ||
126 (_gnutls_mpi_cmp(ff
,prime
) == 0))
129 ret
= GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER
;
133 bits
= _gnutls_mpi_get_nbits (prime
);
134 if (bits
== 0 || bits
> MAX_BITS
)
137 ret
= GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER
;
141 k
= _gnutls_mpi_alloc_like (prime
);
145 ret
= GNUTLS_E_MEMORY_ERROR
;
149 _gnutls_mpi_powm (k
, f
, x
, prime
);
155 _gnutls_mpi_release (&ff
);
161 * _gnutls_get_dh_params - Returns the DH parameters pointer
162 * @dh_params: is an DH parameters structure, or NULL.
163 * @func: is a callback function to receive the parameters or NULL.
164 * @session: a gnutls session.
166 * This function will return the dh parameters pointer.
169 _gnutls_get_dh_params (gnutls_dh_params_t dh_params
,
170 gnutls_params_function
* func
,
171 gnutls_session_t session
)
173 gnutls_params_st params
;
176 /* if cached return the cached */
177 if (session
->internals
.params
.dh_params
)
178 return session
->internals
.params
.dh_params
;
182 session
->internals
.params
.dh_params
= dh_params
;
186 ret
= func (session
, GNUTLS_PARAMS_DH
, ¶ms
);
187 if (ret
== 0 && params
.type
== GNUTLS_PARAMS_DH
)
189 session
->internals
.params
.dh_params
= params
.params
.dh
;
190 session
->internals
.params
.free_dh_params
= params
.deinit
;
194 return session
->internals
.params
.dh_params
;