Coverage Report

Created: 2025-01-28 06:58

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