cleaned up errno handling.
[gnutls.git] / lib / auth / ecdh_common.c
blob72b75641dabe5897fca59bc89c72ff24e5863fab
1 /*
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>
39 #include <ext/ecc.h>
40 #include <algorithms.h>
41 #include <auth/psk.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;
47 int ret;
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;
59 if (psk_key == NULL)
60 ret = _gnutls_pk_derive(GNUTLS_PK_EC, &session->key->key, &session->key->ecdh_params, &pub);
61 else
63 gnutls_datum_t tmp_dh_key;
65 ret = _gnutls_pk_derive(GNUTLS_PK_EC, &tmp_dh_key, &session->key->ecdh_params, &pub);
66 if (ret < 0)
68 ret = gnutls_assert_val(ret);
69 goto cleanup;
72 ret = _gnutls_set_psk_session_key (session, psk_key, &tmp_dh_key);
73 _gnutls_free_datum (&tmp_dh_key);
77 if (ret < 0)
79 ret = gnutls_assert_val(ret);
80 goto cleanup;
83 ret = 0;
85 cleanup:
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);
90 return ret;
95 int
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;
102 int ret, i = 0;
103 int point_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];
110 i+=1;
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);
114 if (ret < 0)
115 return gnutls_assert_val(ret);
117 /* generate pre-shared key */
118 ret = calc_ecdh_key(session, psk_key);
119 if (ret < 0)
120 return gnutls_assert_val(ret);
122 return 0;
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)
137 int ret;
138 gnutls_datum_t out;
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);
143 if (ret < 0)
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);
148 if (ret < 0)
149 return gnutls_assert_val(ret);
151 ret = _gnutls_buffer_append_data_prefix(data, 8, out.data, out.size);
153 _gnutls_free_datum(&out);
155 if (ret < 0)
156 return gnutls_assert_val(ret);
158 /* generate pre-shared key */
159 ret = calc_ecdh_key(session, psk_key);
160 if (ret < 0)
161 return gnutls_assert_val(ret);
163 return data->length;
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;
175 i = 0;
176 DECR_LEN (data_size, 1);
177 if (data[i++] != 3)
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]));
182 i += 2;
184 ret = _gnutls_session_supports_ecc_curve(session, curve);
185 if (ret < 0)
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];
192 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);
196 if (ret < 0)
197 return gnutls_assert_val(ret);
199 i+=point_size;
201 return i;
204 /* If the psk flag is set, then an empty psk_identity_hint will
205 * be inserted */
206 int _gnutls_ecdh_common_print_server_kx (gnutls_session_t session, gnutls_buffer_st* data,
207 gnutls_ecc_curve_t curve)
209 uint8_t p;
210 int ret;
211 gnutls_datum_t out;
213 if (curve == GNUTLS_ECC_CURVE_INVALID)
214 return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES);
216 /* curve type */
217 p = 3;
219 ret = _gnutls_buffer_append_data(data, &p, 1);
220 if (ret < 0)
221 return gnutls_assert_val(ret);
223 ret = _gnutls_buffer_append_prefix(data, 16, _gnutls_ecc_curve_get_tls_id(curve));
224 if (ret < 0)
225 return gnutls_assert_val(ret);
227 /* generate temporal key */
228 ret = _gnutls_pk_generate(GNUTLS_PK_EC, curve, &session->key->ecdh_params);
229 if (ret < 0)
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);
234 if (ret < 0)
235 return gnutls_assert_val(ret);
237 ret = _gnutls_buffer_append_data_prefix(data, 8, out.data, out.size);
239 _gnutls_free_datum(&out);
241 if (ret < 0)
242 return gnutls_assert_val(ret);
244 return data->length;