certtool is able to set certificate policies via a template
[gnutls.git] / lib / gnutls_dh.c
blob40dcd51de6fd6b316c1b670a8944b213d4e3eee1
1 /*
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>
28 /*
29 --Example--
30 you: X = g ^ x mod p;
31 peer:Y = g ^ y mod p;
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).
48 int
49 gnutls_calc_dh_secret (bigint_t* ret_y, bigint_t * ret_x, bigint_t g, bigint_t prime,
50 unsigned int q_bits)
52 bigint_t e=NULL, x = NULL;
53 unsigned int x_size;
54 int ret;
56 if (q_bits == 0)
58 x_size = _gnutls_mpi_get_nbits (prime);
59 if (x_size > 0) x_size--;
61 else
62 x_size = q_bits;
64 if (x_size > MAX_BITS || x_size == 0)
66 gnutls_assert ();
67 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
70 x = _gnutls_mpi_new(x_size);
71 if (x == NULL)
73 gnutls_assert ();
74 ret = GNUTLS_E_MEMORY_ERROR;
75 goto fail;
78 e = _gnutls_mpi_alloc_like (prime);
79 if (e == NULL)
81 gnutls_assert ();
82 ret = GNUTLS_E_MEMORY_ERROR;
83 goto fail;
88 if (_gnutls_mpi_randomize (x, x_size, GNUTLS_RND_RANDOM) == NULL)
90 gnutls_assert();
91 ret = GNUTLS_E_INTERNAL_ERROR;
92 goto fail;
95 _gnutls_mpi_powm (e, g, x, prime);
97 while(_gnutls_mpi_cmp_ui(e, 1) == 0);
99 *ret_x = x;
100 *ret_y = e;
102 return 0;
104 fail:
105 if (x) _gnutls_mpi_release (&x);
106 if (e) _gnutls_mpi_release (&e);
107 return ret;
111 /* returns f^x mod prime
114 gnutls_calc_dh_key (bigint_t *key, bigint_t f, bigint_t x, bigint_t prime)
116 bigint_t k, ff;
117 unsigned int bits;
118 int ret;
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))
128 gnutls_assert();
129 ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
130 goto cleanup;
133 bits = _gnutls_mpi_get_nbits (prime);
134 if (bits == 0 || bits > MAX_BITS)
136 gnutls_assert ();
137 ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
138 goto cleanup;
141 k = _gnutls_mpi_alloc_like (prime);
142 if (k == NULL)
144 gnutls_assert();
145 ret = GNUTLS_E_MEMORY_ERROR;
146 goto cleanup;
149 _gnutls_mpi_powm (k, f, x, prime);
151 *key = k;
153 ret = 0;
154 cleanup:
155 _gnutls_mpi_release (&ff);
157 return ret;
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.
168 gnutls_dh_params_t
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;
174 int ret;
176 /* if cached return the cached */
177 if (session->internals.params.dh_params)
178 return session->internals.params.dh_params;
180 if (dh_params)
182 session->internals.params.dh_params = dh_params;
184 else if (func)
186 ret = func (session, GNUTLS_PARAMS_DH, &params);
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;