Line | Count | Source |
1 | | /* |
2 | | * Copyright (C) 2005-2012 Free Software Foundation, Inc. |
3 | | * |
4 | | * Author: Nikos Mavrogiannopoulos |
5 | | * |
6 | | * This file is part of GnuTLS. |
7 | | * |
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 2.1 of |
11 | | * the License, or (at your option) any later version. |
12 | | * |
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. |
17 | | * |
18 | | * You should have received a copy of the GNU Lesser General Public License |
19 | | * along with this program. If not, see <https://www.gnu.org/licenses/> |
20 | | * |
21 | | */ |
22 | | |
23 | | /* Functions for manipulating the PSK credentials. */ |
24 | | |
25 | | #include "gnutls_int.h" |
26 | | #include "errors.h" |
27 | | #include "str.h" |
28 | | #include "auth/psk.h" |
29 | | #include "state.h" |
30 | | |
31 | | #ifdef ENABLE_PSK |
32 | | |
33 | | #include "auth/psk_passwd.h" |
34 | | #include "num.h" |
35 | | #include "file.h" |
36 | | #include "datum.h" |
37 | | #include "debug.h" |
38 | | #include "dh.h" |
39 | | |
40 | | /** |
41 | | * gnutls_psk_free_client_credentials: |
42 | | * @sc: is a #gnutls_psk_client_credentials_t type. |
43 | | * |
44 | | * Free a gnutls_psk_client_credentials_t structure. |
45 | | **/ |
46 | | void gnutls_psk_free_client_credentials(gnutls_psk_client_credentials_t sc) |
47 | 0 | { |
48 | 0 | _gnutls_free_datum(&sc->username); |
49 | 0 | _gnutls_free_datum(&sc->key); |
50 | 0 | gnutls_free(sc); |
51 | 0 | } |
52 | | |
53 | | /** |
54 | | * gnutls_psk_allocate_client_credentials: |
55 | | * @sc: is a pointer to a #gnutls_psk_client_credentials_t type. |
56 | | * |
57 | | * Allocate a gnutls_psk_client_credentials_t structure. |
58 | | * |
59 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise |
60 | | * an error code is returned. |
61 | | **/ |
62 | | int gnutls_psk_allocate_client_credentials(gnutls_psk_client_credentials_t *sc) |
63 | 0 | { |
64 | | /* TLS 1.3 - Default binder HMAC algorithm is SHA-256 */ |
65 | 0 | return gnutls_psk_allocate_client_credentials2(sc, GNUTLS_MAC_SHA256); |
66 | 0 | } |
67 | | |
68 | | /** |
69 | | * gnutls_psk_allocate_client_credentials2: |
70 | | * @sc: is a pointer to a #gnutls_psk_client_credentials_t type. |
71 | | * @mac: encryption algorithm to use |
72 | | * |
73 | | * Allocate a gnutls_psk_client_credentials_t structure and initializes |
74 | | * the HMAC binder algorithm to @mac. |
75 | | * |
76 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise |
77 | | * an error code is returned. |
78 | | **/ |
79 | | int gnutls_psk_allocate_client_credentials2(gnutls_psk_client_credentials_t *sc, |
80 | | gnutls_mac_algorithm_t mac) |
81 | 0 | { |
82 | | /* TLS 1.3 - Only SHA-256 and SHA-384 are allowed */ |
83 | 0 | if (mac != GNUTLS_MAC_SHA256 && mac != GNUTLS_MAC_SHA384) |
84 | 0 | return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); |
85 | | |
86 | 0 | *sc = gnutls_calloc(1, sizeof(psk_client_credentials_st)); |
87 | |
|
88 | 0 | if (*sc == NULL) |
89 | 0 | return GNUTLS_E_MEMORY_ERROR; |
90 | | |
91 | 0 | (*sc)->binder_algo = _gnutls_mac_to_entry(mac); |
92 | 0 | return 0; |
93 | 0 | } |
94 | | |
95 | | /** |
96 | | * gnutls_psk_set_client_credentials: |
97 | | * @res: is a #gnutls_psk_client_credentials_t type. |
98 | | * @username: is the user's zero-terminated userid |
99 | | * @key: is the user's key |
100 | | * @flags: indicate the format of the key, either |
101 | | * %GNUTLS_PSK_KEY_RAW or %GNUTLS_PSK_KEY_HEX. |
102 | | * |
103 | | * This function sets the username and password, in a |
104 | | * gnutls_psk_client_credentials_t type. Those will be used in |
105 | | * PSK authentication. @username should be an ASCII string or UTF-8 |
106 | | * string. In case of a UTF-8 string it is recommended to be following |
107 | | * the PRECIS framework for usernames (rfc8265). The key can be either |
108 | | * in raw byte format or in Hex format (without the 0x prefix). |
109 | | * |
110 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise |
111 | | * an error code is returned. |
112 | | **/ |
113 | | int gnutls_psk_set_client_credentials(gnutls_psk_client_credentials_t res, |
114 | | const char *username, |
115 | | const gnutls_datum_t *key, |
116 | | gnutls_psk_key_flags flags) |
117 | 0 | { |
118 | 0 | gnutls_datum_t dat; |
119 | |
|
120 | 0 | if (username == NULL) |
121 | 0 | return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); |
122 | | |
123 | 0 | dat.data = (unsigned char *)username; |
124 | 0 | dat.size = strlen(username); |
125 | |
|
126 | 0 | return gnutls_psk_set_client_credentials2(res, &dat, key, flags); |
127 | 0 | } |
128 | | |
129 | | /** |
130 | | * gnutls_psk_set_client_credentials2: |
131 | | * @res: is a #gnutls_psk_client_credentials_t type. |
132 | | * @username: is the userid |
133 | | * @key: is the user's key |
134 | | * @flags: indicate the format of the key, either |
135 | | * %GNUTLS_PSK_KEY_RAW or %GNUTLS_PSK_KEY_HEX. |
136 | | * |
137 | | * This function is identical to gnutls_psk_set_client_credentials(), |
138 | | * except that it allows a non-null-terminated username to be introduced. |
139 | | * |
140 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise |
141 | | * an error code is returned. |
142 | | */ |
143 | | int gnutls_psk_set_client_credentials2(gnutls_psk_client_credentials_t res, |
144 | | const gnutls_datum_t *username, |
145 | | const gnutls_datum_t *key, |
146 | | gnutls_psk_key_flags flags) |
147 | 0 | { |
148 | 0 | int ret; |
149 | |
|
150 | 0 | if (username == NULL || username->data == NULL || key == NULL || |
151 | 0 | key->data == NULL) { |
152 | 0 | gnutls_assert(); |
153 | 0 | return GNUTLS_E_INVALID_REQUEST; |
154 | 0 | } |
155 | | |
156 | 0 | ret = _gnutls_set_datum(&res->username, username->data, username->size); |
157 | 0 | if (ret < 0) |
158 | 0 | return ret; |
159 | | |
160 | 0 | if (flags == GNUTLS_PSK_KEY_RAW) { |
161 | 0 | if (_gnutls_set_datum(&res->key, key->data, key->size) < 0) { |
162 | 0 | gnutls_assert(); |
163 | 0 | ret = GNUTLS_E_MEMORY_ERROR; |
164 | 0 | goto error; |
165 | 0 | } |
166 | 0 | } else { /* HEX key */ |
167 | 0 | size_t size; |
168 | 0 | size = res->key.size = key->size / 2; |
169 | 0 | res->key.data = gnutls_malloc(size); |
170 | 0 | if (res->key.data == NULL) { |
171 | 0 | gnutls_assert(); |
172 | 0 | ret = GNUTLS_E_MEMORY_ERROR; |
173 | 0 | goto error; |
174 | 0 | } |
175 | | |
176 | 0 | ret = gnutls_hex_decode(key, (char *)res->key.data, &size); |
177 | 0 | res->key.size = (unsigned int)size; |
178 | 0 | if (ret < 0) { |
179 | 0 | gnutls_assert(); |
180 | 0 | goto error; |
181 | 0 | } |
182 | | |
183 | 0 | if (size < 4) { |
184 | 0 | gnutls_assert(); |
185 | 0 | ret = GNUTLS_E_INVALID_REQUEST; |
186 | 0 | goto error; |
187 | 0 | } |
188 | 0 | } |
189 | | |
190 | 0 | return 0; |
191 | | |
192 | 0 | error: |
193 | 0 | _gnutls_free_datum(&res->username); |
194 | 0 | _gnutls_free_datum(&res->key); |
195 | |
|
196 | 0 | return ret; |
197 | 0 | } |
198 | | |
199 | | /** |
200 | | * gnutls_psk_free_server_credentials: |
201 | | * @sc: is a #gnutls_psk_server_credentials_t type. |
202 | | * |
203 | | * Free a gnutls_psk_server_credentials_t structure. |
204 | | **/ |
205 | | void gnutls_psk_free_server_credentials(gnutls_psk_server_credentials_t sc) |
206 | 0 | { |
207 | 0 | if (sc->deinit_dh_params) { |
208 | 0 | gnutls_dh_params_deinit(sc->dh_params); |
209 | 0 | } |
210 | |
|
211 | 0 | gnutls_free(sc->password_file); |
212 | 0 | gnutls_free(sc->hint); |
213 | 0 | gnutls_free(sc); |
214 | 0 | } |
215 | | |
216 | | /** |
217 | | * gnutls_psk_allocate_server_credentials: |
218 | | * @sc: is a pointer to a #gnutls_psk_server_credentials_t type. |
219 | | * |
220 | | * Allocate a gnutls_psk_server_credentials_t structure. |
221 | | * |
222 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise |
223 | | * an error code is returned. |
224 | | **/ |
225 | | int gnutls_psk_allocate_server_credentials(gnutls_psk_server_credentials_t *sc) |
226 | 0 | { |
227 | | /* TLS 1.3 - Default binder HMAC algorithm is SHA-256 */ |
228 | 0 | return gnutls_psk_allocate_server_credentials2(sc, GNUTLS_MAC_SHA256); |
229 | 0 | } |
230 | | |
231 | | /** |
232 | | * gnutls_psk_allocate_server_credentials2: |
233 | | * @sc: is a pointer to a #gnutls_psk_server_credentials_t type. |
234 | | * @mac: encryption algorithm to use |
235 | | * |
236 | | * Allocate a gnutls_psk_server_credentials_t structure and initializes |
237 | | * the HMAC binder algorithm to @mac. If @mac is set to GNUTLS_MAC_UNKNOWN |
238 | | * both possible algorithms SHA384 and SHA256 are applied to find a matching |
239 | | * binder value. |
240 | | * |
241 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise |
242 | | * an error code is returned. |
243 | | **/ |
244 | | int gnutls_psk_allocate_server_credentials2(gnutls_psk_server_credentials_t *sc, |
245 | | gnutls_mac_algorithm_t mac) |
246 | 0 | { |
247 | | /* |
248 | | * TLS 1.3 - Only SHA-256 and SHA-384 are allowed; |
249 | | * additionally allow GNUTLS_MAC_UNKNOWN for autodetection. |
250 | | */ |
251 | 0 | if (mac != GNUTLS_MAC_SHA256 && mac != GNUTLS_MAC_SHA384 && |
252 | 0 | mac != GNUTLS_MAC_UNKNOWN) |
253 | 0 | return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); |
254 | | |
255 | 0 | *sc = gnutls_calloc(1, sizeof(psk_server_cred_st)); |
256 | |
|
257 | 0 | if (*sc == NULL) |
258 | 0 | return GNUTLS_E_MEMORY_ERROR; |
259 | | /* |
260 | | * For GNUTLS_MAC_UNKNOWN, setting binder_algo to NULL allows |
261 | | * for auto-detction. |
262 | | */ |
263 | 0 | (*sc)->binder_algo = |
264 | 0 | (mac == GNUTLS_MAC_UNKNOWN ? NULL : _gnutls_mac_to_entry(mac)); |
265 | 0 | return 0; |
266 | 0 | } |
267 | | |
268 | | /** |
269 | | * gnutls_psk_set_server_credentials_file: |
270 | | * @res: is a #gnutls_psk_server_credentials_t type. |
271 | | * @password_file: is the PSK password file (passwd.psk) |
272 | | * |
273 | | * This function sets the password file, in a |
274 | | * #gnutls_psk_server_credentials_t type. This password file |
275 | | * holds usernames and keys and will be used for PSK authentication. |
276 | | * |
277 | | * Each entry in the file consists of a username, followed by a colon |
278 | | * (':') and a hex-encoded key. If the username contains a colon or |
279 | | * any other special character, it can be hex-encoded preceded by a |
280 | | * '#'. |
281 | | * |
282 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise |
283 | | * an error code is returned. |
284 | | **/ |
285 | | int gnutls_psk_set_server_credentials_file(gnutls_psk_server_credentials_t res, |
286 | | const char *password_file) |
287 | 0 | { |
288 | 0 | if (password_file == NULL) { |
289 | 0 | gnutls_assert(); |
290 | 0 | return GNUTLS_E_INVALID_REQUEST; |
291 | 0 | } |
292 | | |
293 | | /* Check if the files can be opened */ |
294 | 0 | if (_gnutls_file_exists(password_file) != 0) { |
295 | 0 | gnutls_assert(); |
296 | 0 | return GNUTLS_E_FILE_ERROR; |
297 | 0 | } |
298 | | |
299 | 0 | res->password_file = gnutls_strdup(password_file); |
300 | 0 | if (res->password_file == NULL) { |
301 | 0 | gnutls_assert(); |
302 | 0 | return GNUTLS_E_MEMORY_ERROR; |
303 | 0 | } |
304 | | |
305 | 0 | return 0; |
306 | 0 | } |
307 | | |
308 | | /** |
309 | | * gnutls_psk_set_server_credentials_hint: |
310 | | * @res: is a #gnutls_psk_server_credentials_t type. |
311 | | * @hint: is the PSK identity hint string |
312 | | * |
313 | | * This function sets the identity hint, in a |
314 | | * #gnutls_psk_server_credentials_t type. This hint is sent to |
315 | | * the client to help it chose a good PSK credential (i.e., username |
316 | | * and password). |
317 | | * |
318 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise |
319 | | * an error code is returned. |
320 | | * |
321 | | * Since: 2.4.0 |
322 | | **/ |
323 | | int gnutls_psk_set_server_credentials_hint(gnutls_psk_server_credentials_t res, |
324 | | const char *hint) |
325 | 0 | { |
326 | 0 | res->hint = gnutls_strdup(hint); |
327 | 0 | if (res->hint == NULL) { |
328 | 0 | gnutls_assert(); |
329 | 0 | return GNUTLS_E_MEMORY_ERROR; |
330 | 0 | } |
331 | | |
332 | 0 | return 0; |
333 | 0 | } |
334 | | |
335 | | static int call_server_callback1(gnutls_session_t session, |
336 | | const gnutls_datum_t *username, |
337 | | gnutls_datum_t *key) |
338 | 0 | { |
339 | 0 | gnutls_psk_server_credentials_t cred = |
340 | 0 | (gnutls_psk_server_credentials_t)_gnutls_get_cred( |
341 | 0 | session, GNUTLS_CRD_PSK); |
342 | 0 | if (unlikely(cred == NULL)) |
343 | 0 | return gnutls_assert_val(-1); |
344 | | |
345 | 0 | return cred->pwd_callback1(session, (const char *)username->data, key); |
346 | 0 | } |
347 | | |
348 | | static int call_server_callback2(gnutls_session_t session, |
349 | | const gnutls_datum_t *username, |
350 | | gnutls_datum_t *key, |
351 | | gnutls_psk_key_flags *flags) |
352 | 0 | { |
353 | 0 | gnutls_psk_server_credentials_t cred; |
354 | 0 | int ret; |
355 | |
|
356 | 0 | cred = (gnutls_psk_server_credentials_t)_gnutls_get_cred( |
357 | 0 | session, GNUTLS_CRD_PSK); |
358 | 0 | if (unlikely(cred == NULL)) |
359 | 0 | return gnutls_assert_val(-1); |
360 | | |
361 | 0 | ret = cred->pwd_callback2(session, username, key); |
362 | 0 | if (ret >= 0) { |
363 | 0 | if (flags) { |
364 | 0 | *flags = 0; |
365 | 0 | } |
366 | 0 | } |
367 | 0 | return ret; |
368 | 0 | } |
369 | | |
370 | | /** |
371 | | * gnutls_psk_set_server_credentials_function: |
372 | | * @cred: is a #gnutls_psk_server_credentials_t type. |
373 | | * @func: is the callback function |
374 | | * |
375 | | * This function can be used to set a callback to retrieve the user's PSK credentials. |
376 | | * The callback's function form is: |
377 | | * int (*callback)(gnutls_session_t, const char* username, |
378 | | * gnutls_datum_t* key); |
379 | | * |
380 | | * @username contains the actual username. |
381 | | * The @key must be filled in using the gnutls_malloc(). |
382 | | * |
383 | | * In case the callback returned a negative number then gnutls will |
384 | | * assume that the username does not exist. |
385 | | * |
386 | | * The callback function will only be called once per handshake. The |
387 | | * callback function should return 0 on success, while -1 indicates |
388 | | * an error. |
389 | | **/ |
390 | | void gnutls_psk_set_server_credentials_function( |
391 | | gnutls_psk_server_credentials_t cred, |
392 | | gnutls_psk_server_credentials_function *func) |
393 | 0 | { |
394 | 0 | cred->pwd_callback1 = func; |
395 | 0 | cred->pwd_callback2 = call_server_callback1; |
396 | 0 | cred->pwd_callback = call_server_callback2; |
397 | 0 | } |
398 | | |
399 | | /** |
400 | | * gnutls_psk_set_server_credentials_function2: |
401 | | * @cred: is a #gnutls_psk_server_credentials_t type. |
402 | | * @func: is the callback function |
403 | | * |
404 | | * This function can be used to set a callback to retrieve the user's PSK credentials. |
405 | | * The callback's function form is: |
406 | | * int (*callback)(gnutls_session_t, const gnutls_datum_t* username, |
407 | | * gnutls_datum_t* key); |
408 | | * |
409 | | * This callback function has the same semantics as that of gnutls_psk_set_server_credentials_function(), |
410 | | * but it allows non-string usernames to be used. |
411 | | * |
412 | | * @username contains the actual username. |
413 | | * The @key must be filled in using the gnutls_malloc(). |
414 | | * |
415 | | * In case the callback returned a negative number then gnutls will |
416 | | * assume that the username does not exist. |
417 | | * |
418 | | * The callback function will only be called once per handshake. The |
419 | | * callback function should return 0 on success, while -1 indicates |
420 | | * an error. |
421 | | **/ |
422 | | void gnutls_psk_set_server_credentials_function2( |
423 | | gnutls_psk_server_credentials_t cred, |
424 | | gnutls_psk_server_credentials_function2 func) |
425 | 0 | { |
426 | 0 | cred->pwd_callback1 = NULL; |
427 | 0 | cred->pwd_callback2 = func; |
428 | 0 | cred->pwd_callback = call_server_callback2; |
429 | 0 | } |
430 | | |
431 | | /** |
432 | | * gnutls_psk_set_server_credentials_function3: |
433 | | * @cred: is a #gnutls_psk_server_credentials_t type. |
434 | | * @func: is the callback function |
435 | | * |
436 | | * This function can be used to set a callback to retrieve the user's PSK credentials. |
437 | | * The callback's function form is: |
438 | | * int (*callback)(gnutls_session_t, const gnutls_datum_t* username, |
439 | | * gnutls_datum_t* key, gnutls_psk_key_flags *flags); |
440 | | * |
441 | | * This callback function has the same semantics as that of |
442 | | * gnutls_psk_set_server_credentials_function2(), but it returns flags |
443 | | * associated with the key. The callback may import external PSK |
444 | | * using the method described in RFC 9258 by using |
445 | | * gnutls_psk_format_imported_identity(). |
446 | | * |
447 | | * @username contains the actual username. |
448 | | * The @key must be filled in using the gnutls_malloc(). |
449 | | * |
450 | | * In case the callback returned a negative number then gnutls will |
451 | | * assume that the username does not exist. |
452 | | * |
453 | | * The callback function will only be called once per handshake. The |
454 | | * callback function should return 0 on success, while -1 indicates |
455 | | * an error. |
456 | | **/ |
457 | | void gnutls_psk_set_server_credentials_function3( |
458 | | gnutls_psk_server_credentials_t cred, |
459 | | gnutls_psk_server_credentials_function3 func) |
460 | 0 | { |
461 | 0 | cred->pwd_callback1 = NULL; |
462 | 0 | cred->pwd_callback2 = NULL; |
463 | 0 | cred->pwd_callback = func; |
464 | 0 | } |
465 | | |
466 | | static int call_client_callback1(gnutls_session_t session, |
467 | | gnutls_datum_t *username, gnutls_datum_t *key) |
468 | 0 | { |
469 | 0 | gnutls_psk_client_credentials_t cred; |
470 | 0 | int ret; |
471 | 0 | char *user_p; |
472 | |
|
473 | 0 | cred = (gnutls_psk_client_credentials_t)_gnutls_get_cred( |
474 | 0 | session, GNUTLS_CRD_PSK); |
475 | 0 | if (unlikely(cred == NULL)) |
476 | 0 | return gnutls_assert_val(-1); |
477 | | |
478 | 0 | ret = cred->get_function1(session, &user_p, key); |
479 | 0 | if (ret >= 0) { |
480 | 0 | username->data = (uint8_t *)user_p; |
481 | 0 | username->size = strlen(user_p); |
482 | 0 | } |
483 | |
|
484 | 0 | return ret; |
485 | 0 | } |
486 | | |
487 | | static int call_client_callback2(gnutls_session_t session, |
488 | | gnutls_datum_t *username, gnutls_datum_t *key, |
489 | | gnutls_psk_key_flags *flags) |
490 | 0 | { |
491 | 0 | gnutls_psk_client_credentials_t cred; |
492 | 0 | int ret; |
493 | |
|
494 | 0 | cred = (gnutls_psk_client_credentials_t)_gnutls_get_cred( |
495 | 0 | session, GNUTLS_CRD_PSK); |
496 | 0 | if (unlikely(cred == NULL)) |
497 | 0 | return gnutls_assert_val(-1); |
498 | | |
499 | 0 | ret = cred->get_function2(session, username, key); |
500 | 0 | if (ret < 0) { |
501 | 0 | return ret; |
502 | 0 | } |
503 | | |
504 | 0 | if (flags) { |
505 | 0 | *flags = 0; |
506 | 0 | } |
507 | |
|
508 | 0 | return ret; |
509 | 0 | } |
510 | | |
511 | | /** |
512 | | * gnutls_psk_set_client_credentials_function: |
513 | | * @cred: is a #gnutls_psk_server_credentials_t type. |
514 | | * @func: is the callback function |
515 | | * |
516 | | * This function can be used to set a callback to retrieve the username and |
517 | | * password for client PSK authentication. |
518 | | * The callback's function form is: |
519 | | * int (*callback)(gnutls_session_t, char** username, |
520 | | * gnutls_datum_t* key); |
521 | | * |
522 | | * The @username and @key->data must be allocated using gnutls_malloc(). |
523 | | * The @username should be an ASCII string or UTF-8 |
524 | | * string. In case of a UTF-8 string it is recommended to be following |
525 | | * the PRECIS framework for usernames (rfc8265). |
526 | | * |
527 | | * The callback function will be called once per handshake. |
528 | | * |
529 | | * The callback function should return 0 on success. |
530 | | * -1 indicates an error. |
531 | | **/ |
532 | | void gnutls_psk_set_client_credentials_function( |
533 | | gnutls_psk_client_credentials_t cred, |
534 | | gnutls_psk_client_credentials_function *func) |
535 | 0 | { |
536 | 0 | cred->get_function1 = func; |
537 | 0 | cred->get_function2 = call_client_callback1; |
538 | 0 | cred->get_function = call_client_callback2; |
539 | 0 | } |
540 | | |
541 | | /** |
542 | | * gnutls_psk_set_client_credentials_function2: |
543 | | * @cred: is a #gnutls_psk_server_credentials_t type. |
544 | | * @func: is the callback function |
545 | | * |
546 | | * This function can be used to set a callback to retrieve the username and |
547 | | * password for client PSK authentication. |
548 | | * The callback's function form is: |
549 | | * int (*callback)(gnutls_session_t, gnutls_datum_t* username, |
550 | | * gnutls_datum_t* key); |
551 | | * |
552 | | * This callback function has the same semantics as that of gnutls_psk_set_client_credentials_function(), |
553 | | * but it allows non-string usernames to be used. |
554 | | * |
555 | | * The @username and @key->data must be allocated using gnutls_malloc(). |
556 | | * The @username should be an ASCII string or UTF-8 |
557 | | * string. In case of a UTF-8 string it is recommended to be following |
558 | | * the PRECIS framework for usernames (rfc8265). |
559 | | * |
560 | | * The callback function will be called once per handshake. |
561 | | * |
562 | | * The callback function should return 0 on success. |
563 | | * -1 indicates an error. |
564 | | **/ |
565 | | void gnutls_psk_set_client_credentials_function2( |
566 | | gnutls_psk_client_credentials_t cred, |
567 | | gnutls_psk_client_credentials_function2 *func) |
568 | 0 | { |
569 | 0 | cred->get_function1 = NULL; |
570 | 0 | cred->get_function2 = func; |
571 | 0 | cred->get_function = call_client_callback2; |
572 | 0 | } |
573 | | |
574 | | /** |
575 | | * gnutls_psk_set_client_credentials_function3: |
576 | | * @cred: is a #gnutls_psk_server_credentials_t type. |
577 | | * @func: is the callback function |
578 | | * |
579 | | * This function can be used to set a callback to retrieve the username and |
580 | | * password for client PSK authentication. |
581 | | * The callback's function form is: |
582 | | * int (*callback)(gnutls_session_t, gnutls_datum_t* username, |
583 | | * gnutls_datum_t* key, gnutls_datum_t* context, gnutls_psk_key_flags *flags); |
584 | | * |
585 | | * This callback function has the same semantics as that of |
586 | | * gnutls_psk_set_client_credentials_function2(), but it returns flags |
587 | | * associated with the key. The callback may import external PSK |
588 | | * using the method described in RFC 9258 by using |
589 | | * gnutls_psk_format_imported_identity(). |
590 | | * |
591 | | * The data field of @username, @key, and @context must be allocated |
592 | | * using gnutls_malloc(). The @username should be an ASCII string or |
593 | | * UTF-8 string. In case of a UTF-8 string it is recommended to be |
594 | | * following the PRECIS framework for usernames (rfc8265). |
595 | | * |
596 | | * The callback function will be called once per handshake. |
597 | | * |
598 | | * The callback function should return 0 on success. |
599 | | * -1 indicates an error. |
600 | | **/ |
601 | | void gnutls_psk_set_client_credentials_function3( |
602 | | gnutls_psk_client_credentials_t cred, |
603 | | gnutls_psk_client_credentials_function3 *func) |
604 | 0 | { |
605 | 0 | cred->get_function1 = NULL; |
606 | 0 | cred->get_function2 = NULL; |
607 | 0 | cred->get_function = func; |
608 | 0 | } |
609 | | |
610 | | /** |
611 | | * gnutls_psk_server_get_username: |
612 | | * @session: is a gnutls session |
613 | | * |
614 | | * This should only be called in case of PSK authentication and in |
615 | | * case of a server. |
616 | | * |
617 | | * The returned pointer should be considered constant (do not free) and valid |
618 | | * for the lifetime of the session. |
619 | | * |
620 | | * This function will return %NULL if the username has embedded NULL bytes. |
621 | | * In that case, gnutls_psk_server_get_username2() should be used to retrieve the username. |
622 | | * |
623 | | * Returns: the username of the peer, or %NULL in case of an error, |
624 | | * or if the username has embedded NULLs. |
625 | | **/ |
626 | | const char *gnutls_psk_server_get_username(gnutls_session_t session) |
627 | 0 | { |
628 | 0 | psk_auth_info_t info; |
629 | |
|
630 | 0 | CHECK_AUTH_TYPE(GNUTLS_CRD_PSK, NULL); |
631 | |
|
632 | 0 | info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK); |
633 | 0 | if (info == NULL) |
634 | 0 | return NULL; |
635 | | |
636 | 0 | if (info->username && !memchr(info->username, '\0', info->username_len)) |
637 | 0 | return info->username; |
638 | | |
639 | 0 | return NULL; |
640 | 0 | } |
641 | | |
642 | | /** |
643 | | * gnutls_psk_server_get_username2: |
644 | | * @session: is a gnutls session |
645 | | * @username: a datum that will be filled in by this function |
646 | | * |
647 | | * Return a pointer to the username of the peer in the supplied datum. Does not |
648 | | * need to be null-terminated. |
649 | | * |
650 | | * This should only be called in case of PSK authentication and in |
651 | | * case of a server. |
652 | | * |
653 | | * The returned pointer should be considered constant (do not free) and valid |
654 | | * for the lifetime of the session. |
655 | | * |
656 | | * Returns: %GNUTLS_E_SUCCESS, or a negative value in case of an error. |
657 | | **/ |
658 | | int gnutls_psk_server_get_username2(gnutls_session_t session, |
659 | | gnutls_datum_t *username) |
660 | 0 | { |
661 | 0 | psk_auth_info_t info; |
662 | |
|
663 | 0 | CHECK_AUTH_TYPE(GNUTLS_CRD_PSK, GNUTLS_E_INVALID_REQUEST); |
664 | |
|
665 | 0 | info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK); |
666 | 0 | if (info == NULL) |
667 | 0 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; |
668 | | |
669 | 0 | if (info->username_len > 0) { |
670 | 0 | username->data = (unsigned char *)info->username; |
671 | 0 | username->size = info->username_len; |
672 | 0 | return 0; |
673 | 0 | } |
674 | | |
675 | 0 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; |
676 | 0 | } |
677 | | |
678 | | /** |
679 | | * gnutls_psk_client_get_hint: |
680 | | * @session: is a gnutls session |
681 | | * |
682 | | * The PSK identity hint may give the client help in deciding which |
683 | | * username to use. This should only be called in case of PSK |
684 | | * authentication and in case of a client. |
685 | | * |
686 | | * Note: there is no hint in TLS 1.3, so this function will return %NULL |
687 | | * if TLS 1.3 has been negotiated. |
688 | | * |
689 | | * Returns: the identity hint of the peer, or %NULL in case of an error or if TLS 1.3 is being used. |
690 | | * |
691 | | * Since: 2.4.0 |
692 | | **/ |
693 | | const char *gnutls_psk_client_get_hint(gnutls_session_t session) |
694 | 0 | { |
695 | 0 | psk_auth_info_t info; |
696 | |
|
697 | 0 | CHECK_AUTH_TYPE(GNUTLS_CRD_PSK, NULL); |
698 | |
|
699 | 0 | info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK); |
700 | 0 | return info ? info->hint : NULL; |
701 | 0 | } |
702 | | |
703 | | /** |
704 | | * gnutls_psk_set_server_dh_params: |
705 | | * @res: is a gnutls_psk_server_credentials_t type |
706 | | * @dh_params: is a structure that holds Diffie-Hellman parameters. |
707 | | * |
708 | | * This function will set the Diffie-Hellman parameters for an |
709 | | * anonymous server to use. These parameters will be used in |
710 | | * Diffie-Hellman exchange with PSK cipher suites. |
711 | | * |
712 | | * Deprecated: This function is unnecessary and discouraged on GnuTLS 3.6.0 |
713 | | * or later. Since 3.6.0, DH parameters are negotiated |
714 | | * following RFC7919. |
715 | | * |
716 | | **/ |
717 | | void gnutls_psk_set_server_dh_params(gnutls_psk_server_credentials_t res, |
718 | | gnutls_dh_params_t dh_params) |
719 | 0 | { |
720 | 0 | if (res->deinit_dh_params) { |
721 | 0 | res->deinit_dh_params = 0; |
722 | 0 | gnutls_dh_params_deinit(res->dh_params); |
723 | 0 | res->dh_params = NULL; |
724 | 0 | } |
725 | |
|
726 | 0 | res->dh_params = dh_params; |
727 | 0 | res->dh_sec_param = gnutls_pk_bits_to_sec_param( |
728 | 0 | GNUTLS_PK_DH, _gnutls_mpi_get_nbits(dh_params->params[0])); |
729 | 0 | } |
730 | | |
731 | | /** |
732 | | * gnutls_psk_set_server_known_dh_params: |
733 | | * @res: is a gnutls_psk_server_credentials_t type |
734 | | * @sec_param: is an option of the %gnutls_sec_param_t enumeration |
735 | | * |
736 | | * This function will set the Diffie-Hellman parameters for a |
737 | | * PSK server to use. These parameters will be used in |
738 | | * Ephemeral Diffie-Hellman cipher suites and will be selected from |
739 | | * the FFDHE set of RFC7919 according to the security level provided. |
740 | | * |
741 | | * Deprecated: This function is unnecessary and discouraged on GnuTLS 3.6.0 |
742 | | * or later. Since 3.6.0, DH parameters are negotiated |
743 | | * following RFC7919. |
744 | | * |
745 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
746 | | * negative error value. |
747 | | * |
748 | | * Since: 3.5.6 |
749 | | **/ |
750 | | int gnutls_psk_set_server_known_dh_params(gnutls_psk_server_credentials_t res, |
751 | | gnutls_sec_param_t sec_param) |
752 | 0 | { |
753 | 0 | res->dh_sec_param = sec_param; |
754 | |
|
755 | 0 | return 0; |
756 | 0 | } |
757 | | |
758 | | /** |
759 | | * gnutls_psk_set_server_params_function: |
760 | | * @res: is a #gnutls_certificate_credentials_t type |
761 | | * @func: is the function to be called |
762 | | * |
763 | | * This function will set a callback in order for the server to get |
764 | | * the Diffie-Hellman parameters for PSK authentication. The callback |
765 | | * should return %GNUTLS_E_SUCCESS (0) on success. |
766 | | * |
767 | | * Deprecated: This function is unnecessary and discouraged on GnuTLS 3.6.0 |
768 | | * or later. Since 3.6.0, DH parameters are negotiated |
769 | | * following RFC7919. |
770 | | * |
771 | | **/ |
772 | | void gnutls_psk_set_server_params_function(gnutls_psk_server_credentials_t res, |
773 | | gnutls_params_function *func) |
774 | 0 | { |
775 | 0 | res->params_func = func; |
776 | 0 | } |
777 | | |
778 | | /** |
779 | | * gnutls_psk_set_params_function: |
780 | | * @res: is a gnutls_psk_server_credentials_t type |
781 | | * @func: is the function to be called |
782 | | * |
783 | | * This function will set a callback in order for the server to get |
784 | | * the Diffie-Hellman or RSA parameters for PSK authentication. The |
785 | | * callback should return %GNUTLS_E_SUCCESS (0) on success. |
786 | | * |
787 | | * Deprecated: This function is unnecessary and discouraged on GnuTLS 3.6.0 |
788 | | * or later. Since 3.6.0, DH parameters are negotiated |
789 | | * following RFC7919. |
790 | | * |
791 | | **/ |
792 | | void gnutls_psk_set_params_function(gnutls_psk_server_credentials_t res, |
793 | | gnutls_params_function *func) |
794 | 0 | { |
795 | 0 | res->params_func = func; |
796 | 0 | } |
797 | | |
798 | | #endif /* ENABLE_PSK */ |