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,
25 #include <gnutls_int.h>
29 #include "gnutls_errors.h"
30 #include "gnutls_auth.h"
31 #include "gnutls_auth_int.h"
33 #include "gnutls_num.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
= {
48 _gnutls_gen_psk_client_kx
,
53 NULL
, /* certificate */
55 _gnutls_proc_psk_client_kx
,
60 /* Set the PSK premaster secret.
63 _gnutls_set_psk_session_key (gnutls_session_t session
,
64 gnutls_datum
* dh_secret
)
66 gnutls_datum pwd_psk
= { NULL
, 0 };
68 size_t dh_secret_size
;
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
);
81 return GNUTLS_E_INSUFFICIENT_CREDENTIALS
;
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
);
105 if (dh_secret
== NULL
)
106 dh_secret_size
= ppsk
->size
;
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
)
117 ret
= GNUTLS_E_MEMORY_ERROR
;
121 /* format of the premaster secret:
122 * (uint16_t) psk_size
123 * psk_size bytes of zeros
124 * (uint16_t) psk_size
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
);
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
);
137 _gnutls_free_datum (&pwd_psk
);
142 /* Generates the PSK client key exchange
146 * select (KeyExchangeAlgorithm) {
147 * opaque psk_identity<0..2^16-1>;
149 * } ClientKeyExchange;
153 _gnutls_gen_psk_client_kx (gnutls_session_t session
, opaque
** data
)
156 gnutls_psk_client_credentials_t cred
;
158 cred
= (gnutls_psk_client_credentials_t
)
159 _gnutls_get_cred (session
->key
, GNUTLS_CRD_PSK
, NULL
);
164 return GNUTLS_E_INSUFFICIENT_CREDENTIALS
;
167 if (cred
->username
.data
== NULL
|| cred
->key
.data
== NULL
)
170 return GNUTLS_E_INSUFFICIENT_CREDENTIALS
;
173 ret
= _gnutls_set_psk_session_key (session
, NULL
);
180 (*data
) = gnutls_malloc (2 + cred
->username
.size
);
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
,
199 ssize_t data_size
= _data_size
;
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
);
211 return GNUTLS_E_INSUFFICIENT_CREDENTIALS
;
215 _gnutls_auth_info_set (session
, GNUTLS_CRD_PSK
,
216 sizeof (psk_auth_info_st
), 1)) < 0)
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
)
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
);
257 #endif /* ENABLE_SRP */