2 * Copyright (C) 2011-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 /* This file contains common stuff in Ephemeral Diffie-Hellman (DHE)
24 * and Anonymous DH key exchange(DHA). These are used in the handshake
25 * procedure of the certificate and anoymous authentication.
28 #include "gnutls_int.h"
29 #include "gnutls_auth.h"
30 #include "gnutls_errors.h"
31 #include "gnutls_dh.h"
32 #include "gnutls_num.h"
33 #include "gnutls_sig.h"
34 #include <gnutls_datum.h>
35 #include <gnutls_x509.h>
36 #include <gnutls_state.h>
37 #include <auth/ecdh_common.h>
38 #include <gnutls_ecc.h>
40 #include <algorithms.h>
42 #include <gnutls_pk.h>
44 static int calc_ecdh_key( gnutls_session_t session
, gnutls_datum_t
* psk_key
)
46 gnutls_pk_params_st pub
;
49 memset(&pub
,0,sizeof(pub
));
50 pub
.params
[ECC_PRIME
] = session
->key
->ecdh_params
.params
[ECC_PRIME
];
51 pub
.params
[ECC_ORDER
] = session
->key
->ecdh_params
.params
[ECC_ORDER
];
52 pub
.params
[ECC_A
] = session
->key
->ecdh_params
.params
[ECC_A
];
53 pub
.params
[ECC_B
] = session
->key
->ecdh_params
.params
[ECC_B
];
54 pub
.params
[ECC_GX
] = session
->key
->ecdh_params
.params
[ECC_GX
];
55 pub
.params
[ECC_GY
] = session
->key
->ecdh_params
.params
[ECC_GY
];
56 pub
.params
[ECC_X
] = session
->key
->ecdh_x
;
57 pub
.params
[ECC_Y
] = session
->key
->ecdh_y
;
60 ret
= _gnutls_pk_derive(GNUTLS_PK_EC
, &session
->key
->key
, &session
->key
->ecdh_params
, &pub
);
63 gnutls_datum_t tmp_dh_key
;
65 ret
= _gnutls_pk_derive(GNUTLS_PK_EC
, &tmp_dh_key
, &session
->key
->ecdh_params
, &pub
);
68 ret
= gnutls_assert_val(ret
);
72 ret
= _gnutls_set_psk_session_key (session
, psk_key
, &tmp_dh_key
);
73 _gnutls_free_datum (&tmp_dh_key
);
79 ret
= gnutls_assert_val(ret
);
86 /* no longer needed */
87 _gnutls_mpi_release (&session
->key
->ecdh_x
);
88 _gnutls_mpi_release (&session
->key
->ecdh_y
);
89 gnutls_pk_params_release( &session
->key
->ecdh_params
);
96 _gnutls_proc_ecdh_common_client_kx (gnutls_session_t session
,
97 uint8_t * data
, size_t _data_size
,
98 gnutls_ecc_curve_t curve
,
99 gnutls_datum_t
*psk_key
)
101 ssize_t data_size
= _data_size
;
105 if (curve
== GNUTLS_ECC_CURVE_INVALID
)
106 return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES
);
108 DECR_LEN (data_size
, 1);
109 point_size
= data
[i
];
112 DECR_LEN (data_size
, point_size
);
113 ret
= _gnutls_ecc_ansi_x963_import(&data
[i
], point_size
, &session
->key
->ecdh_x
, &session
->key
->ecdh_y
);
115 return gnutls_assert_val(ret
);
117 /* generate pre-shared key */
118 ret
= calc_ecdh_key(session
, psk_key
);
120 return gnutls_assert_val(ret
);
126 _gnutls_gen_ecdh_common_client_kx (gnutls_session_t session
,
127 gnutls_buffer_st
* data
)
129 return _gnutls_gen_ecdh_common_client_kx_int(session
, data
, NULL
);
133 _gnutls_gen_ecdh_common_client_kx_int (gnutls_session_t session
,
134 gnutls_buffer_st
* data
,
135 gnutls_datum_t
* psk_key
)
139 int curve
= _gnutls_session_ecc_curve_get(session
);
141 /* generate temporal key */
142 ret
= _gnutls_pk_generate(GNUTLS_PK_EC
, curve
, &session
->key
->ecdh_params
);
144 return gnutls_assert_val(ret
);
146 ret
= _gnutls_ecc_ansi_x963_export(curve
, session
->key
->ecdh_params
.params
[6] /* x */,
147 session
->key
->ecdh_params
.params
[7] /* y */, &out
);
149 return gnutls_assert_val(ret
);
151 ret
= _gnutls_buffer_append_data_prefix(data
, 8, out
.data
, out
.size
);
153 _gnutls_free_datum(&out
);
156 return gnutls_assert_val(ret
);
158 /* generate pre-shared key */
159 ret
= calc_ecdh_key(session
, psk_key
);
161 return gnutls_assert_val(ret
);
166 /* Returns the bytes parsed */
168 _gnutls_proc_ecdh_common_server_kx (gnutls_session_t session
,
169 uint8_t * data
, size_t _data_size
)
171 int i
, ret
, point_size
;
172 gnutls_ecc_curve_t curve
;
173 ssize_t data_size
= _data_size
;
176 DECR_LEN (data_size
, 1);
178 return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES
);
180 DECR_LEN (data_size
, 2);
181 curve
= _gnutls_tls_id_to_ecc_curve(_gnutls_read_uint16 (&data
[i
]));
184 ret
= _gnutls_session_supports_ecc_curve(session
, curve
);
186 return gnutls_assert_val(ret
);
188 _gnutls_session_ecc_curve_set(session
, curve
);
190 DECR_LEN (data_size
, 1);
191 point_size
= data
[i
];
194 DECR_LEN (data_size
, point_size
);
195 ret
= _gnutls_ecc_ansi_x963_import(&data
[i
], point_size
, &session
->key
->ecdh_x
, &session
->key
->ecdh_y
);
197 return gnutls_assert_val(ret
);
204 /* If the psk flag is set, then an empty psk_identity_hint will
206 int _gnutls_ecdh_common_print_server_kx (gnutls_session_t session
, gnutls_buffer_st
* data
,
207 gnutls_ecc_curve_t curve
)
213 if (curve
== GNUTLS_ECC_CURVE_INVALID
)
214 return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES
);
219 ret
= _gnutls_buffer_append_data(data
, &p
, 1);
221 return gnutls_assert_val(ret
);
223 ret
= _gnutls_buffer_append_prefix(data
, 16, _gnutls_ecc_curve_get_tls_id(curve
));
225 return gnutls_assert_val(ret
);
227 /* generate temporal key */
228 ret
= _gnutls_pk_generate(GNUTLS_PK_EC
, curve
, &session
->key
->ecdh_params
);
230 return gnutls_assert_val(ret
);
232 ret
= _gnutls_ecc_ansi_x963_export(curve
, session
->key
->ecdh_params
.params
[6] /* x */,
233 session
->key
->ecdh_params
.params
[7] /* y */, &out
);
235 return gnutls_assert_val(ret
);
237 ret
= _gnutls_buffer_append_data_prefix(data
, 8, out
.data
, out
.size
);
239 _gnutls_free_datum(&out
);
242 return gnutls_assert_val(ret
);