Coverage Report

Created: 2025-11-16 06:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gnutls/lib/kx.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2000-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 functions which are wrappers for the key exchange
24
 * part of TLS. They are called by the handshake functions (gnutls_handshake)
25
 */
26
27
#include "gnutls_int.h"
28
#include "handshake.h"
29
#include "kx.h"
30
#include "dh.h"
31
#include "errors.h"
32
#include "algorithms.h"
33
#include "debug.h"
34
#include "locks.h"
35
#include "mpi.h"
36
#include "state.h"
37
#include "datum.h"
38
#include "mbuffers.h"
39
40
/* This file contains important thing for the TLS handshake procedure.
41
 */
42
43
10.3k
#define MASTER_SECRET "master secret"
44
5.15k
#define MASTER_SECRET_SIZE (sizeof(MASTER_SECRET) - 1)
45
46
922
#define EXT_MASTER_SECRET "extended master secret"
47
461
#define EXT_MASTER_SECRET_SIZE (sizeof(EXT_MASTER_SECRET) - 1)
48
49
GNUTLS_STATIC_MUTEX(keylog_mutex);
50
static FILE *keylog;
51
52
static int generate_normal_master(gnutls_session_t session, gnutls_datum_t *,
53
          int);
54
55
int _gnutls_generate_master(gnutls_session_t session, int keep_premaster)
56
5.61k
{
57
5.61k
  if (!session->internals.resumed)
58
5.61k
    return generate_normal_master(session, &session->key.key,
59
5.61k
                keep_premaster);
60
0
  else if (session->internals.premaster_set) {
61
0
    gnutls_datum_t premaster;
62
0
    premaster.size =
63
0
      sizeof(session->internals.resumed_security_parameters
64
0
               .master_secret);
65
0
    premaster.data = session->internals.resumed_security_parameters
66
0
           .master_secret;
67
0
    return generate_normal_master(session, &premaster, 1);
68
0
  }
69
0
  return 0;
70
5.61k
}
71
72
/**
73
 * gnutls_session_get_keylog_function:
74
 * @session: is #gnutls_session_t type
75
 *
76
 * This function will return the callback function set using
77
 * gnutls_session_set_keylog_function().
78
 *
79
 * Returns: The function set or %NULL otherwise.
80
 *
81
 * Since: 3.6.13
82
 */
83
gnutls_keylog_func
84
gnutls_session_get_keylog_function(const gnutls_session_t session)
85
0
{
86
0
  return session->internals.keylog_func;
87
0
}
88
89
/**
90
 * gnutls_session_set_keylog_function:
91
 * @session: is #gnutls_session_t type
92
 * @func: is the function to be called
93
 *
94
 * This function will set a callback to be called when a new secret is
95
 * derived and installed during handshake.
96
 *
97
 * Since: 3.6.13
98
 */
99
void gnutls_session_set_keylog_function(gnutls_session_t session,
100
          gnutls_keylog_func func)
101
41.2k
{
102
41.2k
  session->internals.keylog_func = func;
103
41.2k
}
104
105
int _gnutls_call_keylog_func(gnutls_session_t session, const char *label,
106
           const uint8_t *data, unsigned size)
107
40.7k
{
108
40.7k
  if (session->internals.keylog_func) {
109
40.7k
    gnutls_datum_t secret = { (void *)data, size };
110
40.7k
    return session->internals.keylog_func(session, label, &secret);
111
40.7k
  }
112
0
  return 0;
113
40.7k
}
114
115
int _gnutls_nss_keylog_func(gnutls_session_t session, const char *label,
116
          const gnutls_datum_t *secret)
117
40.7k
{
118
  /* ignore subsequent traffic secrets that are calculated from
119
   * the previous traffic secret
120
   */
121
40.7k
  if (!session->internals.handshake_in_progress)
122
0
    return 0;
123
124
40.7k
  _gnutls_nss_keylog_write(session, label, secret->data, secret->size);
125
40.7k
  return 0;
126
40.7k
}
127
128
/* GCC analyzer doesn't like static FILE pointer */
129
#pragma GCC diagnostic push
130
#pragma GCC diagnostic ignored "-Wanalyzer-file-leak"
131
132
GNUTLS_ONCE(keylog_once);
133
134
static void keylog_once_init(void)
135
8
{
136
8
  const char *keylogfile;
137
138
8
  keylogfile = secure_getenv("SSLKEYLOGFILE");
139
8
  if (keylogfile != NULL && *keylogfile != '\0') {
140
0
    keylog = fopen(keylogfile, "ae");
141
0
    _gnutls_debug_log("unable to open keylog file %s\n",
142
0
          keylogfile);
143
0
  }
144
8
}
145
146
void _gnutls_nss_keylog_write(gnutls_session_t session, const char *label,
147
            const uint8_t *secret, size_t secret_size)
148
40.7k
{
149
40.7k
  (void)gnutls_once(&keylog_once, keylog_once_init);
150
151
40.7k
  if (keylog) {
152
0
    char client_random_hex[2 * GNUTLS_RANDOM_SIZE + 1];
153
0
    char secret_hex[2 * MAX_HASH_SIZE + 1];
154
155
0
    if (gnutls_static_mutex_lock(&keylog_mutex) < 0) {
156
0
      return;
157
0
    }
158
0
    fprintf(keylog, "%s %s %s\n", label,
159
0
      _gnutls_bin2hex(
160
0
        session->security_parameters.client_random,
161
0
        GNUTLS_RANDOM_SIZE, client_random_hex,
162
0
        sizeof(client_random_hex), NULL),
163
0
      _gnutls_bin2hex(secret, secret_size, secret_hex,
164
0
          sizeof(secret_hex), NULL));
165
0
    fflush(keylog);
166
0
    (void)gnutls_static_mutex_unlock(&keylog_mutex);
167
0
  }
168
40.7k
}
169
170
void _gnutls_nss_keylog_deinit(void)
171
0
{
172
0
  if (keylog) {
173
0
    fclose(keylog);
174
0
    keylog = NULL;
175
0
  }
176
0
}
177
178
#pragma GCC diagnostic pop
179
180
/* here we generate the TLS Master secret.
181
 */
182
static int generate_normal_master(gnutls_session_t session,
183
          gnutls_datum_t *premaster, int keep_premaster)
184
5.61k
{
185
5.61k
  int ret = 0;
186
5.61k
  char buf[512];
187
188
5.61k
  _gnutls_hard_log("INT: PREMASTER SECRET[%d]: %s\n", premaster->size,
189
5.61k
       _gnutls_bin2hex(premaster->data, premaster->size, buf,
190
5.61k
           sizeof(buf), NULL));
191
5.61k
  _gnutls_hard_log(
192
5.61k
    "INT: CLIENT RANDOM[%d]: %s\n", 32,
193
5.61k
    _gnutls_bin2hex(session->security_parameters.client_random, 32,
194
5.61k
        buf, sizeof(buf), NULL));
195
5.61k
  _gnutls_hard_log(
196
5.61k
    "INT: SERVER RANDOM[%d]: %s\n", 32,
197
5.61k
    _gnutls_bin2hex(session->security_parameters.server_random, 32,
198
5.61k
        buf, sizeof(buf), NULL));
199
200
5.61k
  if (session->security_parameters.ext_master_secret == 0) {
201
5.15k
    uint8_t rnd[2 * GNUTLS_RANDOM_SIZE + 1];
202
5.15k
    memcpy(rnd, session->security_parameters.client_random,
203
5.15k
           GNUTLS_RANDOM_SIZE);
204
5.15k
    memcpy(&rnd[GNUTLS_RANDOM_SIZE],
205
5.15k
           session->security_parameters.server_random,
206
5.15k
           GNUTLS_RANDOM_SIZE);
207
208
5.15k
    _gnutls_memory_mark_defined(
209
5.15k
      session->security_parameters.master_secret,
210
5.15k
      GNUTLS_MASTER_SIZE);
211
#ifdef ENABLE_SSL3
212
    if (get_num_version(session) == GNUTLS_SSL3) {
213
      ret = _gnutls_ssl3_generate_random(
214
        premaster->data, premaster->size, rnd,
215
        2 * GNUTLS_RANDOM_SIZE, GNUTLS_MASTER_SIZE,
216
        session->security_parameters.master_secret);
217
    } else
218
#endif
219
5.15k
      ret = _gnutls_PRF(
220
5.15k
        session, premaster->data, premaster->size,
221
5.15k
        MASTER_SECRET, MASTER_SECRET_SIZE, rnd,
222
5.15k
        2 * GNUTLS_RANDOM_SIZE, GNUTLS_MASTER_SIZE,
223
5.15k
        session->security_parameters.master_secret);
224
5.15k
    if (ret < 0)
225
0
      _gnutls_memory_mark_undefined(
226
0
        session->security_parameters.master_secret,
227
0
        GNUTLS_MASTER_SIZE);
228
5.15k
  } else {
229
461
    gnutls_datum_t shash = { NULL, 0 };
230
231
    /* draft-ietf-tls-session-hash-02 */
232
461
    ret = _gnutls_handshake_get_session_hash(session, &shash);
233
461
    if (ret < 0)
234
0
      return gnutls_assert_val(ret);
235
#ifdef ENABLE_SSL3
236
    if (get_num_version(session) == GNUTLS_SSL3)
237
      return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
238
#endif
239
240
461
    _gnutls_memory_mark_defined(
241
461
      session->security_parameters.master_secret,
242
461
      GNUTLS_MASTER_SIZE);
243
461
    ret = _gnutls_PRF(session, premaster->data, premaster->size,
244
461
          EXT_MASTER_SECRET, EXT_MASTER_SECRET_SIZE,
245
461
          shash.data, shash.size, GNUTLS_MASTER_SIZE,
246
461
          session->security_parameters.master_secret);
247
461
    if (ret < 0)
248
0
      _gnutls_memory_mark_undefined(
249
0
        session->security_parameters.master_secret,
250
0
        GNUTLS_MASTER_SIZE);
251
252
461
    gnutls_free(shash.data);
253
461
  }
254
255
5.61k
  if (!keep_premaster)
256
5.61k
    _gnutls_free_key_datum(premaster);
257
258
5.61k
  if (ret < 0)
259
0
    return ret;
260
261
5.61k
  ret = _gnutls_call_keylog_func(
262
5.61k
    session, "CLIENT_RANDOM",
263
5.61k
    session->security_parameters.master_secret, GNUTLS_MASTER_SIZE);
264
5.61k
  if (ret < 0)
265
0
    return gnutls_assert_val(ret);
266
267
5.61k
  _gnutls_hard_log(
268
5.61k
    "INT: MASTER SECRET[%d]: %s\n", GNUTLS_MASTER_SIZE,
269
5.61k
    _gnutls_bin2hex(session->security_parameters.master_secret,
270
5.61k
        GNUTLS_MASTER_SIZE, buf, sizeof(buf), NULL));
271
272
5.61k
  return ret;
273
5.61k
}
274
275
/* This is called when we want to receive the key exchange message of the
276
 * server. It does nothing if this type of message is not required
277
 * by the selected ciphersuite. 
278
 */
279
int _gnutls_send_server_kx_message(gnutls_session_t session, int again)
280
5.97k
{
281
5.97k
  gnutls_buffer_st buf;
282
5.97k
  int ret = 0;
283
5.97k
  mbuffer_st *bufel = NULL;
284
285
5.97k
  if (session->internals.auth_struct->gnutls_generate_server_kx == NULL)
286
273
    return 0;
287
288
5.70k
  if (again == 0) {
289
5.70k
    ret = _gnutls_buffer_init_handshake_mbuffer(&buf);
290
5.70k
    if (ret < 0)
291
0
      return gnutls_assert_val(ret);
292
293
5.70k
    ret = session->internals.auth_struct->gnutls_generate_server_kx(
294
5.70k
      session, &buf);
295
296
5.70k
    if (ret == GNUTLS_E_INT_RET_0) {
297
329
      gnutls_assert();
298
329
      ret = 0;
299
329
      goto cleanup;
300
329
    }
301
302
5.37k
    if (ret < 0) {
303
0
      gnutls_assert();
304
0
      goto cleanup;
305
0
    }
306
307
5.37k
    bufel = _gnutls_buffer_to_mbuffer(&buf);
308
5.37k
  }
309
310
5.37k
  return _gnutls_send_handshake(session, bufel,
311
5.37k
              GNUTLS_HANDSHAKE_SERVER_KEY_EXCHANGE);
312
313
329
cleanup:
314
329
  _gnutls_buffer_clear(&buf);
315
329
  return ret;
316
5.70k
}
317
318
/* This function sends a certificate request message to the
319
 * client.
320
 */
321
int _gnutls_send_server_crt_request(gnutls_session_t session, int again)
322
5.97k
{
323
5.97k
  gnutls_buffer_st buf;
324
5.97k
  int ret = 0;
325
5.97k
  mbuffer_st *bufel = NULL;
326
327
5.97k
  if (session->internals.auth_struct->gnutls_generate_server_crt_request ==
328
5.97k
      NULL)
329
2.07k
    return 0;
330
331
3.90k
  if (session->internals.send_cert_req <= 0)
332
3.90k
    return 0;
333
334
0
  if (again == 0) {
335
0
    ret = _gnutls_buffer_init_handshake_mbuffer(&buf);
336
0
    if (ret < 0)
337
0
      return gnutls_assert_val(ret);
338
339
0
    ret = session->internals.auth_struct
340
0
            ->gnutls_generate_server_crt_request(session,
341
0
                   &buf);
342
343
0
    if (ret < 0) {
344
0
      gnutls_assert();
345
0
      goto cleanup;
346
0
    }
347
348
0
    bufel = _gnutls_buffer_to_mbuffer(&buf);
349
0
  }
350
351
0
  return _gnutls_send_handshake(session, bufel,
352
0
              GNUTLS_HANDSHAKE_CERTIFICATE_REQUEST);
353
354
0
cleanup:
355
0
  _gnutls_buffer_clear(&buf);
356
0
  return ret;
357
0
}
358
359
/* This is the function for the client to send the key
360
 * exchange message 
361
 */
362
int _gnutls_send_client_kx_message(gnutls_session_t session, int again)
363
5.51k
{
364
5.51k
  gnutls_buffer_st buf;
365
5.51k
  int ret = 0;
366
5.51k
  mbuffer_st *bufel = NULL;
367
368
5.51k
  if (session->internals.auth_struct->gnutls_generate_client_kx == NULL)
369
0
    return 0;
370
371
5.51k
  if (again == 0) {
372
5.51k
    ret = _gnutls_buffer_init_handshake_mbuffer(&buf);
373
5.51k
    if (ret < 0)
374
0
      return gnutls_assert_val(ret);
375
376
5.51k
    ret = session->internals.auth_struct->gnutls_generate_client_kx(
377
5.51k
      session, &buf);
378
5.51k
    if (ret < 0) {
379
329
      gnutls_assert();
380
329
      goto cleanup;
381
329
    }
382
383
5.18k
    bufel = _gnutls_buffer_to_mbuffer(&buf);
384
5.18k
  }
385
386
5.18k
  return _gnutls_send_handshake(session, bufel,
387
5.18k
              GNUTLS_HANDSHAKE_CLIENT_KEY_EXCHANGE);
388
389
329
cleanup:
390
329
  _gnutls_buffer_clear(&buf);
391
329
  return ret;
392
5.51k
}
393
394
/* This is the function for the client to send the certificate
395
 * verify message
396
 */
397
int _gnutls_send_client_certificate_verify(gnutls_session_t session, int again)
398
5.18k
{
399
5.18k
  gnutls_buffer_st buf;
400
5.18k
  int ret = 0;
401
5.18k
  mbuffer_st *bufel = NULL;
402
403
  /* This is a packet that is only sent by the client
404
   */
405
5.18k
  if (session->security_parameters.entity == GNUTLS_SERVER)
406
0
    return 0;
407
408
  /* if certificate verify is not needed just exit 
409
   */
410
5.18k
  if (!(session->internals.hsk_flags & HSK_CRT_ASKED))
411
5.18k
    return 0;
412
413
4
  if (session->internals.auth_struct->gnutls_generate_client_crt_vrfy ==
414
4
      NULL) {
415
0
    gnutls_assert();
416
0
    return 0; /* this algorithm does not support cli_crt_vrfy 
417
         */
418
0
  }
419
420
4
  if (again == 0) {
421
4
    ret = _gnutls_buffer_init_handshake_mbuffer(&buf);
422
4
    if (ret < 0)
423
0
      return gnutls_assert_val(ret);
424
425
4
    ret = session->internals.auth_struct
426
4
            ->gnutls_generate_client_crt_vrfy(session, &buf);
427
4
    if (ret < 0) {
428
0
      gnutls_assert();
429
0
      goto cleanup;
430
0
    }
431
432
4
    if (ret == 0)
433
4
      goto cleanup;
434
435
0
    bufel = _gnutls_buffer_to_mbuffer(&buf);
436
0
  }
437
438
0
  return _gnutls_send_handshake(session, bufel,
439
0
              GNUTLS_HANDSHAKE_CERTIFICATE_VERIFY);
440
441
4
cleanup:
442
4
  _gnutls_buffer_clear(&buf);
443
4
  return ret;
444
4
}
445
446
/* This is called when we want send our certificate
447
 */
448
int _gnutls_send_client_certificate(gnutls_session_t session, int again)
449
5.51k
{
450
5.51k
  gnutls_buffer_st buf;
451
5.51k
  int ret = 0;
452
5.51k
  mbuffer_st *bufel = NULL;
453
454
5.51k
  if (!(session->internals.hsk_flags & HSK_CRT_ASKED))
455
5.51k
    return 0;
456
457
6
  if (session->internals.auth_struct->gnutls_generate_client_certificate ==
458
6
      NULL)
459
0
    return 0;
460
461
6
  if (again == 0) {
462
6
    ret = _gnutls_buffer_init_handshake_mbuffer(&buf);
463
6
    if (ret < 0)
464
0
      return gnutls_assert_val(ret);
465
466
#ifdef ENABLE_SSL3
467
    if (get_num_version(session) != GNUTLS_SSL3 ||
468
        session->internals.selected_cert_list_length > 0)
469
#endif
470
6
    {
471
      /* TLS 1.x or SSL 3.0 with a valid certificate 
472
       */
473
6
      ret = session->internals.auth_struct
474
6
              ->gnutls_generate_client_certificate(
475
6
                session, &buf);
476
477
6
      if (ret < 0) {
478
0
        gnutls_assert();
479
0
        goto cleanup;
480
0
      }
481
6
    }
482
483
6
    bufel = _gnutls_buffer_to_mbuffer(&buf);
484
6
  }
485
#ifdef ENABLE_SSL3
486
  /* In the SSL 3.0 protocol we need to send a
487
   * no certificate alert instead of an
488
   * empty certificate.
489
   */
490
  if (get_num_version(session) == GNUTLS_SSL3 &&
491
      session->internals.selected_cert_list_length == 0) {
492
    _mbuffer_xfree(&bufel);
493
    return gnutls_alert_send(session, GNUTLS_AL_WARNING,
494
           GNUTLS_A_SSL3_NO_CERTIFICATE);
495
496
  } else /* TLS 1.0 or SSL 3.0 with a valid certificate 
497
         */
498
#endif
499
6
    return _gnutls_send_handshake(session, bufel,
500
6
                GNUTLS_HANDSHAKE_CERTIFICATE_PKT);
501
502
0
cleanup:
503
0
  _gnutls_buffer_clear(&buf);
504
0
  return ret;
505
6
}
506
507
/* This is called when we want send our certificate
508
 */
509
int _gnutls_send_server_certificate(gnutls_session_t session, int again)
510
5.97k
{
511
5.97k
  gnutls_buffer_st buf;
512
5.97k
  int ret = 0;
513
5.97k
  mbuffer_st *bufel = NULL;
514
515
5.97k
  if (session->internals.auth_struct->gnutls_generate_server_certificate ==
516
5.97k
      NULL)
517
1.91k
    return 0;
518
519
4.06k
  if (again == 0) {
520
4.06k
    ret = _gnutls_buffer_init_handshake_mbuffer(&buf);
521
4.06k
    if (ret < 0)
522
0
      return gnutls_assert_val(ret);
523
524
4.06k
    ret = session->internals.auth_struct
525
4.06k
            ->gnutls_generate_server_certificate(session,
526
4.06k
                   &buf);
527
528
4.06k
    if (ret < 0) {
529
0
      gnutls_assert();
530
0
      goto cleanup;
531
0
    }
532
533
4.06k
    bufel = _gnutls_buffer_to_mbuffer(&buf);
534
4.06k
  }
535
536
4.06k
  return _gnutls_send_handshake(session, bufel,
537
4.06k
              GNUTLS_HANDSHAKE_CERTIFICATE_PKT);
538
539
0
cleanup:
540
0
  _gnutls_buffer_clear(&buf);
541
0
  return ret;
542
4.06k
}
543
544
int _gnutls_recv_server_kx_message(gnutls_session_t session)
545
12.5k
{
546
12.5k
  gnutls_buffer_st buf;
547
12.5k
  int ret = 0;
548
12.5k
  unsigned int optflag = 0;
549
550
12.5k
  if (session->internals.auth_struct->gnutls_process_server_kx != NULL) {
551
    /* Server key exchange packet is optional for PSK. */
552
10.8k
    if (_gnutls_session_is_psk(session))
553
4.83k
      optflag = 1;
554
555
10.8k
    ret = _gnutls_recv_handshake(
556
10.8k
      session, GNUTLS_HANDSHAKE_SERVER_KEY_EXCHANGE, optflag,
557
10.8k
      &buf);
558
10.8k
    if (ret < 0) {
559
1.78k
      gnutls_assert();
560
1.78k
      return ret;
561
1.78k
    }
562
563
9.10k
    ret = session->internals.auth_struct->gnutls_process_server_kx(
564
9.10k
      session, buf.data, buf.length);
565
9.10k
    _gnutls_buffer_clear(&buf);
566
567
9.10k
    if (ret < 0) {
568
4.88k
      gnutls_assert();
569
4.88k
      return ret;
570
4.88k
    }
571
9.10k
  }
572
5.89k
  return ret;
573
12.5k
}
574
575
int _gnutls_recv_server_crt_request(gnutls_session_t session)
576
6.56k
{
577
6.56k
  gnutls_buffer_st buf;
578
6.56k
  int ret = 0;
579
580
6.56k
  if (session->internals.auth_struct->gnutls_process_server_crt_request !=
581
6.56k
      NULL) {
582
2.35k
    ret = _gnutls_recv_handshake(
583
2.35k
      session, GNUTLS_HANDSHAKE_CERTIFICATE_REQUEST, 1, &buf);
584
2.35k
    if (ret < 0)
585
737
      return ret;
586
587
1.62k
    if (ret == 0 && buf.length == 0) {
588
1.41k
      _gnutls_buffer_clear(&buf);
589
1.41k
      return 0; /* ignored */
590
1.41k
    }
591
592
207
    ret = session->internals.auth_struct
593
207
            ->gnutls_process_server_crt_request(
594
207
              session, buf.data, buf.length);
595
207
    _gnutls_buffer_clear(&buf);
596
207
    if (ret < 0)
597
178
      return ret;
598
207
  }
599
4.24k
  return ret;
600
6.56k
}
601
602
int _gnutls_recv_client_kx_message(gnutls_session_t session)
603
8.18k
{
604
8.18k
  gnutls_buffer_st buf;
605
8.18k
  int ret = 0;
606
607
  /* Do key exchange only if the algorithm permits it */
608
8.18k
  if (session->internals.auth_struct->gnutls_process_client_kx != NULL) {
609
8.18k
    ret = _gnutls_recv_handshake(
610
8.18k
      session, GNUTLS_HANDSHAKE_CLIENT_KEY_EXCHANGE, 0, &buf);
611
8.18k
    if (ret < 0)
612
3.36k
      return ret;
613
614
4.81k
    ret = session->internals.auth_struct->gnutls_process_client_kx(
615
4.81k
      session, buf.data, buf.length);
616
4.81k
    _gnutls_buffer_clear(&buf);
617
4.81k
    if (ret < 0)
618
1.30k
      return ret;
619
4.81k
  }
620
621
3.51k
  return ret;
622
8.18k
}
623
624
int _gnutls_recv_client_certificate(gnutls_session_t session)
625
5.97k
{
626
5.97k
  gnutls_buffer_st buf;
627
5.97k
  int ret = 0;
628
5.97k
  int optional;
629
630
5.97k
  if (session->internals.auth_struct->gnutls_process_client_certificate ==
631
5.97k
      NULL)
632
2.07k
    return 0;
633
634
  /* if we have not requested a certificate then just return
635
   */
636
3.90k
  if (session->internals.send_cert_req == 0) {
637
3.90k
    return 0;
638
3.90k
  }
639
640
0
  if (session->internals.send_cert_req == GNUTLS_CERT_REQUIRE)
641
0
    optional = 0;
642
0
  else
643
0
    optional = 1;
644
645
0
  ret = _gnutls_recv_handshake(session, GNUTLS_HANDSHAKE_CERTIFICATE_PKT,
646
0
             optional, &buf);
647
648
0
  if (ret < 0) {
649
    /* Handle the case of old SSL3 clients who send
650
     * a warning alert instead of an empty certificate to indicate
651
     * no certificate.
652
     */
653
#ifdef ENABLE_SSL3
654
    if (optional != 0 && ret == GNUTLS_E_WARNING_ALERT_RECEIVED &&
655
        get_num_version(session) == GNUTLS_SSL3 &&
656
        gnutls_alert_get(session) == GNUTLS_A_SSL3_NO_CERTIFICATE) {
657
      /* SSL3 does not send an empty certificate,
658
       * but this alert. So we just ignore it.
659
       */
660
      gnutls_assert();
661
      return 0;
662
    }
663
#endif
664
665
    /* certificate was required 
666
     */
667
0
    if ((ret == GNUTLS_E_WARNING_ALERT_RECEIVED ||
668
0
         ret == GNUTLS_E_FATAL_ALERT_RECEIVED) &&
669
0
        optional == 0) {
670
0
      gnutls_assert();
671
0
      return GNUTLS_E_NO_CERTIFICATE_FOUND;
672
0
    }
673
674
0
    return ret;
675
0
  }
676
677
0
  if (ret == 0 && buf.length == 0 && optional != 0) {
678
    /* Client has not sent the certificate message.
679
     * well I'm not sure we should accept this
680
     * behaviour.
681
     */
682
0
    gnutls_assert();
683
0
    ret = 0;
684
0
    goto cleanup;
685
0
  }
686
0
  ret = session->internals.auth_struct->gnutls_process_client_certificate(
687
0
    session, buf.data, buf.length);
688
689
0
  if (ret < 0 && ret != GNUTLS_E_NO_CERTIFICATE_FOUND) {
690
0
    gnutls_assert();
691
0
    goto cleanup;
692
0
  }
693
694
  /* ok we should expect a certificate verify message now 
695
   */
696
0
  if (ret == GNUTLS_E_NO_CERTIFICATE_FOUND && optional != 0)
697
0
    ret = 0;
698
0
  else
699
0
    session->internals.hsk_flags |= HSK_CRT_VRFY_EXPECTED;
700
701
0
cleanup:
702
0
  _gnutls_buffer_clear(&buf);
703
0
  return ret;
704
0
}
705
706
int _gnutls_recv_server_certificate(gnutls_session_t session)
707
16.1k
{
708
16.1k
  gnutls_buffer_st buf;
709
16.1k
  int ret = 0;
710
711
16.1k
  if (session->internals.auth_struct->gnutls_process_server_certificate !=
712
16.1k
      NULL) {
713
11.7k
    ret = _gnutls_recv_handshake(
714
11.7k
      session, GNUTLS_HANDSHAKE_CERTIFICATE_PKT, 0, &buf);
715
11.7k
    if (ret < 0) {
716
1.65k
      gnutls_assert();
717
1.65k
      return ret;
718
1.65k
    }
719
720
10.0k
    ret = session->internals.auth_struct
721
10.0k
            ->gnutls_process_server_certificate(
722
10.0k
              session, buf.data, buf.length);
723
10.0k
    _gnutls_buffer_clear(&buf);
724
10.0k
    if (ret < 0) {
725
3.40k
      gnutls_assert();
726
3.40k
      return ret;
727
3.40k
    }
728
10.0k
  }
729
730
11.0k
  return ret;
731
16.1k
}
732
733
/* Recv the client certificate verify. This packet may not
734
 * arrive if the peer did not send us a certificate.
735
 */
736
int _gnutls_recv_client_certificate_verify_message(gnutls_session_t session)
737
3.51k
{
738
3.51k
  gnutls_buffer_st buf;
739
3.51k
  int ret = 0;
740
741
3.51k
  if (session->internals.auth_struct->gnutls_process_client_crt_vrfy ==
742
3.51k
      NULL)
743
1.21k
    return 0;
744
745
2.29k
  if (session->internals.send_cert_req == 0 ||
746
2.29k
      (!(session->internals.hsk_flags & HSK_CRT_VRFY_EXPECTED))) {
747
2.29k
    return 0;
748
2.29k
  }
749
750
0
  ret = _gnutls_recv_handshake(
751
0
    session, GNUTLS_HANDSHAKE_CERTIFICATE_VERIFY, 1, &buf);
752
0
  if (ret < 0)
753
0
    return ret;
754
755
0
  if (ret == 0 && buf.length == 0 &&
756
0
      session->internals.send_cert_req == GNUTLS_CERT_REQUIRE) {
757
    /* certificate was required */
758
0
    gnutls_assert();
759
0
    ret = GNUTLS_E_NO_CERTIFICATE_FOUND;
760
0
    goto cleanup;
761
0
  }
762
763
0
  ret = session->internals.auth_struct->gnutls_process_client_crt_vrfy(
764
0
    session, buf.data, buf.length);
765
766
0
cleanup:
767
0
  _gnutls_buffer_clear(&buf);
768
0
  return ret;
769
0
}