summaryrefslogtreecommitdiff
path: root/lib/gnutls_int.h
blob: f68a01380e995560db5e2ace64b40b3010cde4f8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
/*
 * Copyright (C) 2000-2012 Free Software Foundation, Inc.
 *
 * Author: Nikos Mavrogiannopoulos
 *
 * This file is part of GnuTLS.
 *
 * The GnuTLS is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 3 of
 * the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 *
 */

#ifndef GNUTLS_INT_H
#define GNUTLS_INT_H

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <limits.h>
#include <stdint.h>

#ifdef NO_SSIZE_T
#define HAVE_SSIZE_T
typedef int ssize_t;
#endif

#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#if HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#elif HAVE_WS2TCPIP_H
# include <ws2tcpip.h>
#endif
#include <time.h>
#include <u64.h> /* gnulib for uint64_t */

#ifdef HAVE_LIBNETTLE
# include <nettle/memxor.h>
#else
# include <gl/memxor.h>
# define memxor gl_memxor
#endif

#ifdef __GNUC__
# ifndef _GNUTLS_GCC_VERSION
#  define _GNUTLS_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
# endif
# if _GNUTLS_GCC_VERSION >= 30100
#  define likely(x)      __builtin_expect((x), 1)
#  define unlikely(x)    __builtin_expect((x), 0)
# endif
#endif

#ifndef likely
# define likely
# define unlikely
#endif

/* some systems had problems with long long int, thus,
 * it is not used.
 */
typedef struct
{
  unsigned char i[8];
} uint64;

#include <gnutls/gnutls.h>
#include <gnutls/abstract.h>
#include <system.h>

/*
 * They are not needed any more. You can simply enable
 * the gnutls_log callback to get error descriptions.

#define BUFFERS_DEBUG
#define WRITE_DEBUG
#define READ_DEBUG
#define HANDSHAKE_DEBUG // Prints some information on handshake 
#define COMPRESSION_DEBUG
#define DEBUG
*/

/* The size of a handshake message should not
 * be larger than this value.
 */
#define MAX_HANDSHAKE_PACKET_SIZE 48*1024

#define TLS_MAX_SESSION_ID_SIZE 32

/* The maximum digest size of hash algorithms. 
 */
#define MAX_HASH_SIZE 64
#define MAX_CIPHER_BLOCK_SIZE 16
#define MAX_CIPHER_KEY_SIZE 32

#define MAX_USERNAME_SIZE 128
#define MAX_SERVER_NAME_SIZE 128

#define SESSION_TICKET_KEY_NAME_SIZE 16
#define SESSION_TICKET_KEY_SIZE 16
#define SESSION_TICKET_IV_SIZE 16
#define SESSION_TICKET_MAC_SECRET_SIZE 32

#define AEAD_EXPLICIT_DATA_SIZE 8
#define AEAD_IMPLICIT_DATA_SIZE 4

#define GNUTLS_MASTER_SIZE 48
#define GNUTLS_RANDOM_SIZE 32

/* TLS Extensions */
/* we can receive up to MAX_EXT_TYPES extensions.
 */
#define MAX_EXT_TYPES 32

  /**
   * gnutls_ext_parse_type_t:
   * @GNUTLS_EXT_NONE: Never parsed
   * @GNUTLS_EXT_ANY: Any extension type.
   * @GNUTLS_EXT_APPLICATION: Application extension.
   * @GNUTLS_EXT_TLS: TLS-internal extension.
   * @GNUTLS_EXT_MANDATORY: Extension parsed even if resuming (or extensions are disabled).
   *
   * Enumeration of different TLS extension types.  This flag
   * indicates for an extension whether it is useful to application
   * level or TLS level only.  This is (only) used to parse the
   * application level extensions before the "client_hello" callback
   * is called.
   */
  typedef enum
  {
    GNUTLS_EXT_ANY = 0,
    GNUTLS_EXT_APPLICATION = 1,
    GNUTLS_EXT_TLS = 2,
    GNUTLS_EXT_MANDATORY = 3,
    GNUTLS_EXT_NONE = 4
  } gnutls_ext_parse_type_t;


/* expire time for resuming sessions */
#define DEFAULT_EXPIRE_TIME 3600

typedef enum transport_t
{
  GNUTLS_STREAM,
  GNUTLS_DGRAM
} transport_t;

/* the maximum size of encrypted packets */
#define IS_DTLS(session) (session->internals.transport == GNUTLS_DGRAM)

#define DEFAULT_MAX_RECORD_SIZE 16384
#define TLS_RECORD_HEADER_SIZE 5
#define DTLS_RECORD_HEADER_SIZE (TLS_RECORD_HEADER_SIZE+8)
#define RECORD_HEADER_SIZE(session) (IS_DTLS(session) ? DTLS_RECORD_HEADER_SIZE : TLS_RECORD_HEADER_SIZE)
#define MAX_RECORD_HEADER_SIZE DTLS_RECORD_HEADER_SIZE

#define MAX_RECORD_SEND_SIZE(session) (IS_DTLS(session)?((size_t)session->internals.dtls.mtu-DTLS_RECORD_HEADER_SIZE):(size_t)session->security_parameters.max_record_send_size)
#define MAX_RECORD_RECV_SIZE(session) ((size_t)session->security_parameters.max_record_recv_size)
#define MAX_PAD_SIZE 255
#define EXTRA_COMP_SIZE 2048
#define MAX_RECORD_OVERHEAD (MAX_CIPHER_BLOCK_SIZE/*iv*/+MAX_PAD_SIZE+EXTRA_COMP_SIZE+MAX_HASH_SIZE/*MAC*/)
#define MAX_RECV_SIZE(session) (MAX_RECORD_OVERHEAD+MAX_RECORD_RECV_SIZE(session)+RECORD_HEADER_SIZE(session))

#define TLS_HANDSHAKE_HEADER_SIZE 4
#define DTLS_HANDSHAKE_HEADER_SIZE (TLS_HANDSHAKE_HEADER_SIZE+8)
#define HANDSHAKE_HEADER_SIZE(session) (IS_DTLS(session) ? DTLS_HANDSHAKE_HEADER_SIZE : TLS_HANDSHAKE_HEADER_SIZE)
#define MAX_HANDSHAKE_HEADER_SIZE DTLS_HANDSHAKE_HEADER_SIZE

/* This is the maximum handshake message size we send without
   fragmentation. This currently ignores record layer overhead. */
#define DTLS_DEFAULT_MTU 1200

/* the maximum size of the DTLS cookie */
#define DTLS_MAX_COOKIE_SIZE 32

/* The maximum number of HELLO_VERIFY_REQUEST messages the client
   processes before aborting. */
#define MAX_HANDSHAKE_HELLO_VERIFY_REQUESTS 5

/* defaults for verification functions
 */
#define DEFAULT_VERIFY_DEPTH 32
#define DEFAULT_VERIFY_BITS 16*1024

#include <gnutls_mem.h>

#define MEMSUB(x,y) ((ssize_t)((ptrdiff_t)x-(ptrdiff_t)y))

#define DECR_LEN(len, x) do { len-=x; if (len<0) {gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;} } while (0)
#define DECR_LENGTH_RET(len, x, RET) do { len-=x; if (len<0) {gnutls_assert(); return RET;} } while (0)
#define DECR_LENGTH_COM(len, x, COM) do { len-=x; if (len<0) {gnutls_assert(); COM;} } while (0)

#define GNUTLS_POINTER_TO_INT(_) ((int) GNUTLS_POINTER_TO_INT_CAST (_))
#define GNUTLS_INT_TO_POINTER(_) ((void*) GNUTLS_POINTER_TO_INT_CAST (_))

typedef struct
{
  uint8_t pint[3];
} uint24;

#include <gnutls_mpi.h>

typedef enum handshake_state_t
{ STATE0 = 0, STATE1, STATE2,
  STATE3, STATE4, STATE5,
  STATE6, STATE7, STATE8, STATE9, STATE11 = 11,
  STATE20 = 20, STATE21, STATE22,
  STATE30 = 30, STATE31, STATE40 = 40, STATE41, STATE50 = 50,
  STATE60 = 60, STATE61, STATE62, STATE70, STATE71
} handshake_state_t;

#include <gnutls_str.h>

/* This is the maximum number of algorithms (ciphers or macs etc).
 * keep it synced with GNUTLS_MAX_ALGORITHM_NUM in gnutls.h
 */
#define MAX_ALGOS GNUTLS_MAX_ALGORITHM_NUM

typedef enum extensions_t
{
  GNUTLS_EXTENSION_SERVER_NAME = 0,
  GNUTLS_EXTENSION_MAX_RECORD_SIZE = 1,
  GNUTLS_EXTENSION_CERT_TYPE = 9,
  GNUTLS_EXTENSION_SUPPORTED_ECC = 10,
  GNUTLS_EXTENSION_SUPPORTED_ECC_PF = 11,
  GNUTLS_EXTENSION_SRP = 12,
  GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS = 13,
  GNUTLS_EXTENSION_SESSION_TICKET = 35,
  GNUTLS_EXTENSION_SAFE_RENEGOTIATION = 65281   /* aka: 0xff01 */
} extensions_t;

typedef enum
{ CIPHER_STREAM, CIPHER_BLOCK } cipher_type_t;

#define RESUME_TRUE 1
#define RESUME_FALSE 0

/* Record Protocol */
typedef enum content_type_t
{
  GNUTLS_CHANGE_CIPHER_SPEC = 20, GNUTLS_ALERT,
  GNUTLS_HANDSHAKE, GNUTLS_APPLICATION_DATA,
} content_type_t;


#define GNUTLS_PK_ANY (gnutls_pk_algorithm_t)-1
#define GNUTLS_PK_NONE (gnutls_pk_algorithm_t)-2

/* Message buffers (mbuffers) structures */

/* this is actually the maximum number of distinct handshake
 * messages that can arrive in a single flight
 */
#define MAX_HANDSHAKE_MSGS 6
typedef struct
{
  /* Handshake layer type and sequence of message */
  gnutls_handshake_description_t htype;
  uint32_t length;

  /* valid in DTLS */
  uint16_t sequence;

  /* indicate whether that message is complete.
   * complete means start_offset == 0 and end_offset == length
   */
  uint32_t start_offset;
  uint32_t end_offset;
  
  uint8_t header[MAX_HANDSHAKE_HEADER_SIZE];
  int header_size;

  gnutls_buffer_st data;
} handshake_buffer_st;

typedef struct mbuffer_st
{
  /* when used in mbuffer_head_st */
  struct mbuffer_st *next;
  struct mbuffer_st *prev;

  /* msg->size - mark = number of bytes left to process in this
     message. Mark should only be non-zero when this buffer is the
     head of the queue. */
  size_t mark;


  /* the data */
  gnutls_datum_t msg;
  size_t maximum_size;

  /* used during fill in, to separate header from data
   * body. */
  unsigned int user_mark;

  /* Filled in by record layer on recv:
   * type, record_sequence
   */

  /* record layer content type */
  content_type_t type;

  /* record layer sequence */
  uint64 record_sequence;

  /* Filled in by handshake layer on send:
   * type, epoch, htype, handshake_sequence
   */

  /* Record layer epoch of message */
  uint16_t epoch;

  /* Handshake layer type and sequence of message */
  gnutls_handshake_description_t htype;
  uint16_t handshake_sequence;
} mbuffer_st;

typedef struct mbuffer_head_st
{
  mbuffer_st *head;
  mbuffer_st *tail;

  unsigned int length;
  size_t byte_length;
} mbuffer_head_st;

/* Store & Retrieve functions defines: 
 */

typedef struct auth_cred_st
{
  gnutls_credentials_type_t algorithm;

  /* the type of credentials depends on algorithm 
   */
  void *credentials;
  struct auth_cred_st *next;
} auth_cred_st;

struct gnutls_key_st
{
  /* For ECDH KX */
  gnutls_pk_params_st ecdh_params;
  bigint_t ecdh_x;
  bigint_t ecdh_y;

  /* For DH KX */
  gnutls_datum_t key;
  bigint_t KEY;
  bigint_t client_Y;
  bigint_t client_g;
  bigint_t client_p;
  bigint_t dh_secret;
  /* for SRP */
  bigint_t A;
  bigint_t B;
  bigint_t u;
  bigint_t b;
  bigint_t a;
  bigint_t x;
  /* RSA: e, m
   */
  bigint_t rsa[2];

  /* this is used to hold the peers authentication data 
   */
  /* auth_info_t structures SHOULD NOT contain malloced 
   * elements. Check gnutls_session_pack.c, and gnutls_auth.c.
   * Rememember that this should be calloced!
   */
  void *auth_info;
  gnutls_credentials_type_t auth_info_type;
  int auth_info_size;           /* needed in order to store to db for restoring 
                                 */
  uint8_t crypt_algo;

  auth_cred_st *cred;           /* used to specify keys/certificates etc */

  int certificate_requested;
  /* some ciphersuites use this
   * to provide client authentication.
   * 1 if client auth was requested
   * by the peer, 0 otherwise
   *** In case of a server this
   * holds 1 if we should wait
   * for a client certificate verify
   */
};
typedef struct gnutls_key_st *gnutls_key_st;


struct record_state_st;
typedef struct record_state_st record_state_st;

struct record_parameters_st;
typedef struct record_parameters_st record_parameters_st;

/* STATE (cont) */

#include <gnutls_hash_int.h>
#include <gnutls_cipher_int.h>
#include <gnutls_compress.h>

typedef struct
{
  uint8_t hash_algorithm;
  uint8_t sign_algorithm;       /* pk algorithm actually */
} sign_algorithm_st;

/* This structure holds parameters got from TLS extension
 * mechanism. (some extensions may hold parameters in auth_info_t
 * structures also - see SRP).
 */

#define MAX_SIGNATURE_ALGORITHMS 16
#define MAX_SIGN_ALGO_SIZE (2 + MAX_SIGNATURE_ALGORITHMS * 2)

#define MAX_VERIFY_DATA_SIZE 36 /* in SSL 3.0, 12 in TLS 1.0 */

/* auth_info_t structures now MAY contain malloced 
 * elements.
 */

/* This structure and auth_info_t, are stored in the resume database,
 * and are restored, in case of resume.
 * Holds all the required parameters to resume the current 
 * session.
 */

/* if you add anything in Security_Parameters struct, then
 * also modify CPY_COMMON in gnutls_constate.c. 
 */

/* Note that the security parameters structure is set up after the
 * handshake has finished. The only value you may depend on while
 * the handshake is in progress is the cipher suite value.
 */
typedef struct
{
  unsigned int entity; /* GNUTLS_SERVER or GNUTLS_CLIENT */
  gnutls_kx_algorithm_t kx_algorithm;

  /* The epoch used to read and write */
  uint16_t epoch_read;
  uint16_t epoch_write;

  /* The epoch that the next handshake will initialize. */
  uint16_t epoch_next;

  /* The epoch at index 0 of record_parameters. */
  uint16_t epoch_min;

  /* this is the ciphersuite we are going to use 
   * moved here from internals in order to be restored
   * on resume;
   */
  uint8_t cipher_suite[2];
  gnutls_compression_method_t compression_method;
  uint8_t master_secret[GNUTLS_MASTER_SIZE];
  uint8_t client_random[GNUTLS_RANDOM_SIZE];
  uint8_t server_random[GNUTLS_RANDOM_SIZE];
  uint8_t session_id[TLS_MAX_SESSION_ID_SIZE];
  uint8_t session_id_size;
  time_t timestamp;

  /* The send size is the one requested by the programmer.
   * The recv size is the one negotiated with the peer.
   */
  uint16_t max_record_send_size;
  uint16_t max_record_recv_size;
  /* holds the negotiated certificate type */
  gnutls_certificate_type_t cert_type;
  gnutls_ecc_curve_t ecc_curve; /* holds the first supported ECC curve requested by client */
  gnutls_protocol_t version;    /* moved here */

  /* FIXME: The following are not saved in the session storage
   * for session resumption.
   */

  /* Used by extensions that enable supplemental data: Which ones
   * do that? Do they belong in security parameters?
   */
  int do_recv_supplemental, do_send_supplemental;
} security_parameters_st;

struct record_state_st
{
  gnutls_datum_t mac_secret;
  gnutls_datum_t IV;
  gnutls_datum_t key;
  auth_cipher_hd_st cipher_state;
  comp_hd_st compression_state;
  uint64 sequence_number;
};

/* These are used to resolve relative epochs. These values are just
   outside the 16 bit range to prevent off-by-one errors. An absolute
   epoch may be referred to by its numeric id in the range
   0x0000-0xffff. */
#define EPOCH_READ_CURRENT  70000
#define EPOCH_WRITE_CURRENT 70001
#define EPOCH_NEXT          70002

struct record_parameters_st
{
  uint16_t epoch;
  int initialized;

  gnutls_cipher_algorithm_t cipher_algorithm;
  gnutls_mac_algorithm_t mac_algorithm;
  gnutls_compression_method_t compression_algorithm;

  record_state_st read;
  record_state_st write;
  
  /* Whether this state is in use, i.e., if there is
     a pending handshake message waiting to be encrypted
     under this epoch's parameters.
   */
  int usage_cnt;
};

typedef struct
{
  unsigned int priority[MAX_ALGOS];
  unsigned int algorithms;
} priority_st;

typedef enum
{
  SR_DISABLED,
  SR_UNSAFE,
  SR_PARTIAL,
  SR_SAFE
} safe_renegotiation_t;

/* For the external api */
struct gnutls_priority_st
{
  priority_st cipher;
  priority_st mac;
  priority_st kx;
  priority_st compression;
  priority_st protocol;
  priority_st cert_type;
  priority_st sign_algo;
  priority_st supported_ecc;

  /* to disable record padding */
  unsigned int no_extensions:1;
  unsigned int no_padding:1;
  unsigned int allow_large_records:1;
  safe_renegotiation_t sr;
  unsigned int ssl3_record_version:1;
  unsigned int server_precedence:1;
  unsigned int additional_verify_flags;
};


/* DH and RSA parameters types.
 */
typedef struct gnutls_dh_params_int
{
  /* [0] is the prime, [1] is the generator.
   */
  bigint_t params[2];
  int q_bits; /* length of q in bits. If zero then length is unknown.
              */
} dh_params_st;

typedef struct
{
  gnutls_dh_params_t dh_params;
  int free_dh_params;
  gnutls_rsa_params_t rsa_params;
  int free_rsa_params;
} internal_params_st;

#define DTLS_RECORD_WINDOW_SIZE 64

/* DTLS session state
 */
typedef struct
{
  /* HelloVerifyRequest DOS prevention cookie */
  uint8_t  cookie[DTLS_MAX_COOKIE_SIZE];
  uint8_t cookie_len;

  /* For DTLS handshake fragmentation and reassembly. */
  uint16_t hsk_write_seq;
  unsigned int hsk_read_seq;
  uint16_t mtu;

  /* a flight transmission is in process */
  unsigned int flight_init:1;
  /* whether this is the last flight in the protocol  */
  unsigned int last_flight:1;
  unsigned int retrans_timeout;
  unsigned int total_timeout;

  unsigned int hsk_hello_verify_requests;
  
  uint64_t record_sw[DTLS_RECORD_WINDOW_SIZE];
  unsigned int record_sw_size;

  /* non blocking stuff variables */
  unsigned int blocking:1;
  /* starting time of current handshake */
  time_t handshake_start_time;
  /* time in seconds of the last handshake call */
  time_t handshake_last_call;
  /* The actual retrans_timeout for the next message (e.g. doubled or so) */
  unsigned int actual_retrans_timeout;

  /* timers to handle async handshake after gnutls_handshake()
   * has terminated. Required to handle retransmissions.
   */
  time_t async_term;
  
  /* last retransmission triggered by record layer */
  time_t last_retransmit;
  unsigned int packets_dropped;
} dtls_st;


typedef union
{
  void *ptr;
  uint32_t num;
} extension_priv_data_t;

typedef struct
{
  /* holds all the data received by the record layer */
  mbuffer_head_st record_buffer; 

  int handshake_hash_buffer_prev_len;           /* keeps the length of handshake_hash_buffer, excluding
                                                 * the last received message */
  gnutls_buffer_st handshake_hash_buffer;       /* used to keep the last received handshake 
                                                 * message */
  unsigned int resumable:1;              /* TRUE or FALSE - if we can resume that session */
  unsigned int ticket_sent:1;            /* whether a session ticket was sent */
  handshake_state_t handshake_state;    /* holds
                                         * a number which indicates where
                                         * the handshake procedure has been
                                         * interrupted. If it is 0 then
                                         * no interruption has happened.
                                         */

  int invalid_connection:1;     /* true or FALSE - if this session is valid */

  int may_not_read:1;           /* if it's 0 then we can read/write, otherwise it's forbiden to read/write
                                 */
  int may_not_write:1;
  int read_eof:1;               /* non-zero if we have received a closure alert. */

  int last_alert;               /* last alert received */

  /* The last handshake messages sent or received.
   */
  int last_handshake_in;
  int last_handshake_out;

  /* priorities */
  struct gnutls_priority_st priorities;

  /* resumed session */
  unsigned int resumed:1;  /* RESUME_TRUE or FALSE - if we are resuming a session */
  unsigned int resumption_requested:1; /* non-zero if resumption was requested by client */
  security_parameters_st resumed_security_parameters;

  /* These buffers are used in the handshake
   * protocol only. freed using _gnutls_handshake_io_buffer_clear();
   */
  mbuffer_head_st handshake_send_buffer;
  handshake_buffer_st handshake_recv_buffer[MAX_HANDSHAKE_MSGS];
  int handshake_recv_buffer_size;

  /* this buffer holds a record packet -mostly used for
   * non blocking IO.
   */
  mbuffer_head_st record_recv_buffer;   /* buffer holding the record that is currently being received */
  mbuffer_head_st record_send_buffer;   /* holds cached data
                                         * for the gnutls_io_write_buffered()
                                         * function.
                                         */
  size_t record_send_buffer_user_size;  /* holds the
                                         * size of the user specified data to
                                         * send.
                                         */

  int expire_time;              /* after expire_time seconds this session will expire */
  struct mod_auth_st_int *auth_struct;  /* used in handshake packets and KX algorithms */

  /* this is the highest version available
   * to the peer. (advertized version).
   * This is obtained by the Handshake Client Hello 
   * message. (some implementations read the Record version)
   */
  uint8_t adv_version_major;
  uint8_t adv_version_minor;

  /* if this is non zero a certificate request message
   * will be sent to the client. - only if the ciphersuite
   * supports it.
   */
  int send_cert_req;

  /* bits to use for DHE and DHA 
   * use _gnutls_dh_get_prime_bits() and gnutls_dh_set_prime_bits() 
   * to access it.
   */
  uint16_t dh_prime_bits;

  size_t max_handshake_data_buffer_size;

  /* PUSH & PULL functions.
   */
  gnutls_pull_timeout_func pull_timeout_func;
  gnutls_pull_func pull_func;
  gnutls_push_func push_func;
  gnutls_vec_push_func vec_push_func;
  gnutls_errno_func errno_func;
  /* Holds the first argument of PUSH and PULL
   * functions;
   */
  gnutls_transport_ptr_t transport_recv_ptr;
  gnutls_transport_ptr_t transport_send_ptr;

  /* STORE & RETRIEVE functions. Only used if other
   * backend than gdbm is used.
   */
  gnutls_db_store_func db_store_func;
  gnutls_db_retr_func db_retrieve_func;
  gnutls_db_remove_func db_remove_func;
  void *db_ptr;

  /* post client hello callback (server side only)
   */
  gnutls_handshake_post_client_hello_func user_hello_func;

  /* holds the selected certificate and key.
   * use _gnutls_selected_certs_deinit() and _gnutls_selected_certs_set()
   * to change them.
   */
  gnutls_pcert_st *selected_cert_list;
  int selected_cert_list_length;
  struct gnutls_privkey_st *selected_key;
  int selected_need_free:1;

  /* holds the extensions we sent to the peer
   * (in case of a client)
   */
  uint16_t extensions_sent[MAX_EXT_TYPES];
  uint16_t extensions_sent_size;

  /* is 0 if we are to send the whole PGP key, or non zero
   * if the fingerprint is to be sent.
   */
  int pgp_fingerprint;

  /* This holds the default version that our first
   * record packet will have. */
  uint8_t default_record_version[2];

  void *user_ptr;

  int enable_private;           /* non zero to
                                 * enable cipher suites
                                 * which have 0xFF status.
                                 */

  /* Holds 0 if the last called function was interrupted while
   * receiving, and non zero otherwise.
   */
  int direction;

  /* This callback will be used (if set) to receive an
   * openpgp key. (if the peer sends a fingerprint)
   */
  gnutls_openpgp_recv_key_func openpgp_recv_key_func;

  /* If non zero the server will not advertize the CA's he
   * trusts (do not send an RDN sequence).
   */
  int ignore_rdn_sequence;

  /* This is used to set an arbitary version in the RSA
   * PMS secret. Can be used by clients to test whether the
   * server checks that version. (** only used in gnutls-cli-debug)
   */
  uint8_t rsa_pms_version[2];

  /* Here we cache the DH or RSA parameters got from the
   * credentials structure, or from a callback. That is to
   * minimize external calls.
   */
  internal_params_st params;

  /* To avoid using global variables, and especially on Windows where
   * the application may use a different errno variable than GnuTLS,
   * it is possible to use gnutls_transport_set_errno to set a
   * session-specific errno variable in the user-replaceable push/pull
   * functions.  This value is used by the send/recv functions.  (The
   * strange name of this variable is because 'errno' is typically
   * #define'd.)
   */
  int errnum;

  /* Function used to perform public-key signing operation during
     handshake.  Used by gnutls_sig.c:_gnutls_tls_sign(), see also
     gnutls_sign_callback_set(). */
  gnutls_sign_func sign_func;
  void *sign_func_userdata;

  /* minimum bits to allow for SRP
   * use gnutls_srp_set_prime_bits() to adjust it.
   */
  uint16_t srp_prime_bits;

  /* A handshake process has been completed */
  int initial_negotiation_completed:1;

  struct
  {
    uint16_t type;
    extension_priv_data_t priv;
    int set:1;
  } extension_int_data[MAX_EXT_TYPES];

  struct
  {
    uint16_t type;
    extension_priv_data_t priv;
    int set:1;
  } resumed_extension_int_data[MAX_EXT_TYPES];
  /* The type of transport protocol; stream or datagram */
  transport_t transport;

  /* DTLS session state */
  dtls_st dtls;

  unsigned int cb_tls_unique_len;
  unsigned char cb_tls_unique[MAX_VERIFY_DATA_SIZE];

  /* If you add anything here, check _gnutls_handshake_internal_state_clear().
   */
} internals_st;

/* Maximum number of epochs we keep around. */
#define MAX_EPOCH_INDEX 16

struct gnutls_session_int
{
  security_parameters_st security_parameters;
  record_parameters_st *record_parameters[MAX_EPOCH_INDEX];
  internals_st internals;
  gnutls_key_st key;
};


/* functions 
 */
void _gnutls_free_auth_info (gnutls_session_t session);

/* These two macros return the advertized TLS version of
 * the peer.
 */
#define _gnutls_get_adv_version_major( session) \
	session->internals.adv_version_major

#define _gnutls_get_adv_version_minor( session) \
	session->internals.adv_version_minor

#define set_adv_version( session, major, minor) \
	session->internals.adv_version_major = major; \
	session->internals.adv_version_minor = minor

void _gnutls_set_adv_version (gnutls_session_t, gnutls_protocol_t);
gnutls_protocol_t _gnutls_get_adv_version (gnutls_session_t);

int _gnutls_is_secure_mem_null (const void *);

inline static gnutls_protocol_t
_gnutls_protocol_get_version (gnutls_session_t session)
{
  return session->security_parameters.version;
}

#define gnutls_protocol_get_version _gnutls_protocol_get_version

inline static void
_gnutls_set_current_version (gnutls_session_t session,
                             gnutls_protocol_t version)
{
  session->security_parameters.version = version;
}

#endif /* GNUTLS_INT_H */