2 * Copyright (C) 2002,2003 Nikos Mavroyanopoulos
4 * This file is part of GNUTLS.
6 * The GNUTLS library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 /* This file contains common stuff in Ephemeral Diffie Hellman (DHE) and
23 * Anonymous DH key exchange(DHA). These are used in the handshake procedure
24 * of the certificate and anoymous authentication.
27 #include "gnutls_int.h"
28 #include "gnutls_auth_int.h"
29 #include "gnutls_errors.h"
30 #include "gnutls_dh.h"
31 #include "gnutls_num.h"
32 #include "gnutls_sig.h"
33 #include <gnutls_datum.h>
34 #include <gnutls_x509.h>
35 #include <gnutls_extra.h>
36 #include <gnutls_state.h>
37 #include <auth_dh_common.h>
39 int _gnutls_proc_dh_common_client_kx(gnutls_session session
, opaque
* data
,
40 size_t _data_size
, GNUTLS_MPI g
, GNUTLS_MPI p
)
45 ssize_t data_size
= _data_size
;
48 DECR_LEN( data_size
, 2);
49 n_Y
= _gnutls_read_uint16(&data
[0]);
52 DECR_LEN( data_size
, n_Y
);
53 if (_gnutls_mpi_scan(&session
->key
->client_Y
, &data
[2], &_n_Y
)) {
55 return GNUTLS_E_MPI_SCAN_FAILED
;
58 ret
=_gnutls_dh_set_peer_public_bits( session
, _gnutls_mpi_get_nbits(
59 session
->key
->client_Y
));
67 gnutls_calc_dh_key(session
->key
->client_Y
,
68 session
->key
->dh_secret
, p
);
70 if (session
->key
->KEY
== NULL
) {
72 return GNUTLS_E_MEMORY_ERROR
;
75 _gnutls_mpi_release(&session
->key
->client_Y
);
76 _gnutls_mpi_release(&session
->key
->dh_secret
);
78 ret
= _gnutls_generate_session_key(session
->key
);
79 _gnutls_mpi_release(&session
->key
->KEY
);
88 int _gnutls_gen_dh_common_client_kx(gnutls_session session
, opaque
** data
)
94 X
= gnutls_calc_dh_secret(&x
, session
->key
->client_g
,
95 session
->key
->client_p
);
96 if (X
== NULL
|| x
== NULL
) {
98 _gnutls_mpi_release(&x
);
99 _gnutls_mpi_release(&X
);
100 return GNUTLS_E_MEMORY_ERROR
;
103 ret
=_gnutls_dh_set_secret_bits( session
, _gnutls_mpi_get_nbits(x
));
109 _gnutls_mpi_print( NULL
, &n_X
, X
);
110 (*data
) = gnutls_malloc(n_X
+ 2);
112 _gnutls_mpi_release(&x
);
113 _gnutls_mpi_release(&X
);
114 return GNUTLS_E_MEMORY_ERROR
;
117 _gnutls_mpi_print( &(*data
)[2], &n_X
, X
);
118 _gnutls_mpi_release(&X
);
120 _gnutls_write_uint16(n_X
, &(*data
)[0]);
122 /* calculate the key after calculating the message */
124 gnutls_calc_dh_key(session
->key
->client_Y
, x
,
125 session
->key
->client_p
);
127 _gnutls_mpi_release(&x
);
128 if (session
->key
->KEY
== NULL
) {
130 gnutls_free(*data
); *data
= NULL
;
131 return GNUTLS_E_MEMORY_ERROR
;
134 ret
=_gnutls_dh_set_peer_public_bits( session
, _gnutls_mpi_get_nbits(
135 session
->key
->client_Y
));
139 gnutls_free(*data
); *data
= NULL
;
144 /* THESE SHOULD BE DISCARDED */
145 _gnutls_mpi_release(&session
->key
->client_Y
);
146 _gnutls_mpi_release(&session
->key
->client_p
);
147 _gnutls_mpi_release(&session
->key
->client_g
);
149 ret
= _gnutls_generate_session_key(session
->key
);
150 _gnutls_mpi_release(&session
->key
->KEY
);
159 int _gnutls_proc_dh_common_server_kx( gnutls_session session
, opaque
* data
, size_t _data_size
)
161 uint16 n_Y
, n_g
, n_p
;
162 size_t _n_Y
, _n_g
, _n_p
;
167 ssize_t data_size
= _data_size
;
170 DECR_LEN( data_size
, 2);
171 n_p
= _gnutls_read_uint16( &data
[i
]);
174 DECR_LEN( data_size
, n_p
);
179 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH
;
181 DECR_LEN( data_size
, 2);
182 n_g
= _gnutls_read_uint16( &data
[i
]);
185 DECR_LEN( data_size
, n_g
);
189 DECR_LEN( data_size
, 2);
190 n_Y
= _gnutls_read_uint16( &data
[i
]);
193 DECR_LEN( data_size
, n_Y
);
201 if (_gnutls_mpi_scan(&session
->key
->client_Y
, data_Y
, &_n_Y
) != 0 || session
->key
->client_Y
==NULL
) {
203 return GNUTLS_E_MPI_SCAN_FAILED
;
206 if (_gnutls_mpi_scan(&session
->key
->client_g
, data_g
, &_n_g
) != 0 || session
->key
->client_g
==NULL
) {
208 return GNUTLS_E_MPI_SCAN_FAILED
;
210 if (_gnutls_mpi_scan(&session
->key
->client_p
, data_p
, &_n_p
) != 0 || session
->key
->client_p
==NULL
) {
212 return GNUTLS_E_MPI_SCAN_FAILED
;
215 bits
= _gnutls_dh_get_prime_bits( session
);
221 if ( _gnutls_mpi_get_nbits( session
->key
->client_p
) < (size_t)bits
) {
222 /* the prime used by the peer is not acceptable
225 return GNUTLS_E_DH_PRIME_UNACCEPTABLE
;
228 ret
=_gnutls_dh_set_prime_bits( session
, _gnutls_mpi_get_nbits(
229 session
->key
->client_p
));
235 ret
=_gnutls_dh_set_peer_public_bits( session
, _gnutls_mpi_get_nbits(
236 session
->key
->client_Y
));
242 return n_Y
+ n_p
+ n_g
+ 6;
245 int _gnutls_dh_common_print_server_kx( gnutls_session session
,
246 GNUTLS_MPI g
, GNUTLS_MPI p
, opaque
** data
)
249 size_t n_X
, n_g
, n_p
;
255 X
= gnutls_calc_dh_secret(&x
, g
, p
);
256 if (X
== NULL
|| x
== NULL
) {
258 return GNUTLS_E_MEMORY_ERROR
;
261 session
->key
->dh_secret
= x
;
262 ret
= _gnutls_dh_set_secret_bits( session
, _gnutls_mpi_get_nbits(x
));
265 _gnutls_mpi_release(&X
);
269 _gnutls_mpi_print( NULL
, &n_g
, g
);
270 _gnutls_mpi_print( NULL
, &n_p
, p
);
271 _gnutls_mpi_print( NULL
, &n_X
, X
);
272 (*data
) = gnutls_malloc(n_g
+ n_p
+ n_X
+ 6);
274 _gnutls_mpi_release(&X
);
275 return GNUTLS_E_MEMORY_ERROR
;
278 data_p
= &(*data
)[0];
279 _gnutls_mpi_print( &data_p
[2], &n_p
, p
);
281 _gnutls_write_uint16(n_p
, data_p
);
283 data_g
= &data_p
[2 + n_p
];
284 _gnutls_mpi_print( &data_g
[2], &n_g
, g
);
286 _gnutls_write_uint16(n_g
, data_g
);
288 data_X
= &data_g
[2 + n_g
];
289 _gnutls_mpi_print( &data_X
[2], &n_X
, X
);
290 _gnutls_mpi_release(&X
);
292 _gnutls_write_uint16(n_X
, data_X
);
294 ret
= n_p
+ n_g
+ n_X
+ 6;