Coverage Report

Created: 2023-03-26 07:33

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