Coverage Report

Created: 2023-03-26 08:33

/src/gnutls/lib/auth/dhe_psk.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2005-2012 Free Software Foundation, Inc.
3
 * Copyright (C) 2017 Red Hat, Inc.
4
 *
5
 * Author: Nikos Mavrogiannopoulos
6
 *
7
 * This file is part of GnuTLS.
8
 *
9
 * The GnuTLS is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Lesser General Public License
11
 * as published by the Free Software Foundation; either version 2.1 of
12
 * the License, or (at your option) any later version.
13
 *
14
 * This library is distributed in the hope that it will be useful, but
15
 * WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 * Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public License
20
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
21
 *
22
 */
23
24
/* This file contains the PSK Diffie-Hellman key exchange part of the
25
 * PSK authentication.  The functions here are used in the handshake.
26
 */
27
28
#include "gnutls_int.h"
29
30
#ifdef ENABLE_PSK
31
32
/* Contains PSK code for DHE and ECDHE
33
 */
34
35
# include "auth.h"
36
# include "errors.h"
37
# include "dh.h"
38
# include <auth/psk.h>
39
# include "num.h"
40
# include "mpi.h"
41
# include <state.h>
42
# include <auth/dh_common.h>
43
# include <auth/ecdhe.h>
44
# include <datum.h>
45
# include <auth/psk_passwd.h>
46
47
static int
48
proc_ecdhe_psk_server_kx(gnutls_session_t session, uint8_t * data,
49
       size_t _data_size);
50
static int gen_dhe_psk_server_kx(gnutls_session_t, gnutls_buffer_st *);
51
static int gen_dhe_psk_client_kx(gnutls_session_t, gnutls_buffer_st *);
52
static int gen_ecdhe_psk_client_kx(gnutls_session_t, gnutls_buffer_st *);
53
static int proc_ecdhe_psk_client_kx(gnutls_session_t, uint8_t *, size_t);
54
static int proc_dhe_psk_server_kx(gnutls_session_t, uint8_t *, size_t);
55
static int gen_ecdhe_psk_server_kx(gnutls_session_t session,
56
           gnutls_buffer_st * data);
57
static int proc_dhe_psk_client_kx(gnutls_session_t session, uint8_t * data,
58
          size_t _data_size);
59
# ifdef ENABLE_DHE
60
const mod_auth_st dhe_psk_auth_struct = {
61
  "DHE PSK",
62
  NULL,
63
  NULL,
64
  gen_dhe_psk_server_kx,
65
  gen_dhe_psk_client_kx,
66
  NULL,
67
  NULL,
68
69
  NULL,
70
  NULL,     /* certificate */
71
  proc_dhe_psk_server_kx,
72
  proc_dhe_psk_client_kx,
73
  NULL,
74
  NULL
75
};
76
# endif
77
78
# ifdef ENABLE_ECDHE
79
const mod_auth_st ecdhe_psk_auth_struct = {
80
  "ECDHE PSK",
81
  NULL,
82
  NULL,
83
  gen_ecdhe_psk_server_kx,
84
  gen_ecdhe_psk_client_kx,
85
  NULL,
86
  NULL,
87
88
  NULL,
89
  NULL,     /* certificate */
90
  proc_ecdhe_psk_server_kx,
91
  proc_ecdhe_psk_client_kx,
92
  NULL,
93
  NULL
94
};
95
# endif
96
97
static int
98
gen_ecdhe_psk_client_kx(gnutls_session_t session, gnutls_buffer_st * data)
99
0
{
100
0
  int ret, free;
101
0
  gnutls_psk_client_credentials_t cred;
102
0
  gnutls_datum_t username, key;
103
0
  unsigned init_pos = data->length;
104
105
0
  cred = (gnutls_psk_client_credentials_t)
106
0
      _gnutls_get_cred(session, GNUTLS_CRD_PSK);
107
108
0
  if (cred == NULL)
109
0
    return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
110
111
0
  ret = _gnutls_find_psk_key(session, cred, &username, &key, &free);
112
0
  if (ret < 0)
113
0
    return gnutls_assert_val(ret);
114
115
0
  ret =
116
0
      _gnutls_buffer_append_data_prefix(data, 16, username.data,
117
0
                username.size);
118
0
  if (ret < 0) {
119
0
    gnutls_assert();
120
0
    goto cleanup;
121
0
  }
122
123
  /* The PSK key is set in there */
124
0
  ret = _gnutls_gen_ecdh_common_client_kx_int(session, data, &key);
125
0
  if (ret < 0) {
126
0
    gnutls_assert();
127
0
    goto cleanup;
128
0
  }
129
130
0
  ret = data->length - init_pos;
131
132
0
 cleanup:
133
0
  if (free) {
134
0
    _gnutls_free_datum(&username);
135
0
    _gnutls_free_temp_key_datum(&key);
136
0
  }
137
138
0
  return ret;
139
0
}
140
141
static int
142
gen_dhe_psk_client_kx(gnutls_session_t session, gnutls_buffer_st * data)
143
0
{
144
0
  int ret, free;
145
0
  gnutls_psk_client_credentials_t cred;
146
0
  gnutls_datum_t username, key;
147
0
  unsigned init_pos = data->length;
148
149
0
  cred = (gnutls_psk_client_credentials_t)
150
0
      _gnutls_get_cred(session, GNUTLS_CRD_PSK);
151
152
0
  if (cred == NULL)
153
0
    return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
154
155
0
  ret = _gnutls_find_psk_key(session, cred, &username, &key, &free);
156
0
  if (ret < 0)
157
0
    return gnutls_assert_val(ret);
158
159
0
  ret =
160
0
      _gnutls_buffer_append_data_prefix(data, 16, username.data,
161
0
                username.size);
162
0
  if (ret < 0) {
163
0
    gnutls_assert();
164
0
    goto cleanup;
165
0
  }
166
167
  /* The PSK key is set in there */
168
0
  ret = _gnutls_gen_dh_common_client_kx_int(session, data, &key);
169
0
  if (ret < 0) {
170
0
    gnutls_assert();
171
0
    goto cleanup;
172
0
  }
173
174
0
  ret = data->length - init_pos;
175
176
0
 cleanup:
177
0
  if (free) {
178
0
    _gnutls_free_datum(&username);
179
0
    _gnutls_free_temp_key_datum(&key);
180
0
  }
181
182
0
  return ret;
183
0
}
184
185
static int
186
gen_dhe_psk_server_kx(gnutls_session_t session, gnutls_buffer_st * data)
187
0
{
188
0
  int ret;
189
0
  gnutls_psk_server_credentials_t cred;
190
0
  gnutls_datum_t hint = { NULL, 0 };
191
192
0
  cred = (gnutls_psk_server_credentials_t)
193
0
      _gnutls_get_cred(session, GNUTLS_CRD_PSK);
194
0
  if (cred == NULL) {
195
0
    gnutls_assert();
196
0
    return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
197
0
  }
198
199
0
  if ((ret =
200
0
       _gnutls_auth_info_init(session, GNUTLS_CRD_PSK,
201
0
            sizeof(psk_auth_info_st), 1)) < 0) {
202
0
    gnutls_assert();
203
0
    return ret;
204
0
  }
205
206
0
  ret =
207
0
      _gnutls_figure_dh_params(session, cred->dh_params,
208
0
             cred->params_func, cred->dh_sec_param);
209
0
  if (ret < 0) {
210
0
    gnutls_assert();
211
0
    return ret;
212
0
  }
213
214
0
  if (cred->hint) {
215
0
    hint.data = (uint8_t *) cred->hint;
216
0
    hint.size = strlen(cred->hint);
217
0
  }
218
219
0
  ret = _gnutls_buffer_append_data_prefix(data, 16, hint.data, hint.size);
220
0
  if (ret < 0)
221
0
    return gnutls_assert_val(ret);
222
223
0
  ret = _gnutls_dh_common_print_server_kx(session, data);
224
0
  if (ret < 0)
225
0
    gnutls_assert();
226
227
0
  return ret;
228
0
}
229
230
static int
231
gen_ecdhe_psk_server_kx(gnutls_session_t session, gnutls_buffer_st * data)
232
0
{
233
0
  int ret;
234
0
  gnutls_psk_server_credentials_t cred;
235
0
  gnutls_datum_t hint = { NULL, 0 };
236
237
0
  if ((ret =
238
0
       _gnutls_auth_info_init(session, GNUTLS_CRD_PSK,
239
0
            sizeof(psk_auth_info_st), 1)) < 0) {
240
0
    gnutls_assert();
241
0
    return ret;
242
0
  }
243
244
0
  cred = (gnutls_psk_server_credentials_t)
245
0
      _gnutls_get_cred(session, GNUTLS_CRD_PSK);
246
247
0
  if (cred == NULL) {
248
0
    gnutls_assert();
249
0
    return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
250
0
  }
251
252
0
  if (cred->hint) {
253
0
    hint.data = (uint8_t *) cred->hint;
254
0
    hint.size = strlen(cred->hint);
255
0
  }
256
257
0
  ret = _gnutls_buffer_append_data_prefix(data, 16, hint.data, hint.size);
258
0
  if (ret < 0)
259
0
    return gnutls_assert_val(ret);
260
261
0
  ret = _gnutls_ecdh_common_print_server_kx(session, data,
262
0
              get_group(session));
263
0
  if (ret < 0)
264
0
    gnutls_assert();
265
266
0
  return ret;
267
0
}
268
269
static int
270
proc_dhe_psk_client_kx(gnutls_session_t session, uint8_t * data,
271
           size_t _data_size)
272
0
{
273
0
  int ret;
274
0
  gnutls_datum_t psk_key;
275
0
  gnutls_psk_server_credentials_t cred;
276
0
  psk_auth_info_t info;
277
0
  gnutls_datum_t username;
278
0
  ssize_t data_size = _data_size;
279
280
0
  cred = (gnutls_psk_server_credentials_t)
281
0
      _gnutls_get_cred(session, GNUTLS_CRD_PSK);
282
283
0
  if (cred == NULL) {
284
0
    gnutls_assert();
285
0
    return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
286
0
  }
287
288
0
  if ((ret =
289
0
       _gnutls_auth_info_init(session, GNUTLS_CRD_PSK,
290
0
            sizeof(psk_auth_info_st), 1)) < 0) {
291
0
    gnutls_assert();
292
0
    return ret;
293
0
  }
294
295
0
  DECR_LEN(data_size, 2);
296
0
  username.size = _gnutls_read_uint16(&data[0]);
297
298
0
  DECR_LEN(data_size, username.size);
299
300
0
  username.data = &data[2];
301
302
  /* copy the username to the auth info structures
303
   */
304
0
  info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
305
0
  if (info == NULL) {
306
0
    gnutls_assert();
307
0
    return GNUTLS_E_INTERNAL_ERROR;
308
0
  }
309
310
0
  if (username.size > MAX_USERNAME_SIZE) {
311
0
    gnutls_assert();
312
0
    return GNUTLS_E_ILLEGAL_SRP_USERNAME;
313
0
  }
314
315
0
  ret = _gnutls_copy_psk_username(info, username);
316
0
  if (ret < 0)
317
0
    return gnutls_assert_val(ret);
318
319
  /* Adjust the data */
320
0
  data += username.size + 2;
321
322
0
  ret =
323
0
      _gnutls_psk_pwd_find_entry(session, info->username,
324
0
               info->username_len, &psk_key);
325
0
  if (ret < 0)
326
0
    return gnutls_assert_val(ret);
327
328
0
  ret = _gnutls_proc_dh_common_client_kx(session, data, data_size,
329
0
                 &psk_key);
330
331
0
  _gnutls_free_key_datum(&psk_key);
332
333
0
  return ret;
334
335
0
}
336
337
static int
338
proc_ecdhe_psk_client_kx(gnutls_session_t session, uint8_t * data,
339
       size_t _data_size)
340
0
{
341
0
  int ret;
342
0
  gnutls_psk_server_credentials_t cred;
343
0
  gnutls_datum_t psk_key;
344
0
  psk_auth_info_t info;
345
0
  gnutls_datum_t username;
346
0
  ssize_t data_size = _data_size;
347
348
0
  cred = (gnutls_psk_server_credentials_t)
349
0
      _gnutls_get_cred(session, GNUTLS_CRD_PSK);
350
351
0
  if (cred == NULL) {
352
0
    gnutls_assert();
353
0
    return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
354
0
  }
355
356
0
  if ((ret =
357
0
       _gnutls_auth_info_init(session, GNUTLS_CRD_PSK,
358
0
            sizeof(psk_auth_info_st), 1)) < 0) {
359
0
    gnutls_assert();
360
0
    return ret;
361
0
  }
362
363
0
  DECR_LEN(data_size, 2);
364
0
  username.size = _gnutls_read_uint16(&data[0]);
365
366
0
  DECR_LEN(data_size, username.size);
367
368
0
  username.data = &data[2];
369
370
  /* copy the username to the auth info structures
371
   */
372
0
  info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
373
0
  if (info == NULL) {
374
0
    gnutls_assert();
375
0
    return GNUTLS_E_INTERNAL_ERROR;
376
0
  }
377
378
0
  if (username.size > MAX_USERNAME_SIZE) {
379
0
    gnutls_assert();
380
0
    return GNUTLS_E_ILLEGAL_SRP_USERNAME;
381
0
  }
382
383
0
  ret = _gnutls_copy_psk_username(info, username);
384
0
  if (ret < 0)
385
0
    return gnutls_assert_val(ret);
386
387
  /* Adjust the data */
388
0
  data += username.size + 2;
389
390
  /* should never fail. It will always return a key even if it is
391
   * a random one */
392
0
  ret =
393
0
      _gnutls_psk_pwd_find_entry(session, info->username,
394
0
               info->username_len, &psk_key);
395
0
  if (ret < 0)
396
0
    return gnutls_assert_val(ret);
397
398
0
  ret = _gnutls_proc_ecdh_common_client_kx(session, data, data_size,
399
0
             get_group(session), &psk_key);
400
401
0
  _gnutls_free_key_datum(&psk_key);
402
403
0
  return ret;
404
0
}
405
406
static int
407
proc_dhe_psk_server_kx(gnutls_session_t session, uint8_t * data,
408
           size_t _data_size)
409
0
{
410
411
0
  int ret;
412
0
  ssize_t data_size = _data_size;
413
0
  psk_auth_info_t info;
414
0
  gnutls_datum_t hint;
415
416
  /* set auth_info */
417
0
  if ((ret =
418
0
       _gnutls_auth_info_init(session, GNUTLS_CRD_PSK,
419
0
            sizeof(psk_auth_info_st), 1)) < 0) {
420
0
    gnutls_assert();
421
0
    return ret;
422
0
  }
423
424
0
  DECR_LEN(data_size, 2);
425
426
0
  hint.size = _gnutls_read_uint16(&data[0]);
427
0
  hint.data = &data[2];
428
429
0
  DECR_LEN(data_size, hint.size);
430
0
  data += 2 + hint.size;
431
432
0
  ret = _gnutls_proc_dh_common_server_kx(session, data, data_size);
433
0
  if (ret < 0) {
434
0
    gnutls_assert();
435
0
    return ret;
436
0
  }
437
438
0
  info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
439
0
  if (info == NULL)
440
0
    return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
441
442
0
  if (hint.size > MAX_USERNAME_SIZE)
443
0
    return gnutls_assert_val(GNUTLS_E_ILLEGAL_SRP_USERNAME);
444
445
0
  ret = _gnutls_copy_psk_hint(info, hint);
446
0
  if (ret < 0) {
447
0
    gnutls_assert();
448
0
    return ret;
449
0
  }
450
451
0
  return 0;
452
0
}
453
454
static int
455
proc_ecdhe_psk_server_kx(gnutls_session_t session, uint8_t * data,
456
       size_t _data_size)
457
0
{
458
459
0
  int ret;
460
0
  ssize_t data_size = _data_size;
461
0
  psk_auth_info_t info;
462
0
  gnutls_datum_t hint;
463
464
  /* set auth_info */
465
0
  if ((ret =
466
0
       _gnutls_auth_info_init(session, GNUTLS_CRD_PSK,
467
0
            sizeof(psk_auth_info_st), 1)) < 0) {
468
0
    gnutls_assert();
469
0
    return ret;
470
0
  }
471
472
0
  DECR_LEN(data_size, 2);
473
474
0
  hint.size = _gnutls_read_uint16(&data[0]);
475
0
  hint.data = &data[2];
476
477
0
  DECR_LEN(data_size, hint.size);
478
0
  data += 2 + hint.size;
479
480
0
  ret = _gnutls_proc_ecdh_common_server_kx(session, data, data_size);
481
0
  if (ret < 0) {
482
0
    gnutls_assert();
483
0
    return ret;
484
0
  }
485
486
0
  info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
487
0
  if (info == NULL)
488
0
    return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
489
490
0
  if (hint.size > MAX_USERNAME_SIZE)
491
0
    return gnutls_assert_val(GNUTLS_E_ILLEGAL_SRP_USERNAME);
492
493
0
  ret = _gnutls_copy_psk_hint(info, hint);
494
0
  if (ret < 0) {
495
0
    gnutls_assert();
496
0
    return ret;
497
0
  }
498
499
0
  return 0;
500
0
}
501
502
#endif        /* ENABLE_PSK */