Coverage Report

Created: 2023-03-26 08:33

/src/gnutls/lib/auth/dh_common.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2002-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
/* This file contains common stuff in Ephemeral Diffie-Hellman (DHE)
24
 * and Anonymous DH key exchange(DHA). These are used in the handshake
25
 * procedure of the certificate and anonymous authentication.
26
 */
27
28
#include "gnutls_int.h"
29
#include "auth.h"
30
#include "errors.h"
31
#include "dh.h"
32
#include "num.h"
33
#include "tls-sig.h"
34
#include <datum.h>
35
#include <x509.h>
36
#include <state.h>
37
#include <pk.h>
38
#include <auth/dh_common.h>
39
#include <algorithms.h>
40
#include <auth/psk.h>
41
42
#if defined(ENABLE_DHE) || defined(ENABLE_ANON)
43
44
/* Frees the dh_info_st structure.
45
 */
46
void _gnutls_free_dh_info(dh_info_st * dh)
47
0
{
48
0
  dh->secret_bits = 0;
49
0
  _gnutls_free_datum(&dh->prime);
50
0
  _gnutls_free_datum(&dh->generator);
51
0
  _gnutls_free_datum(&dh->public_key);
52
0
}
53
54
int
55
_gnutls_proc_dh_common_client_kx(gnutls_session_t session,
56
         uint8_t * data, size_t _data_size,
57
         gnutls_datum_t * psk_key)
58
0
{
59
0
  uint16_t n_Y;
60
0
  size_t _n_Y;
61
0
  int ret;
62
0
  ssize_t data_size = _data_size;
63
0
  gnutls_datum_t tmp_dh_key = { NULL, 0 };
64
0
  gnutls_pk_params_st peer_pub;
65
66
0
  gnutls_pk_params_init(&peer_pub);
67
68
0
  DECR_LEN(data_size, 2);
69
0
  n_Y = _gnutls_read_uint16(&data[0]);
70
0
  _n_Y = n_Y;
71
72
0
  DECR_LEN(data_size, n_Y);
73
74
0
  if (data_size != 0)
75
0
    return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
76
77
0
  if (_gnutls_mpi_init_scan_nz
78
0
      (&session->key.proto.tls12.dh.client_Y, &data[2], _n_Y)) {
79
0
    gnutls_assert();
80
0
    return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; /* most likely zero or illegal size */
81
0
  }
82
83
0
  _gnutls_dh_set_peer_public(session,
84
0
           session->key.proto.tls12.dh.client_Y);
85
86
0
  peer_pub.params[DH_Y] = session->key.proto.tls12.dh.client_Y;
87
88
  /* calculate the key after calculating the message */
89
0
  ret =
90
0
      _gnutls_pk_derive(GNUTLS_PK_DH, &tmp_dh_key,
91
0
            &session->key.proto.tls12.dh.params, &peer_pub);
92
0
  if (ret < 0) {
93
0
    gnutls_assert();
94
0
    goto error;
95
0
  }
96
97
0
  if (psk_key == NULL) {
98
0
    session->key.key.data = tmp_dh_key.data;
99
0
    session->key.key.size = tmp_dh_key.size;
100
0
  } else {   /* In DHE_PSK the key is set differently */
101
0
    ret =
102
0
        _gnutls_set_psk_session_key(session, psk_key, &tmp_dh_key);
103
0
    _gnutls_free_temp_key_datum(&tmp_dh_key);
104
0
  }
105
106
0
  if (ret < 0) {
107
0
    gnutls_assert();
108
0
    goto error;
109
0
  }
110
111
0
  ret = 0;
112
0
 error:
113
0
  _gnutls_mpi_release(&session->key.proto.tls12.dh.client_Y);
114
0
  gnutls_pk_params_clear(&session->key.proto.tls12.dh.params);
115
116
0
  return ret;
117
0
}
118
119
int _gnutls_gen_dh_common_client_kx(gnutls_session_t session,
120
            gnutls_buffer_st * data)
121
0
{
122
0
  return _gnutls_gen_dh_common_client_kx_int(session, data, NULL);
123
0
}
124
125
int
126
_gnutls_gen_dh_common_client_kx_int(gnutls_session_t session,
127
            gnutls_buffer_st * data,
128
            gnutls_datum_t * pskkey)
129
0
{
130
0
  int ret;
131
0
  gnutls_pk_params_st peer_pub;
132
0
  gnutls_datum_t tmp_dh_key = { NULL, 0 };
133
0
  unsigned init_pos = data->length;
134
135
0
  gnutls_pk_params_init(&peer_pub);
136
137
0
  ret =
138
0
      _gnutls_pk_generate_keys(GNUTLS_PK_DH, 0,
139
0
             &session->key.proto.tls12.dh.params, 1);
140
0
  if (ret < 0)
141
0
    return gnutls_assert_val(ret);
142
143
0
  _gnutls_dh_set_secret_bits(session,
144
0
           _gnutls_mpi_get_nbits(session->key.
145
0
               proto.tls12.dh.
146
0
               params.params[DH_X]));
147
148
0
  ret =
149
0
      _gnutls_buffer_append_mpi(data, 16,
150
0
              session->key.proto.tls12.dh.
151
0
              params.params[DH_Y], 0);
152
0
  if (ret < 0) {
153
0
    gnutls_assert();
154
0
    goto error;
155
0
  }
156
157
0
  peer_pub.params[DH_Y] = session->key.proto.tls12.dh.client_Y;
158
159
  /* calculate the key after calculating the message */
160
0
  ret =
161
0
      _gnutls_pk_derive(GNUTLS_PK_DH, &tmp_dh_key,
162
0
            &session->key.proto.tls12.dh.params, &peer_pub);
163
0
  if (ret < 0) {
164
0
    gnutls_assert();
165
0
    goto error;
166
0
  }
167
168
0
  if (session->security_parameters.cs->kx_algorithm != GNUTLS_KX_DHE_PSK) {
169
0
    session->key.key.data = tmp_dh_key.data;
170
0
    session->key.key.size = tmp_dh_key.size;
171
0
  } else {   /* In DHE_PSK the key is set differently */
172
0
    ret = _gnutls_set_psk_session_key(session, pskkey, &tmp_dh_key);
173
0
    _gnutls_free_temp_key_datum(&tmp_dh_key);
174
0
  }
175
176
0
  if (ret < 0) {
177
0
    gnutls_assert();
178
0
    goto error;
179
0
  }
180
181
0
  ret = data->length - init_pos;
182
183
0
 error:
184
0
  gnutls_pk_params_clear(&session->key.proto.tls12.dh.params);
185
0
  return ret;
186
0
}
187
188
/* Returns the bytes parsed */
189
int
190
_gnutls_proc_dh_common_server_kx(gnutls_session_t session,
191
         uint8_t * data, size_t _data_size)
192
0
{
193
0
  uint16_t n_Y, n_g, n_p;
194
0
  size_t _n_Y, _n_g, _n_p, _n_q;
195
0
  uint8_t *data_p;
196
0
  uint8_t *data_g;
197
0
  uint8_t *data_Y;
198
0
  uint8_t *data_q = NULL;
199
0
  int i, bits, ret, p_bits;
200
0
  unsigned j;
201
0
  ssize_t data_size = _data_size;
202
203
  /* just in case we are resuming a session */
204
0
  gnutls_pk_params_release(&session->key.proto.tls12.dh.params);
205
206
0
  gnutls_pk_params_init(&session->key.proto.tls12.dh.params);
207
208
0
  i = 0;
209
210
0
  DECR_LEN(data_size, 2);
211
0
  n_p = _gnutls_read_uint16(&data[i]);
212
0
  i += 2;
213
214
0
  DECR_LEN(data_size, n_p);
215
0
  data_p = &data[i];
216
0
  i += n_p;
217
218
0
  DECR_LEN(data_size, 2);
219
0
  n_g = _gnutls_read_uint16(&data[i]);
220
0
  i += 2;
221
222
0
  DECR_LEN(data_size, n_g);
223
0
  data_g = &data[i];
224
0
  i += n_g;
225
226
0
  DECR_LEN(data_size, 2);
227
0
  n_Y = _gnutls_read_uint16(&data[i]);
228
0
  i += 2;
229
230
0
  DECR_LEN(data_size, n_Y);
231
0
  data_Y = &data[i];
232
233
0
  _n_Y = n_Y;
234
0
  _n_g = n_g;
235
0
  _n_p = n_p;
236
237
0
  if (_gnutls_mpi_init_scan_nz
238
0
      (&session->key.proto.tls12.dh.client_Y, data_Y, _n_Y) != 0) {
239
0
    gnutls_assert();
240
0
    return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
241
0
  }
242
243
  /* if we are doing RFC7919 */
244
0
  if (session->internals.priorities->groups.have_ffdhe != 0) {
245
    /* verify whether the received parameters match the advertised, otherwise
246
     * log that. */
247
0
    for (j = 0; j < session->internals.priorities->groups.size; j++) {
248
0
      if (session->internals.priorities->groups.
249
0
          entry[j]->generator
250
0
          && session->internals.priorities->groups.
251
0
          entry[j]->generator->size == n_g
252
0
          && session->internals.priorities->groups.
253
0
          entry[j]->prime->size == n_p
254
0
          && memcmp(session->internals.priorities->
255
0
              groups.entry[j]->generator->data, data_g,
256
0
              n_g) == 0
257
0
          && memcmp(session->internals.priorities->
258
0
              groups.entry[j]->prime->data, data_p,
259
0
              n_p) == 0) {
260
261
0
        session->internals.hsk_flags |= HSK_USED_FFDHE;
262
0
        _gnutls_session_group_set(session,
263
0
                session->
264
0
                internals.priorities->
265
0
                groups.entry[j]);
266
0
        session->key.proto.tls12.dh.params.qbits =
267
0
            *session->internals.priorities->
268
0
            groups.entry[j]->q_bits;
269
0
        data_q =
270
0
            session->internals.priorities->
271
0
            groups.entry[j]->q->data;
272
0
        _n_q =
273
0
            session->internals.priorities->
274
0
            groups.entry[j]->q->size;
275
0
        break;
276
0
      }
277
0
    }
278
279
0
    if (!(session->internals.hsk_flags & HSK_USED_FFDHE)) {
280
0
      _gnutls_audit_log(session,
281
0
            "FFDHE groups advertised, but server didn't support it; falling back to server's choice\n");
282
0
    }
283
0
  }
284
# ifdef ENABLE_FIPS140
285
  if (gnutls_fips140_mode_enabled() &&
286
      !_gnutls_dh_prime_match_fips_approved(data_p, n_p, data_g, n_g,
287
              NULL, NULL)) {
288
    gnutls_assert();
289
    return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
290
  }
291
# endif
292
293
0
  if (_gnutls_mpi_init_scan_nz
294
0
      (&session->key.proto.tls12.dh.params.params[DH_G], data_g,
295
0
       _n_g) != 0) {
296
0
    gnutls_assert();
297
0
    return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
298
0
  }
299
300
0
  if (_gnutls_mpi_init_scan_nz
301
0
      (&session->key.proto.tls12.dh.params.params[DH_P], data_p,
302
0
       _n_p) != 0) {
303
0
    gnutls_assert();
304
    /* we release now because session->key.proto.tls12.dh.params.params_nr is not yet set */
305
0
    _gnutls_mpi_release(&session->key.proto.tls12.dh.
306
0
            params.params[DH_G]);
307
0
    return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
308
0
  }
309
0
  if (data_q
310
0
      && _gnutls_mpi_init_scan_nz(&session->key.proto.tls12.dh.
311
0
          params.params[DH_Q], data_q,
312
0
          _n_q) != 0) {
313
    /* we release now because params_nr is not yet set */
314
0
    _gnutls_mpi_release(&session->key.proto.tls12.dh.
315
0
            params.params[DH_P]);
316
0
    _gnutls_mpi_release(&session->key.proto.tls12.dh.
317
0
            params.params[DH_G]);
318
0
    return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
319
0
  }
320
321
  /* include, possibly empty, q */
322
0
  session->key.proto.tls12.dh.params.params_nr = 3;
323
0
  session->key.proto.tls12.dh.params.algo = GNUTLS_PK_DH;
324
325
0
  if (!(session->internals.hsk_flags & HSK_USED_FFDHE)) {
326
0
    bits = _gnutls_dh_get_min_prime_bits(session);
327
0
    if (bits < 0) {
328
0
      gnutls_assert();
329
0
      return bits;
330
0
    }
331
332
0
    p_bits =
333
0
        _gnutls_mpi_get_nbits(session->key.proto.tls12.dh.
334
0
            params.params[DH_P]);
335
0
    if (p_bits < bits) {
336
      /* the prime used by the peer is not acceptable
337
       */
338
0
      gnutls_assert();
339
0
      _gnutls_debug_log
340
0
          ("Received a prime of %u bits, limit is %u\n",
341
0
           (unsigned)_gnutls_mpi_get_nbits(session->key.
342
0
                   proto.tls12.dh.
343
0
                   params.params
344
0
                   [DH_P]),
345
0
           (unsigned)bits);
346
0
      return GNUTLS_E_DH_PRIME_UNACCEPTABLE;
347
0
    }
348
349
0
    if (p_bits >= DEFAULT_MAX_VERIFY_BITS) {
350
0
      gnutls_assert();
351
0
      _gnutls_debug_log
352
0
          ("Received a prime of %u bits, limit is %u\n",
353
0
           (unsigned)p_bits,
354
0
           (unsigned)DEFAULT_MAX_VERIFY_BITS);
355
0
      return GNUTLS_E_DH_PRIME_UNACCEPTABLE;
356
0
    }
357
0
  }
358
359
0
  _gnutls_dh_save_group(session,
360
0
            session->key.proto.tls12.dh.params.params[DH_G],
361
0
            session->key.proto.tls12.dh.params.params[DH_P]);
362
0
  _gnutls_dh_set_peer_public(session,
363
0
           session->key.proto.tls12.dh.client_Y);
364
365
0
  ret = n_Y + n_p + n_g + 6;
366
367
0
  return ret;
368
0
}
369
370
int
371
_gnutls_dh_common_print_server_kx(gnutls_session_t session,
372
          gnutls_buffer_st * data)
373
0
{
374
0
  int ret;
375
0
  unsigned q_bits = session->key.proto.tls12.dh.params.qbits;
376
0
  unsigned init_pos = data->length;
377
378
0
  if (q_bits < 192 && q_bits != 0) {
379
0
    gnutls_assert();
380
0
    _gnutls_debug_log("too small q_bits value for DH: %u\n",
381
0
          q_bits);
382
0
    q_bits = 0; /* auto-detect */
383
0
  }
384
385
  /* Y=g^x mod p */
386
0
  ret =
387
0
      _gnutls_pk_generate_keys(GNUTLS_PK_DH, q_bits,
388
0
             &session->key.proto.tls12.dh.params, 1);
389
0
  if (ret < 0)
390
0
    return gnutls_assert_val(ret);
391
392
0
  _gnutls_dh_set_secret_bits(session,
393
0
           _gnutls_mpi_get_nbits(session->key.
394
0
               proto.tls12.dh.
395
0
               params.params[DH_X]));
396
397
0
  ret =
398
0
      _gnutls_buffer_append_mpi(data, 16,
399
0
              session->key.proto.tls12.dh.
400
0
              params.params[DH_P], 0);
401
0
  if (ret < 0) {
402
0
    gnutls_assert();
403
0
    goto cleanup;
404
0
  }
405
406
0
  ret =
407
0
      _gnutls_buffer_append_mpi(data, 16,
408
0
              session->key.proto.tls12.dh.
409
0
              params.params[DH_G], 0);
410
0
  if (ret < 0) {
411
0
    gnutls_assert();
412
0
    goto cleanup;
413
0
  }
414
415
0
  ret =
416
0
      _gnutls_buffer_append_mpi(data, 16,
417
0
              session->key.proto.tls12.dh.
418
0
              params.params[DH_Y], 0);
419
0
  if (ret < 0) {
420
0
    gnutls_assert();
421
0
    goto cleanup;
422
0
  }
423
424
0
  ret = data->length - init_pos;
425
426
0
 cleanup:
427
0
  return ret;
428
0
}
429
430
#endif