Coverage Report

Created: 2025-12-31 08:15

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