Use libtasn1 v2.4.
[gnutls.git] / lib / auth_psk.c
blobc7f1a2e41e02b7a22496d1db888a8dfbee780f00
1 /*
2 * Copyright (C) 2005, 2007, 2008, 2010 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GNUTLS.
8 * The GNUTLS library 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 2.1 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
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
21 * USA
25 #include <gnutls_int.h>
27 #ifdef ENABLE_PSK
29 #include "gnutls_errors.h"
30 #include "gnutls_auth.h"
31 #include "gnutls_auth.h"
32 #include "debug.h"
33 #include "gnutls_num.h"
34 #include <auth_psk.h>
35 #include <auth_psk_passwd.h>
36 #include <gnutls_str.h>
37 #include <gnutls_datum.h>
39 int _gnutls_gen_psk_server_kx (gnutls_session_t session, opaque ** data);
40 int _gnutls_gen_psk_client_kx (gnutls_session_t, opaque **);
42 int _gnutls_proc_psk_client_kx (gnutls_session_t, opaque *, size_t);
44 int _gnutls_proc_psk_server_kx (gnutls_session_t session, opaque * data,
45 size_t _data_size);
47 const mod_auth_st psk_auth_struct = {
48 "PSK",
49 NULL,
50 NULL,
51 _gnutls_gen_psk_server_kx,
52 _gnutls_gen_psk_client_kx,
53 NULL,
54 NULL,
56 NULL,
57 NULL, /* certificate */
58 _gnutls_proc_psk_server_kx,
59 _gnutls_proc_psk_client_kx,
60 NULL,
61 NULL
64 /* Set the PSK premaster secret.
66 int
67 _gnutls_set_psk_session_key (gnutls_session_t session,
68 gnutls_datum_t * dh_secret)
70 gnutls_datum_t pwd_psk = { NULL, 0 };
71 gnutls_datum_t *ppsk;
72 size_t dh_secret_size;
73 int ret;
75 if (session->security_parameters.entity == GNUTLS_CLIENT)
77 gnutls_psk_client_credentials_t cred;
79 cred = (gnutls_psk_client_credentials_t)
80 _gnutls_get_cred (session->key, GNUTLS_CRD_PSK, NULL);
82 if (cred == NULL)
84 gnutls_assert ();
85 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
88 ppsk = &cred->key;
91 else
92 { /* SERVER side */
93 psk_auth_info_t info;
95 info = _gnutls_get_auth_info (session);
97 /* find the key of this username
99 ret = _gnutls_psk_pwd_find_entry (session, info->username, &pwd_psk);
100 if (ret < 0)
102 gnutls_assert ();
103 return ret;
105 ppsk = &pwd_psk;
109 if (dh_secret == NULL)
110 dh_secret_size = ppsk->size;
111 else
112 dh_secret_size = dh_secret->size;
114 /* set the session key
116 session->key->key.size = 4 + dh_secret_size + ppsk->size;
117 session->key->key.data = gnutls_malloc (session->key->key.size);
118 if (session->key->key.data == NULL)
120 gnutls_assert ();
121 ret = GNUTLS_E_MEMORY_ERROR;
122 goto error;
125 /* format of the premaster secret:
126 * (uint16_t) psk_size
127 * psk_size bytes of zeros
128 * (uint16_t) psk_size
129 * the psk
131 _gnutls_write_uint16 (dh_secret_size, session->key->key.data);
132 if (dh_secret == NULL)
133 memset (&session->key->key.data[2], 0, dh_secret_size);
134 else
135 memcpy (&session->key->key.data[2], dh_secret->data, dh_secret->size);
136 _gnutls_write_datum16 (&session->key->key.data[dh_secret_size + 2], *ppsk);
138 ret = 0;
140 error:
141 _gnutls_free_datum (&pwd_psk);
142 return ret;
146 /* Generates the PSK client key exchange
149 * struct {
150 * select (KeyExchangeAlgorithm) {
151 * opaque psk_identity<0..2^16-1>;
152 * } exchange_keys;
153 * } ClientKeyExchange;
157 _gnutls_gen_psk_client_kx (gnutls_session_t session, opaque ** data)
159 int ret;
160 gnutls_psk_client_credentials_t cred;
162 cred = (gnutls_psk_client_credentials_t)
163 _gnutls_get_cred (session->key, GNUTLS_CRD_PSK, NULL);
165 if (cred == NULL)
167 gnutls_assert ();
168 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
171 if (cred->username.data == NULL && cred->key.data == NULL &&
172 cred->get_function != NULL)
174 char *username;
175 gnutls_datum_t key;
177 ret = cred->get_function (session, &username, &key);
178 if (ret)
180 gnutls_assert ();
181 return ret;
184 ret = _gnutls_set_datum (&cred->username, username, strlen (username));
185 gnutls_free (username);
186 if (ret < 0)
188 gnutls_assert ();
189 _gnutls_free_datum (&key);
190 return ret;
193 ret = _gnutls_set_datum (&cred->key, key.data, key.size);
194 _gnutls_free_datum (&key);
195 if (ret < 0)
197 gnutls_assert ();
198 return GNUTLS_E_MEMORY_ERROR;
201 else if (cred->username.data == NULL || cred->key.data == NULL)
203 gnutls_assert ();
204 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
207 ret = _gnutls_set_psk_session_key (session, NULL);
208 if (ret < 0)
210 gnutls_assert ();
211 return ret;
214 (*data) = gnutls_malloc (2 + cred->username.size);
215 if ((*data) == NULL)
217 gnutls_assert ();
218 return GNUTLS_E_MEMORY_ERROR;
221 _gnutls_write_datum16 (*data, cred->username);
223 return (cred->username.size + 2);
227 /* just read the username from the client key exchange.
230 _gnutls_proc_psk_client_kx (gnutls_session_t session, opaque * data,
231 size_t _data_size)
233 ssize_t data_size = _data_size;
234 int ret;
235 gnutls_datum_t username;
236 gnutls_psk_server_credentials_t cred;
237 psk_auth_info_t info;
239 cred = (gnutls_psk_server_credentials_t)
240 _gnutls_get_cred (session->key, GNUTLS_CRD_PSK, NULL);
242 if (cred == NULL)
244 gnutls_assert ();
245 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
248 if ((ret =
249 _gnutls_auth_info_set (session, GNUTLS_CRD_PSK,
250 sizeof (psk_auth_info_st), 1)) < 0)
252 gnutls_assert ();
253 return ret;
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];
264 /* copy the username to the auth info structures
266 info = _gnutls_get_auth_info (session);
268 if (username.size > MAX_SRP_USERNAME)
270 gnutls_assert ();
271 return GNUTLS_E_ILLEGAL_SRP_USERNAME;
274 memcpy (info->username, username.data, username.size);
275 info->username[username.size] = 0;
277 ret = _gnutls_set_psk_session_key (session, NULL);
278 if (ret < 0)
280 gnutls_assert ();
281 goto error;
284 ret = 0;
286 error:
287 return ret;
291 /* Generates the PSK server key exchange
293 * struct {
294 * select (KeyExchangeAlgorithm) {
295 * // other cases for rsa, diffie_hellman, etc.
296 * case psk: // NEW
297 * opaque psk_identity_hint<0..2^16-1>;
298 * };
299 * } ServerKeyExchange;
303 _gnutls_gen_psk_server_kx (gnutls_session_t session, opaque ** data)
305 gnutls_psk_server_credentials_t cred;
306 gnutls_datum_t hint;
308 cred = (gnutls_psk_server_credentials_t)
309 _gnutls_get_cred (session->key, GNUTLS_CRD_PSK, NULL);
311 if (cred == NULL)
313 gnutls_assert ();
314 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
317 /* Abort sending this message if there is no PSK identity hint. */
318 if (cred->hint == NULL)
320 gnutls_assert ();
321 return GNUTLS_E_INT_RET_0;
324 hint.data = cred->hint;
325 hint.size = strlen (cred->hint);
327 (*data) = gnutls_malloc (2 + hint.size);
328 if ((*data) == NULL)
330 gnutls_assert ();
331 return GNUTLS_E_MEMORY_ERROR;
334 _gnutls_write_datum16 (*data, hint);
336 return hint.size + 2;
340 /* just read the hint from the server key exchange.
343 _gnutls_proc_psk_server_kx (gnutls_session_t session, opaque * data,
344 size_t _data_size)
346 ssize_t data_size = _data_size;
347 int ret;
348 gnutls_datum_t hint;
349 gnutls_psk_server_credentials_t cred;
350 psk_auth_info_t info;
352 cred = (gnutls_psk_server_credentials_t)
353 _gnutls_get_cred (session->key, GNUTLS_CRD_PSK, NULL);
355 if (cred == NULL)
357 gnutls_assert ();
358 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
361 if ((ret =
362 _gnutls_auth_info_set (session, GNUTLS_CRD_PSK,
363 sizeof (psk_auth_info_st), 1)) < 0)
365 gnutls_assert ();
366 return ret;
369 DECR_LENGTH_RET (data_size, 2, 0);
370 hint.size = _gnutls_read_uint16 (&data[0]);
372 DECR_LEN (data_size, hint.size);
374 hint.data = &data[2];
376 /* copy the hint to the auth info structures
378 info = _gnutls_get_auth_info (session);
380 if (hint.size > MAX_SRP_USERNAME)
382 gnutls_assert ();
383 return GNUTLS_E_ILLEGAL_SRP_USERNAME;
386 memcpy (info->hint, hint.data, hint.size);
387 info->hint[hint.size] = 0;
389 ret = _gnutls_set_psk_session_key (session, NULL);
390 if (ret < 0)
392 gnutls_assert ();
393 goto error;
396 ret = 0;
398 error:
399 return ret;
402 #endif /* ENABLE_SRP */