updated doc
[gnutls.git] / lib / auth / dhe_psk.c
blob5205cf515b5a441d02762096be99fc1dd1998c73
1 /*
2 * Copyright (C) 2005-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 the PSK Diffie-Hellman key exchange part of the
24 * PSK authentication. The functions here are used in the handshake.
27 #include <gnutls_int.h>
29 #ifdef ENABLE_PSK
31 /* Contains PSK code for DHE and ECDHE
34 #include "gnutls_auth.h"
35 #include "gnutls_errors.h"
36 #include "gnutls_dh.h"
37 #include <auth/psk.h>
38 #include "gnutls_num.h"
39 #include "gnutls_mpi.h"
40 #include <gnutls_state.h>
41 #include <auth/dh_common.h>
42 #include <auth/ecdh_common.h>
43 #include <gnutls_datum.h>
44 #include <auth/psk_passwd.h>
46 static int gen_psk_server_kx (gnutls_session_t, gnutls_buffer_st*);
47 static int gen_psk_client_kx (gnutls_session_t, gnutls_buffer_st*);
48 static int proc_psk_client_kx (gnutls_session_t, uint8_t *, size_t);
49 static int proc_psk_server_kx (gnutls_session_t, uint8_t *, size_t);
50 static int gen_ecdhe_psk_server_kx (gnutls_session_t session, gnutls_buffer_st* data);
51 static int proc_ecdhe_psk_client_kx (gnutls_session_t session, uint8_t * data,
52 size_t _data_size);
54 const mod_auth_st dhe_psk_auth_struct = {
55 "DHE PSK",
56 NULL,
57 NULL,
58 gen_psk_server_kx,
59 gen_psk_client_kx,
60 NULL,
61 NULL,
63 NULL,
64 NULL, /* certificate */
65 proc_psk_server_kx,
66 proc_psk_client_kx,
67 NULL,
68 NULL
71 const mod_auth_st ecdhe_psk_auth_struct = {
72 "ECDHE PSK",
73 NULL,
74 NULL,
75 gen_ecdhe_psk_server_kx,
76 gen_psk_client_kx,
77 NULL,
78 NULL,
80 NULL,
81 NULL, /* certificate */
82 proc_psk_server_kx,
83 proc_ecdhe_psk_client_kx,
84 NULL,
85 NULL
88 static int
89 gen_psk_client_kx (gnutls_session_t session, gnutls_buffer_st* data)
91 int ret, free;
92 gnutls_psk_client_credentials_t cred;
93 gnutls_datum_t username, key;
95 cred = (gnutls_psk_client_credentials_t)
96 _gnutls_get_cred (session, GNUTLS_CRD_PSK, NULL);
98 if (cred == NULL)
99 return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
101 ret = _gnutls_find_psk_key( session, cred, &username, &key, &free);
102 if (ret < 0)
103 return gnutls_assert_val(ret);
105 ret = _gnutls_buffer_append_data_prefix(data, 16, username.data, username.size);
106 if (ret < 0)
108 gnutls_assert();
109 goto cleanup;
112 /* The PSK key is set in there */
113 if (!_gnutls_session_is_ecc (session))
114 ret = _gnutls_gen_dh_common_client_kx_int (session, data, &key);
115 else
116 ret = _gnutls_gen_ecdh_common_client_kx_int (session, data, &key);
118 if (ret < 0)
120 gnutls_assert ();
121 goto cleanup;
124 ret = data->length;
126 cleanup:
127 if (free)
129 _gnutls_free_datum(&username);
130 _gnutls_free_datum(&key);
133 return ret;
137 static int
138 gen_psk_server_kx (gnutls_session_t session, gnutls_buffer_st* data)
140 bigint_t g, p;
141 const bigint_t *mpis;
142 int ret;
143 gnutls_dh_params_t dh_params;
144 gnutls_psk_server_credentials_t cred;
146 cred = (gnutls_psk_server_credentials_t)
147 _gnutls_get_cred (session, GNUTLS_CRD_PSK, NULL);
148 if (cred == NULL)
150 gnutls_assert ();
151 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
154 dh_params =
155 _gnutls_get_dh_params (cred->dh_params, cred->params_func, session);
156 mpis = _gnutls_dh_params_to_mpi (dh_params);
157 if (mpis == NULL)
159 gnutls_assert ();
160 return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
163 p = mpis[0];
164 g = mpis[1];
166 if ((ret =
167 _gnutls_auth_info_set (session, GNUTLS_CRD_PSK,
168 sizeof (psk_auth_info_st), 1)) < 0)
170 gnutls_assert ();
171 return ret;
174 _gnutls_dh_set_group (session, g, p);
176 ret = _gnutls_buffer_append_prefix(data, 16, 0);
177 if (ret < 0)
178 return gnutls_assert_val(ret);
180 ret = _gnutls_dh_common_print_server_kx (session, g, p, dh_params->q_bits, data);
181 if (ret < 0)
182 gnutls_assert ();
184 return ret;
187 static int
188 gen_ecdhe_psk_server_kx (gnutls_session_t session, gnutls_buffer_st* data)
190 int ret;
192 if ((ret =
193 _gnutls_auth_info_set (session, GNUTLS_CRD_PSK,
194 sizeof (psk_auth_info_st), 1)) < 0)
196 gnutls_assert ();
197 return ret;
200 ret = _gnutls_buffer_append_prefix(data, 16, 0);
201 if (ret < 0)
202 return gnutls_assert_val(ret);
204 ret = _gnutls_ecdh_common_print_server_kx (session, data,
205 _gnutls_session_ecc_curve_get(session));
206 if (ret < 0)
207 gnutls_assert ();
209 return ret;
213 static int
214 proc_psk_client_kx (gnutls_session_t session, uint8_t * data,
215 size_t _data_size)
217 int ret;
218 bigint_t p, g;
219 gnutls_dh_params_t dh_params;
220 const bigint_t *mpis;
221 gnutls_datum_t psk_key;
222 gnutls_psk_server_credentials_t cred;
223 psk_auth_info_t info;
224 gnutls_datum_t username;
225 ssize_t data_size = _data_size;
227 cred = (gnutls_psk_server_credentials_t)
228 _gnutls_get_cred (session, GNUTLS_CRD_PSK, NULL);
230 if (cred == NULL)
232 gnutls_assert ();
233 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
236 if ((ret =
237 _gnutls_auth_info_set (session, GNUTLS_CRD_PSK,
238 sizeof (psk_auth_info_st), 1)) < 0)
240 gnutls_assert ();
241 return ret;
244 dh_params =
245 _gnutls_get_dh_params (cred->dh_params, cred->params_func, session);
246 mpis = _gnutls_dh_params_to_mpi (dh_params);
247 if (mpis == NULL)
249 gnutls_assert ();
250 return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
253 p = mpis[0];
254 g = mpis[1];
256 DECR_LEN (data_size, 2);
257 username.size = _gnutls_read_uint16 (&data[0]);
259 DECR_LEN (data_size, username.size);
261 username.data = &data[2];
263 /* copy the username to the auth info structures
265 info = _gnutls_get_auth_info (session);
267 if (username.size > MAX_USERNAME_SIZE)
269 gnutls_assert ();
270 return GNUTLS_E_ILLEGAL_SRP_USERNAME;
273 memcpy (info->username, username.data, username.size);
274 info->username[username.size] = 0;
276 /* Adjust the data */
277 data += username.size + 2;
279 ret = _gnutls_psk_pwd_find_entry(session, info->username, &psk_key);
280 if (ret < 0)
281 return gnutls_assert_val(ret);
283 ret = _gnutls_proc_dh_common_client_kx (session, data, data_size,
284 g, p, &psk_key);
286 _gnutls_free_datum(&psk_key);
288 return ret;
292 static int
293 proc_ecdhe_psk_client_kx (gnutls_session_t session, uint8_t * data,
294 size_t _data_size)
296 int ret;
297 gnutls_psk_server_credentials_t cred;
298 gnutls_datum_t psk_key;
299 psk_auth_info_t info;
300 gnutls_datum_t username;
301 ssize_t data_size = _data_size;
303 cred = (gnutls_psk_server_credentials_t)
304 _gnutls_get_cred (session, GNUTLS_CRD_PSK, NULL);
306 if (cred == NULL)
308 gnutls_assert ();
309 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
312 if ((ret =
313 _gnutls_auth_info_set (session, GNUTLS_CRD_PSK,
314 sizeof (psk_auth_info_st), 1)) < 0)
316 gnutls_assert ();
317 return ret;
320 DECR_LEN (data_size, 2);
321 username.size = _gnutls_read_uint16 (&data[0]);
323 DECR_LEN (data_size, username.size);
325 username.data = &data[2];
327 /* copy the username to the auth info structures
329 info = _gnutls_get_auth_info (session);
331 if (username.size > MAX_USERNAME_SIZE)
333 gnutls_assert ();
334 return GNUTLS_E_ILLEGAL_SRP_USERNAME;
337 memcpy (info->username, username.data, username.size);
338 info->username[username.size] = 0;
340 /* Adjust the data */
341 data += username.size + 2;
343 /* should never fail. It will always return a key even if it is
344 * a random one */
345 ret = _gnutls_psk_pwd_find_entry(session, info->username, &psk_key);
346 if (ret < 0)
347 return gnutls_assert_val(ret);
349 ret = _gnutls_proc_ecdh_common_client_kx(session, data, data_size,
350 _gnutls_session_ecc_curve_get(session), &psk_key);
352 _gnutls_free_datum(&psk_key);
354 return ret;
358 proc_psk_server_kx (gnutls_session_t session, uint8_t * data,
359 size_t _data_size)
362 int ret, psk_size;
363 ssize_t data_size = _data_size;
365 /* set auth_info */
366 if ((ret =
367 _gnutls_auth_info_set (session, GNUTLS_CRD_PSK,
368 sizeof (psk_auth_info_st), 1)) < 0)
370 gnutls_assert ();
371 return ret;
374 DECR_LEN (data_size, 2);
375 psk_size = _gnutls_read_uint16 (data);
376 DECR_LEN (data_size, psk_size);
377 data += 2 + psk_size;
379 if (!_gnutls_session_is_ecc (session))
380 ret = _gnutls_proc_dh_common_server_kx (session, data, data_size);
381 else
382 ret = _gnutls_proc_ecdh_common_server_kx (session, data, data_size);
383 if (ret < 0)
385 gnutls_assert ();
386 return ret;
389 return 0;
392 #endif /* ENABLE_PSK */