Coverage Report

Created: 2025-03-18 06:55

/src/gnutls/lib/kx.c
Line
Count
Source (jump to first uncovered line)
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
    _gnutls_debug_log("unable to open keylog file %s\n",
142
0
          keylogfile);
143
0
  }
144
0
}
145
146
void _gnutls_nss_keylog_write(gnutls_session_t session, const char *label,
147
            const uint8_t *secret, size_t secret_size)
148
0
{
149
0
  (void)gnutls_once(&keylog_once, keylog_once_init);
150
151
0
  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
0
}
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
0
{
185
0
  int ret = 0;
186
0
  char buf[512];
187
188
0
  _gnutls_hard_log("INT: PREMASTER SECRET[%d]: %s\n", premaster->size,
189
0
       _gnutls_bin2hex(premaster->data, premaster->size, buf,
190
0
           sizeof(buf), NULL));
191
0
  _gnutls_hard_log(
192
0
    "INT: CLIENT RANDOM[%d]: %s\n", 32,
193
0
    _gnutls_bin2hex(session->security_parameters.client_random, 32,
194
0
        buf, sizeof(buf), NULL));
195
0
  _gnutls_hard_log(
196
0
    "INT: SERVER RANDOM[%d]: %s\n", 32,
197
0
    _gnutls_bin2hex(session->security_parameters.server_random, 32,
198
0
        buf, sizeof(buf), NULL));
199
200
0
  if (session->security_parameters.ext_master_secret == 0) {
201
0
    uint8_t rnd[2 * GNUTLS_RANDOM_SIZE + 1];
202
0
    memcpy(rnd, session->security_parameters.client_random,
203
0
           GNUTLS_RANDOM_SIZE);
204
0
    memcpy(&rnd[GNUTLS_RANDOM_SIZE],
205
0
           session->security_parameters.server_random,
206
0
           GNUTLS_RANDOM_SIZE);
207
208
0
    _gnutls_memory_mark_defined(
209
0
      session->security_parameters.master_secret,
210
0
      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
0
      ret = _gnutls_PRF(
220
0
        session, premaster->data, premaster->size,
221
0
        MASTER_SECRET, MASTER_SECRET_SIZE, rnd,
222
0
        2 * GNUTLS_RANDOM_SIZE, GNUTLS_MASTER_SIZE,
223
0
        session->security_parameters.master_secret);
224
0
    if (ret < 0)
225
0
      _gnutls_memory_mark_undefined(
226
0
        session->security_parameters.master_secret,
227
0
        GNUTLS_MASTER_SIZE);
228
0
  } else {
229
0
    gnutls_datum_t shash = { NULL, 0 };
230
231
    /* draft-ietf-tls-session-hash-02 */
232
0
    ret = _gnutls_handshake_get_session_hash(session, &shash);
233
0
    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
0
    _gnutls_memory_mark_defined(
241
0
      session->security_parameters.master_secret,
242
0
      GNUTLS_MASTER_SIZE);
243
0
    ret = _gnutls_PRF(session, premaster->data, premaster->size,
244
0
          EXT_MASTER_SECRET, EXT_MASTER_SECRET_SIZE,
245
0
          shash.data, shash.size, GNUTLS_MASTER_SIZE,
246
0
          session->security_parameters.master_secret);
247
0
    if (ret < 0)
248
0
      _gnutls_memory_mark_undefined(
249
0
        session->security_parameters.master_secret,
250
0
        GNUTLS_MASTER_SIZE);
251
252
0
    gnutls_free(shash.data);
253
0
  }
254
255
0
  if (!keep_premaster)
256
0
    _gnutls_free_temp_key_datum(premaster);
257
258
0
  if (ret < 0)
259
0
    return ret;
260
261
0
  ret = _gnutls_call_keylog_func(
262
0
    session, "CLIENT_RANDOM",
263
0
    session->security_parameters.master_secret, GNUTLS_MASTER_SIZE);
264
0
  if (ret < 0)
265
0
    return gnutls_assert_val(ret);
266
267
0
  _gnutls_hard_log(
268
0
    "INT: MASTER SECRET[%d]: %s\n", GNUTLS_MASTER_SIZE,
269
0
    _gnutls_bin2hex(session->security_parameters.master_secret,
270
0
        GNUTLS_MASTER_SIZE, buf, sizeof(buf), NULL));
271
272
0
  return ret;
273
0
}
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
0
{
281
0
  gnutls_buffer_st buf;
282
0
  int ret = 0;
283
0
  mbuffer_st *bufel = NULL;
284
285
0
  if (session->internals.auth_struct->gnutls_generate_server_kx == NULL)
286
0
    return 0;
287
288
0
  if (again == 0) {
289
0
    ret = _gnutls_buffer_init_handshake_mbuffer(&buf);
290
0
    if (ret < 0)
291
0
      return gnutls_assert_val(ret);
292
293
0
    ret = session->internals.auth_struct->gnutls_generate_server_kx(
294
0
      session, &buf);
295
296
0
    if (ret == GNUTLS_E_INT_RET_0) {
297
0
      gnutls_assert();
298
0
      ret = 0;
299
0
      goto cleanup;
300
0
    }
301
302
0
    if (ret < 0) {
303
0
      gnutls_assert();
304
0
      goto cleanup;
305
0
    }
306
307
0
    bufel = _gnutls_buffer_to_mbuffer(&buf);
308
0
  }
309
310
0
  return _gnutls_send_handshake(session, bufel,
311
0
              GNUTLS_HANDSHAKE_SERVER_KEY_EXCHANGE);
312
313
0
cleanup:
314
0
  _gnutls_buffer_clear(&buf);
315
0
  return ret;
316
0
}
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
0
{
323
0
  gnutls_buffer_st buf;
324
0
  int ret = 0;
325
0
  mbuffer_st *bufel = NULL;
326
327
0
  if (session->internals.auth_struct->gnutls_generate_server_crt_request ==
328
0
      NULL)
329
0
    return 0;
330
331
0
  if (session->internals.send_cert_req <= 0)
332
0
    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
0
{
364
0
  gnutls_buffer_st buf;
365
0
  int ret = 0;
366
0
  mbuffer_st *bufel = NULL;
367
368
0
  if (session->internals.auth_struct->gnutls_generate_client_kx == NULL)
369
0
    return 0;
370
371
0
  if (again == 0) {
372
0
    ret = _gnutls_buffer_init_handshake_mbuffer(&buf);
373
0
    if (ret < 0)
374
0
      return gnutls_assert_val(ret);
375
376
0
    ret = session->internals.auth_struct->gnutls_generate_client_kx(
377
0
      session, &buf);
378
0
    if (ret < 0) {
379
0
      gnutls_assert();
380
0
      goto cleanup;
381
0
    }
382
383
0
    bufel = _gnutls_buffer_to_mbuffer(&buf);
384
0
  }
385
386
0
  return _gnutls_send_handshake(session, bufel,
387
0
              GNUTLS_HANDSHAKE_CLIENT_KEY_EXCHANGE);
388
389
0
cleanup:
390
0
  _gnutls_buffer_clear(&buf);
391
0
  return ret;
392
0
}
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
0
{
399
0
  gnutls_buffer_st buf;
400
0
  int ret = 0;
401
0
  mbuffer_st *bufel = NULL;
402
403
  /* This is a packet that is only sent by the client
404
   */
405
0
  if (session->security_parameters.entity == GNUTLS_SERVER)
406
0
    return 0;
407
408
  /* if certificate verify is not needed just exit 
409
   */
410
0
  if (!(session->internals.hsk_flags & HSK_CRT_ASKED))
411
0
    return 0;
412
413
0
  if (session->internals.auth_struct->gnutls_generate_client_crt_vrfy ==
414
0
      NULL) {
415
0
    gnutls_assert();
416
0
    return 0; /* this algorithm does not support cli_crt_vrfy 
417
         */
418
0
  }
419
420
0
  if (again == 0) {
421
0
    ret = _gnutls_buffer_init_handshake_mbuffer(&buf);
422
0
    if (ret < 0)
423
0
      return gnutls_assert_val(ret);
424
425
0
    ret = session->internals.auth_struct
426
0
            ->gnutls_generate_client_crt_vrfy(session, &buf);
427
0
    if (ret < 0) {
428
0
      gnutls_assert();
429
0
      goto cleanup;
430
0
    }
431
432
0
    if (ret == 0)
433
0
      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
0
cleanup:
442
0
  _gnutls_buffer_clear(&buf);
443
0
  return ret;
444
0
}
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
0
{
450
0
  gnutls_buffer_st buf;
451
0
  int ret = 0;
452
0
  mbuffer_st *bufel = NULL;
453
454
0
  if (!(session->internals.hsk_flags & HSK_CRT_ASKED))
455
0
    return 0;
456
457
0
  if (session->internals.auth_struct->gnutls_generate_client_certificate ==
458
0
      NULL)
459
0
    return 0;
460
461
0
  if (again == 0) {
462
0
    ret = _gnutls_buffer_init_handshake_mbuffer(&buf);
463
0
    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
0
    {
471
      /* TLS 1.x or SSL 3.0 with a valid certificate 
472
       */
473
0
      ret = session->internals.auth_struct
474
0
              ->gnutls_generate_client_certificate(
475
0
                session, &buf);
476
477
0
      if (ret < 0) {
478
0
        gnutls_assert();
479
0
        goto cleanup;
480
0
      }
481
0
    }
482
483
0
    bufel = _gnutls_buffer_to_mbuffer(&buf);
484
0
  }
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
0
    return _gnutls_send_handshake(session, bufel,
500
0
                GNUTLS_HANDSHAKE_CERTIFICATE_PKT);
501
502
0
cleanup:
503
0
  _gnutls_buffer_clear(&buf);
504
0
  return ret;
505
0
}
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
0
{
511
0
  gnutls_buffer_st buf;
512
0
  int ret = 0;
513
0
  mbuffer_st *bufel = NULL;
514
515
0
  if (session->internals.auth_struct->gnutls_generate_server_certificate ==
516
0
      NULL)
517
0
    return 0;
518
519
0
  if (again == 0) {
520
0
    ret = _gnutls_buffer_init_handshake_mbuffer(&buf);
521
0
    if (ret < 0)
522
0
      return gnutls_assert_val(ret);
523
524
0
    ret = session->internals.auth_struct
525
0
            ->gnutls_generate_server_certificate(session,
526
0
                   &buf);
527
528
0
    if (ret < 0) {
529
0
      gnutls_assert();
530
0
      goto cleanup;
531
0
    }
532
533
0
    bufel = _gnutls_buffer_to_mbuffer(&buf);
534
0
  }
535
536
0
  return _gnutls_send_handshake(session, bufel,
537
0
              GNUTLS_HANDSHAKE_CERTIFICATE_PKT);
538
539
0
cleanup:
540
0
  _gnutls_buffer_clear(&buf);
541
0
  return ret;
542
0
}
543
544
int _gnutls_recv_server_kx_message(gnutls_session_t session)
545
0
{
546
0
  gnutls_buffer_st buf;
547
0
  int ret = 0;
548
0
  unsigned int optflag = 0;
549
550
0
  if (session->internals.auth_struct->gnutls_process_server_kx != NULL) {
551
    /* Server key exchange packet is optional for PSK. */
552
0
    if (_gnutls_session_is_psk(session))
553
0
      optflag = 1;
554
555
0
    ret = _gnutls_recv_handshake(
556
0
      session, GNUTLS_HANDSHAKE_SERVER_KEY_EXCHANGE, optflag,
557
0
      &buf);
558
0
    if (ret < 0) {
559
0
      gnutls_assert();
560
0
      return ret;
561
0
    }
562
563
0
    ret = session->internals.auth_struct->gnutls_process_server_kx(
564
0
      session, buf.data, buf.length);
565
0
    _gnutls_buffer_clear(&buf);
566
567
0
    if (ret < 0) {
568
0
      gnutls_assert();
569
0
      return ret;
570
0
    }
571
0
  }
572
0
  return ret;
573
0
}
574
575
int _gnutls_recv_server_crt_request(gnutls_session_t session)
576
0
{
577
0
  gnutls_buffer_st buf;
578
0
  int ret = 0;
579
580
0
  if (session->internals.auth_struct->gnutls_process_server_crt_request !=
581
0
      NULL) {
582
0
    ret = _gnutls_recv_handshake(
583
0
      session, GNUTLS_HANDSHAKE_CERTIFICATE_REQUEST, 1, &buf);
584
0
    if (ret < 0)
585
0
      return ret;
586
587
0
    if (ret == 0 && buf.length == 0) {
588
0
      _gnutls_buffer_clear(&buf);
589
0
      return 0; /* ignored */
590
0
    }
591
592
0
    ret = session->internals.auth_struct
593
0
            ->gnutls_process_server_crt_request(
594
0
              session, buf.data, buf.length);
595
0
    _gnutls_buffer_clear(&buf);
596
0
    if (ret < 0)
597
0
      return ret;
598
0
  }
599
0
  return ret;
600
0
}
601
602
int _gnutls_recv_client_kx_message(gnutls_session_t session)
603
0
{
604
0
  gnutls_buffer_st buf;
605
0
  int ret = 0;
606
607
  /* Do key exchange only if the algorithm permits it */
608
0
  if (session->internals.auth_struct->gnutls_process_client_kx != NULL) {
609
0
    ret = _gnutls_recv_handshake(
610
0
      session, GNUTLS_HANDSHAKE_CLIENT_KEY_EXCHANGE, 0, &buf);
611
0
    if (ret < 0)
612
0
      return ret;
613
614
0
    ret = session->internals.auth_struct->gnutls_process_client_kx(
615
0
      session, buf.data, buf.length);
616
0
    _gnutls_buffer_clear(&buf);
617
0
    if (ret < 0)
618
0
      return ret;
619
0
  }
620
621
0
  return ret;
622
0
}
623
624
int _gnutls_recv_client_certificate(gnutls_session_t session)
625
0
{
626
0
  gnutls_buffer_st buf;
627
0
  int ret = 0;
628
0
  int optional;
629
630
0
  if (session->internals.auth_struct->gnutls_process_client_certificate ==
631
0
      NULL)
632
0
    return 0;
633
634
  /* if we have not requested a certificate then just return
635
   */
636
0
  if (session->internals.send_cert_req == 0) {
637
0
    return 0;
638
0
  }
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
0
{
708
0
  gnutls_buffer_st buf;
709
0
  int ret = 0;
710
711
0
  if (session->internals.auth_struct->gnutls_process_server_certificate !=
712
0
      NULL) {
713
0
    ret = _gnutls_recv_handshake(
714
0
      session, GNUTLS_HANDSHAKE_CERTIFICATE_PKT, 0, &buf);
715
0
    if (ret < 0) {
716
0
      gnutls_assert();
717
0
      return ret;
718
0
    }
719
720
0
    ret = session->internals.auth_struct
721
0
            ->gnutls_process_server_certificate(
722
0
              session, buf.data, buf.length);
723
0
    _gnutls_buffer_clear(&buf);
724
0
    if (ret < 0) {
725
0
      gnutls_assert();
726
0
      return ret;
727
0
    }
728
0
  }
729
730
0
  return ret;
731
0
}
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
0
{
738
0
  gnutls_buffer_st buf;
739
0
  int ret = 0;
740
741
0
  if (session->internals.auth_struct->gnutls_process_client_crt_vrfy ==
742
0
      NULL)
743
0
    return 0;
744
745
0
  if (session->internals.send_cert_req == 0 ||
746
0
      (!(session->internals.hsk_flags & HSK_CRT_VRFY_EXPECTED))) {
747
0
    return 0;
748
0
  }
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
}