Tizen 2.0 Release
[external/libgnutls26.git] / lib / gnutls_dh.c
1 /*
2  * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2010 Free
3  * Software Foundation, Inc.
4  *
5  * Author: Nikos Mavrogiannopoulos
6  *
7  * This file is part of GnuTLS.
8  *
9  * The GnuTLS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1 of
12  * the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22  * USA
23  *
24  */
25
26 #include <gnutls_int.h>
27 #include <gnutls_errors.h>
28 #include <gnutls_dh.h>
29
30
31 /* 
32         --Example-- 
33         you: X = g ^ x mod p;
34         peer:Y = g ^ y mod p;
35
36         your_key = Y ^ x mod p;
37         his_key  = X ^ y mod p;
38
39 //      generate our secret and the public value (X) for it
40         X = gnutls_calc_dh_secret(&x, g, p);
41 //      now we can calculate the shared secret
42         key = gnutls_calc_dh_key(Y, x, g, p);
43         _gnutls_mpi_release(x);
44         _gnutls_mpi_release(g);
45 */
46
47 #define MAX_BITS 18000
48
49 /* returns the public value (X), and the secret (ret_x).
50  */
51 bigint_t
52 gnutls_calc_dh_secret (bigint_t * ret_x, bigint_t g, bigint_t prime)
53 {
54   bigint_t e, x = NULL;
55   int x_size = _gnutls_mpi_get_nbits (prime) - 1;
56   /* The size of the secret key is less than
57    * prime/2
58    */
59
60   if (x_size > MAX_BITS || x_size <= 0)
61     {
62       gnutls_assert ();
63       return NULL;
64     }
65
66   x = _gnutls_mpi_randomize (NULL, x_size, GNUTLS_RND_RANDOM);
67   if (x == NULL)
68     {
69       gnutls_assert ();
70       return NULL;
71     }
72
73   e = _gnutls_mpi_alloc_like (prime);
74   if (e == NULL)
75     {
76       gnutls_assert ();
77       if (ret_x)
78         *ret_x = NULL;
79
80       _gnutls_mpi_release (&x);
81       return NULL;
82     }
83
84   _gnutls_mpi_powm (e, g, x, prime);
85
86   if (ret_x)
87     *ret_x = x;
88   else
89     _gnutls_mpi_release (&x);
90   return e;
91 }
92
93
94 bigint_t
95 gnutls_calc_dh_key (bigint_t f, bigint_t x, bigint_t prime)
96 {
97   bigint_t k, ff, ret;
98   int bits;
99   
100   ff = _gnutls_mpi_mod(f, prime);
101   _gnutls_mpi_add_ui(ff, ff, 1);
102
103   /* check if f==0,1,p-1. 
104    * or (ff=f+1) equivalently ff==1,2,p */
105   if ((_gnutls_mpi_cmp_ui(ff, 2) == 0) || (_gnutls_mpi_cmp_ui(ff, 1) == 0) ||
106       (_gnutls_mpi_cmp(ff,prime) == 0))
107     {
108       gnutls_assert();
109       ret = NULL;
110       goto cleanup;
111     }
112
113   bits = _gnutls_mpi_get_nbits (prime);
114   if (bits <= 0 || bits > MAX_BITS)
115     {
116       gnutls_assert ();
117       ret = NULL;
118       goto cleanup;
119     }
120
121   k = _gnutls_mpi_alloc_like (prime);
122   if (k == NULL)
123     {
124       gnutls_assert();
125       ret = NULL;
126       goto cleanup;
127     }
128
129   _gnutls_mpi_powm (k, f, x, prime);
130
131   ret = k;
132
133 cleanup:
134   _gnutls_mpi_release (&ff);
135   
136   return ret;
137 }
138
139 /*-
140  * _gnutls_get_dh_params - Returns the DH parameters pointer
141  * @dh_params: is an DH parameters structure, or NULL.
142  * @func: is a callback function to receive the parameters or NULL.
143  * @session: a gnutls session.
144  *
145  * This function will return the dh parameters pointer.
146  -*/
147 gnutls_dh_params_t
148 _gnutls_get_dh_params (gnutls_dh_params_t dh_params,
149                        gnutls_params_function * func,
150                        gnutls_session_t session)
151 {
152   gnutls_params_st params;
153   int ret;
154
155   /* if cached return the cached */
156   if (session->internals.params.dh_params)
157     return session->internals.params.dh_params;
158
159   if (dh_params)
160     {
161       session->internals.params.dh_params = dh_params;
162     }
163   else if (func)
164     {
165       ret = func (session, GNUTLS_PARAMS_DH, &params);
166       if (ret == 0 && params.type == GNUTLS_PARAMS_DH)
167         {
168           session->internals.params.dh_params = params.params.dh;
169           session->internals.params.free_dh_params = params.deinit;
170         }
171     }
172
173   return session->internals.params.dh_params;
174 }