Version 1.7.10.
[gnutls.git] / lib / auth_psk.c
blob60c83873f5f724a373af245db135eeda8709fdc6
1 /*
2 * Copyright (C) 2005 Free Software Foundation
4 * Author: Nikos Mavroyanopoulos
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_int.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_client_kx (gnutls_session_t, opaque **);
41 int _gnutls_proc_psk_client_kx (gnutls_session_t, opaque *, size_t);
43 const mod_auth_st psk_auth_struct = {
44 "PSK",
45 NULL,
46 NULL,
47 NULL,
48 _gnutls_gen_psk_client_kx,
49 NULL,
50 NULL,
52 NULL,
53 NULL, /* certificate */
54 NULL,
55 _gnutls_proc_psk_client_kx,
56 NULL,
57 NULL
60 /* Set the PSK premaster secret.
62 int
63 _gnutls_set_psk_session_key (gnutls_session_t session,
64 gnutls_datum * dh_secret)
66 gnutls_datum pwd_psk = { NULL, 0 };
67 gnutls_datum *ppsk;
68 size_t dh_secret_size;
69 int ret;
71 if (session->security_parameters.entity == GNUTLS_CLIENT)
73 gnutls_psk_client_credentials_t cred;
75 cred = (gnutls_psk_client_credentials_t)
76 _gnutls_get_cred (session->key, GNUTLS_CRD_PSK, NULL);
78 if (cred == NULL)
80 gnutls_assert ();
81 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
84 ppsk = &cred->key;
87 else
88 { /* SERVER side */
89 psk_auth_info_t info;
91 info = _gnutls_get_auth_info (session);
93 /* find the key of this username
95 ret = _gnutls_psk_pwd_find_entry (session, info->username, &pwd_psk);
96 if (ret < 0)
98 gnutls_assert ();
99 return ret;
101 ppsk = &pwd_psk;
105 if (dh_secret == NULL)
106 dh_secret_size = ppsk->size;
107 else
108 dh_secret_size = dh_secret->size;
110 /* set the session key
112 session->key->key.size = 4 + dh_secret_size + ppsk->size;
113 session->key->key.data = gnutls_malloc (session->key->key.size);
114 if (session->key->key.data == NULL)
116 gnutls_assert ();
117 ret = GNUTLS_E_MEMORY_ERROR;
118 goto error;
121 /* format of the premaster secret:
122 * (uint16_t) psk_size
123 * psk_size bytes of zeros
124 * (uint16_t) psk_size
125 * the psk
127 _gnutls_write_uint16 (dh_secret_size, session->key->key.data);
128 if (dh_secret == NULL)
129 memset (&session->key->key.data[2], 0, dh_secret_size);
130 else
131 memcpy (&session->key->key.data[2], dh_secret->data, dh_secret->size);
132 _gnutls_write_datum16 (&session->key->key.data[dh_secret_size + 2], *ppsk);
134 ret = 0;
136 error:
137 _gnutls_free_datum (&pwd_psk);
138 return ret;
142 /* Generates the PSK client key exchange
145 * struct {
146 * select (KeyExchangeAlgorithm) {
147 * opaque psk_identity<0..2^16-1>;
148 * } exchange_keys;
149 * } ClientKeyExchange;
153 _gnutls_gen_psk_client_kx (gnutls_session_t session, opaque ** data)
155 int ret;
156 gnutls_psk_client_credentials_t cred;
158 cred = (gnutls_psk_client_credentials_t)
159 _gnutls_get_cred (session->key, GNUTLS_CRD_PSK, NULL);
161 if (cred == NULL)
163 gnutls_assert ();
164 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
167 if (cred->username.data == NULL || cred->key.data == NULL)
169 gnutls_assert ();
170 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
173 ret = _gnutls_set_psk_session_key (session, NULL);
174 if (ret < 0)
176 gnutls_assert ();
177 return ret;
180 (*data) = gnutls_malloc (2 + cred->username.size);
181 if ((*data) == NULL)
183 gnutls_assert ();
184 return GNUTLS_E_MEMORY_ERROR;
187 _gnutls_write_datum16 (*data, cred->username);
189 return (cred->username.size + 2);
193 /* just read the username from the client key exchange.
196 _gnutls_proc_psk_client_kx (gnutls_session_t session, opaque * data,
197 size_t _data_size)
199 ssize_t data_size = _data_size;
200 int ret;
201 gnutls_datum username;
202 gnutls_psk_server_credentials_t cred;
203 psk_auth_info_t info;
205 cred = (gnutls_psk_server_credentials_t)
206 _gnutls_get_cred (session->key, GNUTLS_CRD_PSK, NULL);
208 if (cred == NULL)
210 gnutls_assert ();
211 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
214 if ((ret =
215 _gnutls_auth_info_set (session, GNUTLS_CRD_PSK,
216 sizeof (psk_auth_info_st), 1)) < 0)
218 gnutls_assert ();
219 return ret;
222 DECR_LEN (data_size, 2);
223 username.size = _gnutls_read_uint16 (&data[0]);
225 DECR_LEN (data_size, username.size);
227 username.data = &data[2];
230 /* copy the username to the auth info structures
232 info = _gnutls_get_auth_info (session);
234 if (username.size > MAX_SRP_USERNAME)
236 gnutls_assert ();
237 return GNUTLS_E_ILLEGAL_SRP_USERNAME;
240 memcpy (info->username, username.data, username.size);
241 info->username[username.size] = 0;
243 ret = _gnutls_set_psk_session_key (session, NULL);
244 if (ret < 0)
246 gnutls_assert ();
247 goto error;
250 ret = 0;
252 error:
253 return ret;
257 #endif /* ENABLE_SRP */