Coverage Report

Created: 2025-11-16 07:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gnutls/lib/ext/key_share.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2017 Red Hat, 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 the code the Key Share TLS 1.3 extension.
24
 */
25
26
#include "gnutls_int.h"
27
#include "errors.h"
28
#include "num.h"
29
#include "ext/supported_groups.h"
30
#include "state.h"
31
#include "num.h"
32
#include "algorithms.h"
33
#include "auth/psk.h"
34
#include "auth/cert.h"
35
#include "handshake.h"
36
#include "../ecc.h"
37
#include "../algorithms.h"
38
#include "pk.h"
39
#include "audit.h"
40
41
static int key_share_recv_params(gnutls_session_t session, const uint8_t *data,
42
         size_t data_size);
43
static int key_share_send_params(gnutls_session_t session,
44
         gnutls_buffer_st *extdata);
45
46
const hello_ext_entry_st ext_mod_key_share = {
47
  .name = "Key Share",
48
  .tls_id = 51,
49
  .gid = GNUTLS_EXTENSION_KEY_SHARE,
50
  .client_parse_point = _GNUTLS_EXT_TLS_POST_CS,
51
  .server_parse_point = _GNUTLS_EXT_TLS_POST_CS,
52
  .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_CLIENT_HELLO |
53
        GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO | GNUTLS_EXT_FLAG_HRR,
54
  .recv_func = key_share_recv_params,
55
  .send_func = key_share_send_params,
56
  .pack_func = NULL,
57
  .unpack_func = NULL,
58
  .deinit_func = NULL,
59
  .cannot_be_overriden = 1
60
};
61
62
static int client_gen_key_share_single(gnutls_session_t session,
63
               const gnutls_group_entry_st *group,
64
               gnutls_buffer_st *extdata)
65
0
{
66
0
  gnutls_datum_t tmp = { NULL, 0 };
67
0
  int ret;
68
69
0
  switch (group->pk) {
70
0
  case GNUTLS_PK_EC:
71
0
    gnutls_pk_params_release(&session->key.kshare.ecdh_params);
72
0
    gnutls_pk_params_init(&session->key.kshare.ecdh_params);
73
74
0
    ret = _gnutls_pk_generate_keys(group->pk, group->curve,
75
0
                 &session->key.kshare.ecdh_params,
76
0
                 1);
77
0
    if (ret < 0) {
78
0
      gnutls_assert();
79
0
      goto cleanup;
80
0
    }
81
82
0
    ret = _gnutls_ecc_ansi_x962_export(
83
0
      group->curve,
84
0
      session->key.kshare.ecdh_params.params[ECC_X],
85
0
      session->key.kshare.ecdh_params.params[ECC_Y], &tmp);
86
0
    if (ret < 0)
87
0
      return gnutls_assert_val(ret);
88
89
0
    ret = gnutls_buffer_append_data(extdata, tmp.data, tmp.size);
90
0
    if (ret < 0) {
91
0
      gnutls_assert();
92
0
      goto cleanup;
93
0
    }
94
95
0
    session->key.kshare.ecdh_params.algo = group->pk;
96
0
    session->key.kshare.ecdh_params.curve = group->curve;
97
98
0
    ret = 0;
99
0
    break;
100
101
0
  case GNUTLS_PK_ECDH_X25519:
102
0
  case GNUTLS_PK_ECDH_X448:
103
0
    gnutls_pk_params_release(&session->key.kshare.ecdhx_params);
104
0
    gnutls_pk_params_init(&session->key.kshare.ecdhx_params);
105
106
0
    ret = _gnutls_pk_generate_keys(
107
0
      group->pk, group->curve,
108
0
      &session->key.kshare.ecdhx_params, 1);
109
0
    if (ret < 0) {
110
0
      gnutls_assert();
111
0
      goto cleanup;
112
0
    }
113
114
0
    ret = gnutls_buffer_append_data(
115
0
      extdata, session->key.kshare.ecdhx_params.raw_pub.data,
116
0
      session->key.kshare.ecdhx_params.raw_pub.size);
117
0
    if (ret < 0) {
118
0
      gnutls_assert();
119
0
      goto cleanup;
120
0
    }
121
122
0
    session->key.kshare.ecdhx_params.algo = group->pk;
123
0
    session->key.kshare.ecdhx_params.curve = group->curve;
124
125
0
    ret = 0;
126
0
    break;
127
128
0
  case GNUTLS_PK_DH:
129
    /* we need to initialize the group parameters first */
130
0
    gnutls_pk_params_release(&session->key.kshare.dh_params);
131
0
    gnutls_pk_params_init(&session->key.kshare.dh_params);
132
133
0
    ret = _gnutls_mpi_init_scan_nz(
134
0
      &session->key.kshare.dh_params.params[DH_G],
135
0
      group->generator->data, group->generator->size);
136
0
    if (ret < 0) {
137
0
      ret = gnutls_assert_val(
138
0
        GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
139
0
      goto cleanup;
140
0
    }
141
142
0
    ret = _gnutls_mpi_init_scan_nz(
143
0
      &session->key.kshare.dh_params.params[DH_P],
144
0
      group->prime->data, group->prime->size);
145
0
    if (ret < 0) {
146
0
      ret = gnutls_assert_val(
147
0
        GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
148
0
      goto cleanup;
149
0
    }
150
151
0
    ret = _gnutls_mpi_init_scan_nz(
152
0
      &session->key.kshare.dh_params.params[DH_Q],
153
0
      group->q->data, group->q->size);
154
0
    if (ret < 0) {
155
0
      ret = gnutls_assert_val(
156
0
        GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
157
0
      goto cleanup;
158
0
    }
159
160
0
    session->key.kshare.dh_params.algo = group->pk;
161
0
    session->key.kshare.dh_params.dh_group =
162
0
      group->id; /* no curve in FFDH, we write the group */
163
0
    session->key.kshare.dh_params.qbits = *group->q_bits;
164
0
    session->key.kshare.dh_params.params_nr = 3;
165
166
0
    ret = _gnutls_pk_generate_keys(
167
0
      group->pk, 0, &session->key.kshare.dh_params, 1);
168
0
    if (ret < 0) {
169
0
      ret = gnutls_assert_val(ret);
170
0
      goto cleanup;
171
0
    }
172
173
0
    ret = _gnutls_buffer_append_fixed_mpi(
174
0
      extdata, session->key.kshare.dh_params.params[DH_Y],
175
0
      group->prime->size);
176
0
    if (ret < 0) {
177
0
      ret = gnutls_assert_val(ret);
178
0
      goto cleanup;
179
0
    }
180
181
0
    ret = 0;
182
0
    break;
183
184
0
  case GNUTLS_PK_MLKEM768:
185
0
  case GNUTLS_PK_MLKEM1024:
186
0
  case GNUTLS_PK_EXP_KYBER768:
187
0
    gnutls_pk_params_release(&session->key.kshare.kem_params);
188
0
    gnutls_pk_params_init(&session->key.kshare.kem_params);
189
190
0
    ret = _gnutls_pk_generate_keys(
191
0
      group->pk, 0, &session->key.kshare.kem_params, 1);
192
0
    if (ret < 0) {
193
0
      gnutls_assert();
194
0
      goto cleanup;
195
0
    }
196
197
0
    ret = gnutls_buffer_append_data(
198
0
      extdata, session->key.kshare.kem_params.raw_pub.data,
199
0
      session->key.kshare.kem_params.raw_pub.size);
200
0
    if (ret < 0) {
201
0
      gnutls_assert();
202
0
      goto cleanup;
203
0
    }
204
205
0
    ret = 0;
206
0
    break;
207
208
0
  default:
209
0
    _gnutls_debug_log("Cannot send key share for group %s!\n",
210
0
          group->name);
211
0
    return GNUTLS_E_INT_RET_0;
212
0
  }
213
214
0
cleanup:
215
0
  gnutls_free(tmp.data);
216
0
  return ret;
217
0
}
218
219
/*
220
 * Generates key exchange parameters, and stores them in
221
 * session->key.kshare_*_params.
222
 *
223
 * struct {
224
 *     NamedGroup group;
225
 *     opaque key_exchange<1..2^16-1>;
226
 * } KeyShareEntry;
227
 *
228
 */
229
static int client_gen_key_share(gnutls_session_t session,
230
        const gnutls_group_entry_st *group,
231
        gnutls_buffer_st *extdata)
232
0
{
233
0
  unsigned int length_pos;
234
0
  const gnutls_group_entry_st *groups[MAX_HYBRID_GROUPS + 1] = {
235
0
    NULL,
236
0
  };
237
0
  int ret;
238
239
0
  _gnutls_handshake_log("EXT[%p]: sending key share for %s\n", session,
240
0
            group->name);
241
242
0
  ret = _gnutls_buffer_append_prefix(extdata, 16, group->tls_id);
243
0
  if (ret < 0)
244
0
    return gnutls_assert_val(ret);
245
246
  /* save the position of length field */
247
0
  length_pos = extdata->length;
248
0
  ret = _gnutls_buffer_append_prefix(extdata, 16, 0);
249
0
  if (ret < 0)
250
0
    return gnutls_assert_val(ret);
251
252
0
  ret = _gnutls_group_expand(group, groups);
253
0
  if (ret < 0)
254
0
    return gnutls_assert_val(ret);
255
256
0
  _gnutls_audit_new_context_with_data("name", CRAU_STRING,
257
0
              "tls::key_exchange", "tls::group",
258
0
              CRAU_WORD, group->tls_id, NULL);
259
260
0
  for (size_t i = 0; groups[i]; i++) {
261
0
    ret = client_gen_key_share_single(session, groups[i], extdata);
262
0
    if (ret < 0)
263
0
      return gnutls_assert_val(ret);
264
0
  }
265
266
0
  gnutls_audit_pop_context();
267
268
  /* copy actual length */
269
0
  _gnutls_write_uint16(extdata->length - length_pos - 2,
270
0
           &extdata->data[length_pos]);
271
272
0
  return 0;
273
0
}
274
275
static int server_gen_key_share_single(gnutls_session_t session,
276
               const gnutls_group_entry_st *group,
277
               gnutls_buffer_st *extdata)
278
0
{
279
0
  gnutls_datum_t tmp = { NULL, 0 };
280
0
  int ret;
281
282
0
  switch (group->pk) {
283
0
  case GNUTLS_PK_EC:
284
0
    ret = _gnutls_ecc_ansi_x962_export(
285
0
      group->curve,
286
0
      session->key.kshare.ecdh_params.params[ECC_X],
287
0
      session->key.kshare.ecdh_params.params[ECC_Y], &tmp);
288
0
    if (ret < 0) {
289
0
      gnutls_assert();
290
0
      goto cleanup;
291
0
    }
292
293
0
    ret = gnutls_buffer_append_data(extdata, tmp.data, tmp.size);
294
0
    if (ret < 0) {
295
0
      gnutls_assert();
296
0
      goto cleanup;
297
0
    }
298
299
0
    ret = 0;
300
0
    break;
301
302
0
  case GNUTLS_PK_ECDH_X25519:
303
0
  case GNUTLS_PK_ECDH_X448:
304
0
    ret = gnutls_buffer_append_data(
305
0
      extdata, session->key.kshare.ecdhx_params.raw_pub.data,
306
0
      session->key.kshare.ecdhx_params.raw_pub.size);
307
0
    if (ret < 0) {
308
0
      gnutls_assert();
309
0
      goto cleanup;
310
0
    }
311
312
0
    ret = 0;
313
0
    break;
314
315
0
  case GNUTLS_PK_DH:
316
0
    ret = _gnutls_buffer_append_fixed_mpi(
317
0
      extdata, session->key.kshare.dh_params.params[DH_Y],
318
0
      group->prime->size);
319
0
    if (ret < 0) {
320
0
      gnutls_assert();
321
0
      goto cleanup;
322
0
    }
323
324
0
    ret = 0;
325
0
    break;
326
327
0
  case GNUTLS_PK_MLKEM768:
328
0
  case GNUTLS_PK_MLKEM1024:
329
0
  case GNUTLS_PK_EXP_KYBER768:
330
0
    ret = gnutls_buffer_append_data(
331
0
      extdata, session->key.kshare.kem_params.raw_pub.data,
332
0
      session->key.kshare.kem_params.raw_pub.size);
333
0
    if (ret < 0) {
334
0
      gnutls_assert();
335
0
      goto cleanup;
336
0
    }
337
338
0
    ret = 0;
339
0
    break;
340
341
0
  default:
342
0
    _gnutls_debug_log("Cannot send key share for group %s!\n",
343
0
          group->name);
344
0
    return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
345
0
  }
346
347
0
cleanup:
348
0
  gnutls_free(tmp.data);
349
0
  return ret;
350
0
}
351
352
/*
353
 * Sends server key exchange parameters
354
 *
355
 */
356
static int server_gen_key_share(gnutls_session_t session,
357
        const gnutls_group_entry_st *group,
358
        gnutls_buffer_st *extdata)
359
0
{
360
0
  unsigned int length_pos;
361
0
  const gnutls_group_entry_st *groups[MAX_HYBRID_GROUPS + 1] = {
362
0
    NULL,
363
0
  };
364
0
  int ret;
365
366
0
  _gnutls_handshake_log("EXT[%p]: sending key share for %s\n", session,
367
0
            group->name);
368
369
0
  ret = _gnutls_buffer_append_prefix(extdata, 16, group->tls_id);
370
0
  if (ret < 0)
371
0
    return gnutls_assert_val(ret);
372
373
  /* save the position of length field */
374
0
  length_pos = extdata->length;
375
0
  ret = _gnutls_buffer_append_prefix(extdata, 16, 0);
376
0
  if (ret < 0)
377
0
    return gnutls_assert_val(ret);
378
379
0
  ret = _gnutls_group_expand(group, groups);
380
0
  if (ret < 0)
381
0
    return gnutls_assert_val(ret);
382
383
0
  _gnutls_audit_new_context_with_data("name", CRAU_STRING,
384
0
              "tls::key_exchange", "tls::group",
385
0
              CRAU_WORD, group->tls_id, NULL);
386
387
0
  for (size_t i = 0; groups[i]; i++) {
388
0
    ret = server_gen_key_share_single(session, groups[i], extdata);
389
0
    if (ret < 0)
390
0
      return gnutls_assert_val(ret);
391
0
  }
392
393
0
  gnutls_audit_pop_context();
394
395
  /* copy actual length */
396
0
  _gnutls_write_uint16(extdata->length - length_pos - 2,
397
0
           &extdata->data[length_pos]);
398
399
0
  return 0;
400
0
}
401
402
static int append_key_datum(gnutls_datum_t *dst, const gnutls_datum_t *src)
403
0
{
404
0
  dst->data = gnutls_realloc_fast(dst->data, dst->size + src->size);
405
0
  if (!dst->data)
406
0
    return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
407
408
0
  memcpy(dst->data + dst->size, src->data, src->size);
409
0
  dst->size += src->size;
410
0
  return 0;
411
0
}
412
413
static int server_use_key_share_single(gnutls_session_t session,
414
               const gnutls_group_entry_st *group,
415
               gnutls_buffer_st *buffer)
416
0
{
417
0
  gnutls_datum_t key = { NULL, 0 };
418
0
  gnutls_datum_t data;
419
0
  gnutls_pk_params_st pub;
420
0
  const gnutls_ecc_curve_entry_st *curve;
421
0
  int ret;
422
423
0
  switch (group->pk) {
424
0
  case GNUTLS_PK_EC:
425
0
    gnutls_pk_params_release(&session->key.kshare.ecdh_params);
426
0
    gnutls_pk_params_init(&session->key.kshare.ecdh_params);
427
428
0
    curve = _gnutls_ecc_curve_get_params(group->curve);
429
430
0
    gnutls_pk_params_init(&pub);
431
432
0
    if (curve->size * 2 + 1 > buffer->length)
433
0
      return gnutls_assert_val(
434
0
        GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
435
0
    _gnutls_buffer_pop_datum(buffer, &data, curve->size * 2 + 1);
436
437
    /* generate our key */
438
0
    ret = _gnutls_pk_generate_keys(curve->pk, curve->id,
439
0
                 &session->key.kshare.ecdh_params,
440
0
                 1);
441
0
    if (ret < 0)
442
0
      return gnutls_assert_val(ret);
443
444
    /* read the public key */
445
0
    ret = _gnutls_ecc_ansi_x962_import(data.data, data.size,
446
0
               &pub.params[ECC_X],
447
0
               &pub.params[ECC_Y]);
448
0
    if (ret < 0)
449
0
      return gnutls_assert_val(
450
0
        GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
451
452
0
    pub.algo = group->pk;
453
0
    pub.curve = curve->id;
454
0
    pub.params_nr = 2;
455
456
    /* generate shared */
457
0
    ret = _gnutls_pk_derive_tls13(curve->pk, &key,
458
0
                &session->key.kshare.ecdh_params,
459
0
                &pub);
460
0
    gnutls_pk_params_release(&pub);
461
0
    if (ret < 0)
462
0
      return gnutls_assert_val(ret);
463
464
0
    ret = append_key_datum(&session->key.key, &key);
465
0
    _gnutls_free_datum(&key);
466
0
    if (ret < 0)
467
0
      return gnutls_assert_val(ret);
468
469
0
    return 0;
470
471
0
  case GNUTLS_PK_ECDH_X25519:
472
0
  case GNUTLS_PK_ECDH_X448:
473
0
    gnutls_pk_params_release(&session->key.kshare.ecdhx_params);
474
0
    gnutls_pk_params_init(&session->key.kshare.ecdhx_params);
475
476
0
    curve = _gnutls_ecc_curve_get_params(group->curve);
477
478
0
    if (curve->size > buffer->length)
479
0
      return gnutls_assert_val(
480
0
        GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
481
0
    _gnutls_buffer_pop_datum(buffer, &data, curve->size);
482
483
    /* generate our key */
484
0
    ret = _gnutls_pk_generate_keys(
485
0
      curve->pk, curve->id, &session->key.kshare.ecdhx_params,
486
0
      1);
487
0
    if (ret < 0)
488
0
      return gnutls_assert_val(ret);
489
490
    /* read the public key and generate shared */
491
0
    gnutls_pk_params_init(&pub);
492
493
0
    pub.algo = group->pk;
494
0
    pub.curve = curve->id;
495
496
0
    pub.raw_pub.data = data.data;
497
0
    pub.raw_pub.size = data.size;
498
499
    /* We don't mask the MSB in the final byte as required
500
     * by RFC7748. This will be done internally by nettle 3.3 or later.
501
     */
502
0
    ret = _gnutls_pk_derive_tls13(curve->pk, &key,
503
0
                &session->key.kshare.ecdhx_params,
504
0
                &pub);
505
0
    if (ret < 0)
506
0
      return gnutls_assert_val(ret);
507
508
0
    ret = append_key_datum(&session->key.key, &key);
509
0
    _gnutls_free_datum(&key);
510
0
    if (ret < 0)
511
0
      return gnutls_assert_val(ret);
512
513
0
    return 0;
514
515
0
  case GNUTLS_PK_DH:
516
    /* we need to initialize the group parameters first */
517
0
    gnutls_pk_params_release(&session->key.kshare.dh_params);
518
0
    gnutls_pk_params_init(&session->key.kshare.dh_params);
519
520
0
    if (group->prime->size > buffer->length)
521
0
      return gnutls_assert_val(
522
0
        GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
523
0
    _gnutls_buffer_pop_datum(buffer, &data, group->prime->size);
524
525
    /* set group params */
526
0
    ret = _gnutls_mpi_init_scan_nz(
527
0
      &session->key.kshare.dh_params.params[DH_G],
528
0
      group->generator->data, group->generator->size);
529
0
    if (ret < 0)
530
0
      return gnutls_assert_val(
531
0
        GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
532
533
0
    ret = _gnutls_mpi_init_scan_nz(
534
0
      &session->key.kshare.dh_params.params[DH_P],
535
0
      group->prime->data, group->prime->size);
536
0
    if (ret < 0)
537
0
      return gnutls_assert_val(
538
0
        GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
539
540
0
    ret = _gnutls_mpi_init_scan_nz(
541
0
      &session->key.kshare.dh_params.params[DH_Q],
542
0
      group->q->data, group->q->size);
543
0
    if (ret < 0)
544
0
      return gnutls_assert_val(
545
0
        GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
546
547
0
    session->key.kshare.dh_params.algo = GNUTLS_PK_DH;
548
0
    session->key.kshare.dh_params.qbits = *group->q_bits;
549
0
    session->key.kshare.dh_params.params_nr = 3;
550
551
    /* generate our keys */
552
0
    ret = _gnutls_pk_generate_keys(
553
0
      group->pk, 0, &session->key.kshare.dh_params, 1);
554
0
    if (ret < 0)
555
0
      return gnutls_assert_val(ret);
556
557
    /* read the public key and generate shared */
558
0
    gnutls_pk_params_init(&pub);
559
560
0
    ret = _gnutls_mpi_init_scan_nz(&pub.params[DH_Y], data.data,
561
0
                 data.size);
562
0
    if (ret < 0)
563
0
      return gnutls_assert_val(
564
0
        GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
565
566
0
    pub.algo = group->pk;
567
568
    /* generate shared key */
569
0
    ret = _gnutls_pk_derive_tls13(GNUTLS_PK_DH, &session->key.key,
570
0
                &session->key.kshare.dh_params,
571
0
                &pub);
572
0
    _gnutls_mpi_release(&pub.params[DH_Y]);
573
0
    if (ret < 0)
574
0
      return gnutls_assert_val(ret);
575
576
0
    return 0;
577
578
0
  case GNUTLS_PK_EXP_KYBER768:
579
0
  case GNUTLS_PK_MLKEM768:
580
0
  case GNUTLS_PK_MLKEM1024:
581
0
    gnutls_pk_params_release(&session->key.kshare.kem_params);
582
0
    gnutls_pk_params_init(&session->key.kshare.kem_params);
583
584
    /* generate our key */
585
0
    ret = _gnutls_pk_generate_keys(
586
0
      group->pk, 0, &session->key.kshare.kem_params, 1);
587
0
    if (ret < 0)
588
0
      return gnutls_assert_val(ret);
589
590
    /* server's public key is unused, but the raw_pub field
591
    * is used to store ciphertext */
592
0
    gnutls_free(session->key.kshare.kem_params.raw_pub.data);
593
594
0
    if (group->pubkey_size > buffer->length)
595
0
      return gnutls_assert_val(
596
0
        GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
597
0
    _gnutls_buffer_pop_datum(buffer, &data, group->pubkey_size);
598
599
0
    ret = _gnutls_pk_encaps(group->pk,
600
0
          &session->key.kshare.kem_params.raw_pub,
601
0
          &key, &data);
602
0
    if (ret < 0)
603
0
      return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
604
605
0
    ret = append_key_datum(&session->key.key, &key);
606
0
    _gnutls_free_datum(&key);
607
0
    if (ret < 0)
608
0
      return gnutls_assert_val(ret);
609
610
0
    return 0;
611
612
0
  default:
613
0
    return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
614
0
  }
615
0
}
616
617
/* Generates shared key and stores it in session->key.key
618
 */
619
static int server_use_key_share(gnutls_session_t session,
620
        const gnutls_group_entry_st *group,
621
        const uint8_t *data, size_t data_size)
622
0
{
623
0
  gnutls_buffer_st buffer;
624
0
  const gnutls_group_entry_st *groups[MAX_HYBRID_GROUPS + 1] = {
625
0
    NULL,
626
0
  };
627
0
  int ret;
628
629
0
  _gnutls_ro_buffer_init(&buffer, data, data_size);
630
631
0
  ret = _gnutls_group_expand(group, groups);
632
0
  if (ret < 0)
633
0
    return gnutls_assert_val(ret);
634
635
0
  _gnutls_audit_new_context_with_data("name", CRAU_STRING,
636
0
              "tls::key_exchange", "tls::group",
637
0
              CRAU_WORD, group->tls_id, NULL);
638
639
0
  for (size_t i = 0; groups[i]; i++) {
640
0
    ret = server_use_key_share_single(session, groups[i], &buffer);
641
0
    if (ret < 0)
642
0
      return gnutls_assert_val(ret);
643
0
  }
644
645
0
  gnutls_audit_pop_context();
646
647
0
  if (buffer.length > 0)
648
0
    return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
649
650
0
  _gnutls_debug_log("EXT[%p]: server generated %s shared key\n", session,
651
0
        group->name);
652
653
0
  return 0;
654
0
}
655
656
static int client_use_key_share_single(gnutls_session_t session,
657
               const gnutls_group_entry_st *group,
658
               gnutls_buffer_st *buffer)
659
0
{
660
0
  gnutls_datum_t key = { NULL, 0 };
661
0
  gnutls_datum_t data;
662
0
  gnutls_pk_params_st pub;
663
0
  const gnutls_ecc_curve_entry_st *curve;
664
0
  int ret;
665
666
0
  switch (group->pk) {
667
0
  case GNUTLS_PK_EC:
668
0
    curve = _gnutls_ecc_curve_get_params(group->curve);
669
670
0
    gnutls_pk_params_init(&pub);
671
672
0
    if (session->key.kshare.ecdh_params.algo != group->pk ||
673
0
        session->key.kshare.ecdh_params.curve != curve->id)
674
0
      return gnutls_assert_val(
675
0
        GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
676
677
0
    if (curve->size * 2 + 1 > buffer->length)
678
0
      return gnutls_assert_val(
679
0
        GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
680
0
    _gnutls_buffer_pop_datum(buffer, &data, curve->size * 2 + 1);
681
682
    /* read the server's public key */
683
0
    ret = _gnutls_ecc_ansi_x962_import(data.data, data.size,
684
0
               &pub.params[ECC_X],
685
0
               &pub.params[ECC_Y]);
686
0
    if (ret < 0)
687
0
      return gnutls_assert_val(
688
0
        GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
689
690
0
    pub.algo = group->pk;
691
0
    pub.curve = curve->id;
692
0
    pub.params_nr = 2;
693
694
    /* generate shared key */
695
0
    ret = _gnutls_pk_derive_tls13(curve->pk, &key,
696
0
                &session->key.kshare.ecdh_params,
697
0
                &pub);
698
0
    gnutls_pk_params_release(&pub);
699
0
    if (ret < 0)
700
0
      return gnutls_assert_val(ret);
701
702
0
    ret = append_key_datum(&session->key.key, &key);
703
0
    _gnutls_free_datum(&key);
704
0
    if (ret < 0)
705
0
      return gnutls_assert_val(ret);
706
707
0
    return 0;
708
709
0
  case GNUTLS_PK_ECDH_X25519:
710
0
  case GNUTLS_PK_ECDH_X448:
711
0
    curve = _gnutls_ecc_curve_get_params(group->curve);
712
713
0
    if (session->key.kshare.ecdhx_params.algo != group->pk ||
714
0
        session->key.kshare.ecdhx_params.curve != curve->id)
715
0
      return gnutls_assert_val(
716
0
        GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
717
718
0
    if (curve->size > buffer->length)
719
0
      return gnutls_assert_val(
720
0
        GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
721
0
    _gnutls_buffer_pop_datum(buffer, &data, curve->size);
722
723
    /* read the public key and generate shared */
724
0
    gnutls_pk_params_init(&pub);
725
726
0
    pub.algo = group->pk;
727
0
    pub.curve = curve->id;
728
729
0
    pub.raw_pub.data = data.data;
730
0
    pub.raw_pub.size = data.size;
731
732
    /* We don't mask the MSB in the final byte as required
733
     * by RFC7748. This will be done internally by nettle 3.3 or later.
734
     */
735
0
    ret = _gnutls_pk_derive_tls13(curve->pk, &key,
736
0
                &session->key.kshare.ecdhx_params,
737
0
                &pub);
738
0
    if (ret < 0)
739
0
      return gnutls_assert_val(ret);
740
741
0
    ret = append_key_datum(&session->key.key, &key);
742
0
    _gnutls_free_datum(&key);
743
0
    if (ret < 0)
744
0
      return gnutls_assert_val(ret);
745
746
0
    return 0;
747
748
0
  case GNUTLS_PK_DH:
749
0
    if (session->key.kshare.dh_params.algo != group->pk ||
750
0
        session->key.kshare.dh_params.dh_group != group->id)
751
0
      return gnutls_assert_val(
752
0
        GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
753
754
0
    if (group->prime->size > buffer->length)
755
0
      return gnutls_assert_val(
756
0
        GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
757
0
    _gnutls_buffer_pop_datum(buffer, &data, group->prime->size);
758
759
    /* read the public key and generate shared */
760
0
    gnutls_pk_params_init(&pub);
761
762
0
    ret = _gnutls_mpi_init_scan_nz(&pub.params[DH_Y], data.data,
763
0
                 data.size);
764
0
    if (ret < 0)
765
0
      return gnutls_assert_val(
766
0
        GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
767
768
0
    pub.algo = group->pk;
769
770
    /* generate shared key */
771
0
    ret = _gnutls_pk_derive_tls13(GNUTLS_PK_DH, &key,
772
0
                &session->key.kshare.dh_params,
773
0
                &pub);
774
0
    _gnutls_mpi_release(&pub.params[DH_Y]);
775
0
    if (ret < 0)
776
0
      return gnutls_assert_val(ret);
777
778
0
    ret = append_key_datum(&session->key.key, &key);
779
0
    _gnutls_free_datum(&key);
780
0
    if (ret < 0)
781
0
      return gnutls_assert_val(ret);
782
783
0
    return 0;
784
785
0
  case GNUTLS_PK_EXP_KYBER768:
786
0
  case GNUTLS_PK_MLKEM768:
787
0
  case GNUTLS_PK_MLKEM1024:
788
0
    if (group->ciphertext_size > buffer->length)
789
0
      return gnutls_assert_val(
790
0
        GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
791
0
    _gnutls_buffer_pop_datum(buffer, &data, group->ciphertext_size);
792
793
0
    ret = _gnutls_pk_decaps(
794
0
      group->pk, &key, &data,
795
0
      &session->key.kshare.kem_params.raw_priv);
796
0
    if (ret < 0)
797
0
      return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
798
799
0
    ret = append_key_datum(&session->key.key, &key);
800
0
    _gnutls_free_datum(&key);
801
0
    if (ret < 0)
802
0
      return gnutls_assert_val(ret);
803
804
0
    return 0;
805
806
0
  default:
807
0
    return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
808
0
  }
809
0
}
810
811
/* Generates shared key and stores it in session->key.key
812
 */
813
static int client_use_key_share(gnutls_session_t session,
814
        const gnutls_group_entry_st *group,
815
        const uint8_t *data, size_t data_size)
816
0
{
817
0
  gnutls_buffer_st buffer;
818
0
  const gnutls_group_entry_st *groups[MAX_HYBRID_GROUPS + 1] = {
819
0
    NULL,
820
0
  };
821
0
  int ret;
822
823
0
  _gnutls_ro_buffer_init(&buffer, data, data_size);
824
825
0
  ret = _gnutls_group_expand(group, groups);
826
0
  if (ret < 0)
827
0
    return gnutls_assert_val(ret);
828
829
0
  _gnutls_audit_new_context_with_data("name", CRAU_STRING,
830
0
              "tls::key_exchange", "tls::group",
831
0
              CRAU_WORD, group->tls_id, NULL);
832
833
0
  for (size_t i = 0; groups[i]; i++) {
834
0
    ret = client_use_key_share_single(session, groups[i], &buffer);
835
0
    if (ret < 0)
836
0
      return gnutls_assert_val(ret);
837
0
  }
838
839
0
  gnutls_audit_pop_context();
840
841
0
  if (buffer.length > 0)
842
0
    return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
843
844
0
  _gnutls_debug_log("EXT[%p]: client generated %s shared key\n", session,
845
0
        group->name);
846
847
0
  return 0;
848
0
}
849
850
static int key_share_recv_params(gnutls_session_t session, const uint8_t *data,
851
         size_t data_size)
852
0
{
853
0
  int ret;
854
0
  size_t size;
855
0
  unsigned gid;
856
0
  const version_entry_st *ver;
857
0
  const gnutls_group_entry_st *group;
858
0
  unsigned used_share = 0;
859
860
0
  if (session->security_parameters.entity == GNUTLS_SERVER) {
861
0
    ver = get_version(session);
862
0
    if (ver == NULL || ver->key_shares == 0)
863
0
      return gnutls_assert_val(0);
864
865
0
    DECR_LEN(data_size, 2);
866
0
    size = _gnutls_read_uint16(data);
867
0
    data += 2;
868
869
0
    if (data_size != size)
870
0
      return gnutls_assert_val(
871
0
        GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
872
873
    /* if we do PSK without DH ignore that share */
874
0
    if ((session->internals.hsk_flags & HSK_PSK_SELECTED) &&
875
0
        (session->internals.hsk_flags & HSK_PSK_KE_MODE_PSK)) {
876
0
      reset_cand_groups(session);
877
0
      return 0;
878
0
    }
879
880
0
    while (data_size > 0) {
881
0
      DECR_LEN(data_size, 2);
882
0
      gid = _gnutls_read_uint16(data);
883
0
      data += 2;
884
885
0
      DECR_LEN(data_size, 2);
886
0
      size = _gnutls_read_uint16(data);
887
0
      data += 2;
888
889
0
      DECR_LEN(data_size, size);
890
891
      /* at this point we have already negotiated a group;
892
       * find the group's share. */
893
0
      group = _gnutls_tls_id_to_group(gid);
894
895
0
      if (group != NULL)
896
0
        _gnutls_handshake_log(
897
0
          "EXT[%p]: Received key share for %s\n",
898
0
          session, group->name);
899
900
0
      if (group != NULL &&
901
0
          group == session->internals.cand_group) {
902
0
        _gnutls_session_group_set(session, group);
903
904
0
        ret = server_use_key_share(session, group, data,
905
0
                 size);
906
0
        if (ret < 0)
907
0
          return gnutls_assert_val(ret);
908
909
0
        used_share = 1;
910
0
        break;
911
0
      }
912
913
0
      data += size;
914
0
      continue;
915
0
    }
916
917
    /* we utilize GNUTLS_E_NO_COMMON_KEY_SHARE for:
918
     * 1. signal for hello-retry-request in the handshake
919
     *    layer during first client hello parsing (server side - here).
920
     *    This does not result to error code being
921
     *    propagated to app layer.
922
     * 2. Propagate to application error code that no
923
     *    common key share was found after an HRR was
924
     *    received (client side)
925
     * 3. Propagate to application error code that no
926
     *    common key share was found after an HRR was
927
     *    sent (server side).
928
     * In cases (2,3) the error is translated to illegal
929
     * parameter alert.
930
     */
931
0
    if (used_share == 0) {
932
0
      return gnutls_assert_val(GNUTLS_E_NO_COMMON_KEY_SHARE);
933
0
    }
934
935
0
    session->internals.hsk_flags |= HSK_KEY_SHARE_RECEIVED;
936
0
  } else { /* Client */
937
0
    ver = get_version(session);
938
0
    if (unlikely(ver == NULL || ver->key_shares == 0))
939
0
      return gnutls_assert_val(
940
0
        GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
941
942
0
    if (_gnutls_ext_get_msg(session) == GNUTLS_EXT_FLAG_HRR) {
943
0
      if (unlikely(!(session->internals.hsk_flags &
944
0
               HSK_HRR_RECEIVED)))
945
0
        return gnutls_assert_val(
946
0
          GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
947
948
0
      DECR_LEN(data_size, 2);
949
0
      gid = _gnutls_read_uint16(data);
950
951
0
      group = _gnutls_tls_id_to_group(gid);
952
0
      if (group == NULL)
953
0
        return gnutls_assert_val(
954
0
          GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
955
956
0
      _gnutls_handshake_log(
957
0
        "EXT[%p]: HRR key share with %s\n", session,
958
0
        group->name);
959
960
      /* check if we support it */
961
0
      if (!_gnutls_session_supports_group(session,
962
0
                  group->id)) {
963
0
        _gnutls_handshake_log(
964
0
          "EXT[%p]: received share for %s which is disabled\n",
965
0
          session, group->name);
966
0
        return gnutls_assert_val(
967
0
          GNUTLS_E_ECC_UNSUPPORTED_CURVE);
968
0
      }
969
970
0
      _gnutls_session_group_set(session, group);
971
972
0
      return 0;
973
0
    }
974
    /* else */
975
976
0
    DECR_LEN(data_size, 2);
977
0
    gid = _gnutls_read_uint16(data);
978
0
    data += 2;
979
980
0
    DECR_LEN(data_size, 2);
981
0
    size = _gnutls_read_uint16(data);
982
0
    data += 2;
983
984
0
    if (data_size != size)
985
0
      return gnutls_assert_val(
986
0
        GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
987
988
0
    group = _gnutls_tls_id_to_group(gid);
989
0
    if (group == NULL)
990
0
      return gnutls_assert_val(
991
0
        GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
992
993
    /* check if we support it */
994
0
    if (!_gnutls_session_supports_group(session, group->id)) {
995
0
      _gnutls_handshake_log(
996
0
        "EXT[%p]: received share for %s which is disabled\n",
997
0
        session, group->name);
998
0
      return gnutls_assert_val(
999
0
        GNUTLS_E_ECC_UNSUPPORTED_CURVE);
1000
0
    }
1001
1002
0
    _gnutls_session_group_set(session, group);
1003
0
    session->internals.hsk_flags |= HSK_KEY_SHARE_RECEIVED;
1004
1005
0
    ret = client_use_key_share(session, group, data, size);
1006
0
    if (ret < 0)
1007
0
      return gnutls_assert_val(ret);
1008
0
  }
1009
1010
0
  return 0;
1011
0
}
1012
1013
static inline bool pk_types_overlap_single(const gnutls_group_entry_st *a,
1014
             const gnutls_group_entry_st *b)
1015
0
{
1016
0
  return a->pk == b->pk || (IS_ECDHX(a->pk) && IS_ECDHX(b->pk)) ||
1017
0
         (IS_KEM(a->pk) && IS_KEM(b->pk));
1018
0
}
1019
1020
static inline bool pk_types_overlap(const gnutls_group_entry_st *a,
1021
            const gnutls_group_entry_st *b)
1022
0
{
1023
0
  const gnutls_group_entry_st *sa[MAX_HYBRID_GROUPS + 1] = {
1024
0
    NULL,
1025
0
  };
1026
0
  const gnutls_group_entry_st *sb[MAX_HYBRID_GROUPS + 1] = {
1027
0
    NULL,
1028
0
  };
1029
0
  int ret;
1030
1031
0
  ret = _gnutls_group_expand(a, sa);
1032
0
  if (ret < 0) {
1033
0
    gnutls_assert();
1034
0
    return false;
1035
0
  }
1036
1037
0
  ret = _gnutls_group_expand(b, sb);
1038
0
  if (ret < 0) {
1039
0
    gnutls_assert();
1040
0
    return false;
1041
0
  }
1042
1043
0
  for (size_t i = 0; sa[i]; i++) {
1044
0
    for (size_t j = 0; sb[j]; j++) {
1045
0
      if (pk_types_overlap_single(sa[i], sb[j]))
1046
0
        return true;
1047
0
    }
1048
0
  }
1049
1050
0
  return false;
1051
0
}
1052
1053
/* returns data_size or a negative number on failure
1054
 */
1055
static int key_share_send_params(gnutls_session_t session,
1056
         gnutls_buffer_st *extdata)
1057
0
{
1058
0
  unsigned i;
1059
0
  int ret;
1060
0
  unsigned int generated = 0;
1061
0
  const gnutls_group_entry_st *group;
1062
0
  const version_entry_st *ver;
1063
1064
  /* this extension is only being sent on client side */
1065
0
  if (session->security_parameters.entity == GNUTLS_CLIENT) {
1066
0
    unsigned int length_pos;
1067
1068
0
    ver = _gnutls_version_max(session);
1069
0
    if (unlikely(ver == NULL || ver->key_shares == 0))
1070
0
      return 0;
1071
1072
0
    if (!have_creds_for_tls13(session))
1073
0
      return 0;
1074
1075
0
    length_pos = extdata->length;
1076
1077
0
    ret = _gnutls_buffer_append_prefix(extdata, 16, 0);
1078
0
    if (ret < 0)
1079
0
      return gnutls_assert_val(ret);
1080
1081
0
    if (session->internals.hsk_flags &
1082
0
        HSK_HRR_RECEIVED) { /* we know the group */
1083
0
      group = get_group(session);
1084
0
      if (unlikely(group == NULL))
1085
0
        return gnutls_assert_val(
1086
0
          GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
1087
1088
0
      ret = client_gen_key_share(session, group, extdata);
1089
0
      if (ret == GNUTLS_E_INT_RET_0)
1090
0
        return gnutls_assert_val(
1091
0
          GNUTLS_E_NO_COMMON_KEY_SHARE);
1092
0
      if (ret < 0)
1093
0
        return gnutls_assert_val(ret);
1094
0
    } else {
1095
0
      const gnutls_group_entry_st *selected_groups[3] = {
1096
0
        NULL,
1097
0
      };
1098
0
      unsigned max_groups = 2; /* GNUTLS_KEY_SHARE_TOP2 */
1099
1100
0
      if (session->internals.flags & GNUTLS_KEY_SHARE_TOP)
1101
0
        max_groups = 1;
1102
0
      else if (session->internals.flags &
1103
0
         GNUTLS_KEY_SHARE_TOP3)
1104
0
        max_groups = 3;
1105
1106
0
      assert(max_groups <=
1107
0
             sizeof(selected_groups) /
1108
0
               sizeof(selected_groups[0]));
1109
1110
      /* generate key shares for out top-(max_groups) groups
1111
       * if they are of different PK type. */
1112
0
      for (i = 0;
1113
0
           i < session->internals.priorities->groups.size;
1114
0
           i++) {
1115
0
        unsigned int j;
1116
1117
0
        group = session->internals.priorities->groups
1118
0
            .entry[i];
1119
1120
0
        for (j = 0; j < generated; j++) {
1121
0
          if (pk_types_overlap(
1122
0
                group,
1123
0
                selected_groups[j])) {
1124
0
            break;
1125
0
          }
1126
0
        }
1127
0
        if (j < generated) {
1128
0
          continue;
1129
0
        }
1130
1131
0
        selected_groups[generated] = group;
1132
1133
0
        ret = client_gen_key_share(session, group,
1134
0
                 extdata);
1135
0
        if (ret == GNUTLS_E_INT_RET_0)
1136
0
          continue; /* no key share for this algorithm */
1137
0
        if (ret < 0)
1138
0
          return gnutls_assert_val(ret);
1139
1140
0
        generated++;
1141
1142
0
        if (generated >= max_groups)
1143
0
          break;
1144
0
      }
1145
0
    }
1146
1147
    /* copy actual length */
1148
0
    _gnutls_write_uint16(extdata->length - length_pos - 2,
1149
0
             &extdata->data[length_pos]);
1150
1151
0
  } else { /* server */
1152
0
    ver = get_version(session);
1153
0
    if (unlikely(ver == NULL || ver->key_shares == 0))
1154
0
      return gnutls_assert_val(0);
1155
1156
0
    if (_gnutls_ext_get_msg(session) == GNUTLS_EXT_FLAG_HRR) {
1157
0
      group = session->internals.cand_group;
1158
1159
0
      if (group == NULL)
1160
0
        return gnutls_assert_val(
1161
0
          GNUTLS_E_NO_COMMON_KEY_SHARE);
1162
1163
0
      _gnutls_session_group_set(session, group);
1164
1165
0
      _gnutls_handshake_log(
1166
0
        "EXT[%p]: requesting retry with group %s\n",
1167
0
        session, group->name);
1168
0
      ret = _gnutls_buffer_append_prefix(extdata, 16,
1169
0
                 group->tls_id);
1170
0
      if (ret < 0)
1171
0
        return gnutls_assert_val(ret);
1172
0
    } else {
1173
      /* if we are negotiating PSK without DH, do not send a key share */
1174
0
      if ((session->internals.hsk_flags & HSK_PSK_SELECTED) &&
1175
0
          (session->internals.hsk_flags &
1176
0
           HSK_PSK_KE_MODE_PSK))
1177
0
        return gnutls_assert_val(0);
1178
1179
0
      group = get_group(session);
1180
0
      if (unlikely(group == NULL))
1181
0
        return gnutls_assert_val(
1182
0
          GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
1183
1184
0
      ret = server_gen_key_share(session, group, extdata);
1185
0
      if (ret < 0)
1186
0
        return gnutls_assert_val(ret);
1187
0
    }
1188
1189
0
    session->internals.hsk_flags |= HSK_KEY_SHARE_SENT;
1190
0
  }
1191
1192
0
  return 0;
1193
0
}