2 * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2010 Free
3 * Software Foundation, Inc.
5 * Author: Nikos Mavrogiannopoulos
7 * This file is part of GnuTLS.
9 * The GnuTLS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
26 /* Functions that are supposed to run after the handshake procedure is
27 * finished. These functions activate the established security parameters.
30 #include <gnutls_int.h>
31 #include <gnutls_constate.h>
32 #include <gnutls_errors.h>
33 #include <gnutls_kx.h>
34 #include <gnutls_algorithms.h>
35 #include <gnutls_num.h>
36 #include <gnutls_datum.h>
37 #include <gnutls_state.h>
38 #include <gnutls_extensions.h>
39 #include <gnutls_buffers.h>
41 static const char keyexp
[] = "key expansion";
42 static const int keyexp_length
= sizeof (keyexp
) - 1;
44 static const char ivblock
[] = "IV block";
45 static const int ivblock_length
= sizeof (ivblock
) - 1;
47 static const char cliwrite
[] = "client write key";
48 static const int cliwrite_length
= sizeof (cliwrite
) - 1;
50 static const char servwrite
[] = "server write key";
51 static const int servwrite_length
= sizeof (servwrite
) - 1;
53 #define EXPORT_FINAL_KEY_SIZE 16
55 /* This function is to be called after handshake, when master_secret,
56 * client_random and server_random have been initialized.
57 * This function creates the keys and stores them into pending session.
58 * (session->cipher_specs)
61 _gnutls_set_keys (gnutls_session_t session
, record_parameters_st
* params
,
62 int hash_size
, int IV_size
, int key_size
, int export_flag
)
64 /* FIXME: This function is too long
66 opaque rnd
[2 * GNUTLS_RANDOM_SIZE
];
67 opaque rrnd
[2 * GNUTLS_RANDOM_SIZE
];
71 /* avoid using malloc */
72 opaque key_block
[2 * MAX_HASH_SIZE
+ 2 * MAX_CIPHER_KEY_SIZE
+
73 2 * MAX_CIPHER_BLOCK_SIZE
];
74 record_state_st
*client_write
, *server_write
;
77 session
->security_parameters
.entity
==
78 GNUTLS_CLIENT
? ¶ms
->write
: ¶ms
->read
;
80 session
->security_parameters
.entity
==
81 GNUTLS_SERVER
? ¶ms
->write
: ¶ms
->read
;
83 block_size
= 2 * hash_size
+ 2 * key_size
;
85 block_size
+= 2 * IV_size
;
87 memcpy (rnd
, session
->security_parameters
.server_random
,
89 memcpy (&rnd
[GNUTLS_RANDOM_SIZE
],
90 session
->security_parameters
.client_random
, GNUTLS_RANDOM_SIZE
);
92 memcpy (rrnd
, session
->security_parameters
.client_random
,
94 memcpy (&rrnd
[GNUTLS_RANDOM_SIZE
],
95 session
->security_parameters
.server_random
, GNUTLS_RANDOM_SIZE
);
97 if (session
->security_parameters
.version
== GNUTLS_SSL3
)
100 _gnutls_ssl3_generate_random
101 (session
->security_parameters
.master_secret
, GNUTLS_MASTER_SIZE
, rnd
,
102 2 * GNUTLS_RANDOM_SIZE
, block_size
, key_block
);
107 _gnutls_PRF (session
, session
->security_parameters
.master_secret
,
108 GNUTLS_MASTER_SIZE
, keyexp
, keyexp_length
,
109 rnd
, 2 * GNUTLS_RANDOM_SIZE
, block_size
, key_block
);
113 return gnutls_assert_val (ret
);
115 _gnutls_hard_log ("INT: KEY BLOCK[%d]: %s\n", block_size
,
116 _gnutls_bin2hex (key_block
, block_size
, buf
,
117 sizeof (buf
), NULL
));
123 if (_gnutls_sset_datum
124 (&client_write
->mac_secret
, &key_block
[pos
], hash_size
) < 0)
125 return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR
);
129 if (_gnutls_sset_datum
130 (&server_write
->mac_secret
, &key_block
[pos
], hash_size
) < 0)
131 return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR
);
138 opaque key1
[EXPORT_FINAL_KEY_SIZE
];
139 opaque key2
[EXPORT_FINAL_KEY_SIZE
];
140 opaque
*client_write_key
, *server_write_key
;
141 int client_write_key_size
, server_write_key_size
;
143 if (export_flag
== 0)
145 client_write_key
= &key_block
[pos
];
146 client_write_key_size
= key_size
;
150 server_write_key
= &key_block
[pos
];
151 server_write_key_size
= key_size
;
158 client_write_key
= key1
;
159 server_write_key
= key2
;
161 /* generate the final keys */
163 if (session
->security_parameters
.version
== GNUTLS_SSL3
)
166 _gnutls_ssl3_hash_md5 (&key_block
[pos
],
168 2 * GNUTLS_RANDOM_SIZE
,
169 EXPORT_FINAL_KEY_SIZE
,
176 _gnutls_PRF (session
, &key_block
[pos
], key_size
,
177 cliwrite
, cliwrite_length
,
179 2 * GNUTLS_RANDOM_SIZE
,
180 EXPORT_FINAL_KEY_SIZE
, client_write_key
);
184 return gnutls_assert_val (ret
);
186 client_write_key_size
= EXPORT_FINAL_KEY_SIZE
;
189 if (session
->security_parameters
.version
== GNUTLS_SSL3
)
192 _gnutls_ssl3_hash_md5 (&key_block
[pos
], key_size
,
193 rnd
, 2 * GNUTLS_RANDOM_SIZE
,
194 EXPORT_FINAL_KEY_SIZE
,
200 _gnutls_PRF (session
, &key_block
[pos
], key_size
,
201 servwrite
, servwrite_length
,
202 rrnd
, 2 * GNUTLS_RANDOM_SIZE
,
203 EXPORT_FINAL_KEY_SIZE
, server_write_key
);
207 return gnutls_assert_val (ret
);
209 server_write_key_size
= EXPORT_FINAL_KEY_SIZE
;
213 if (_gnutls_sset_datum
214 (&client_write
->key
, client_write_key
, client_write_key_size
) < 0)
215 return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR
);
217 _gnutls_hard_log ("INT: CLIENT WRITE KEY [%d]: %s\n",
218 client_write_key_size
,
219 _gnutls_bin2hex (client_write_key
,
220 client_write_key_size
, buf
,
221 sizeof (buf
), NULL
));
223 if (_gnutls_sset_datum
224 (&server_write
->key
, server_write_key
, server_write_key_size
) < 0)
225 return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR
);
227 _gnutls_hard_log ("INT: SERVER WRITE KEY [%d]: %s\n",
228 server_write_key_size
,
229 _gnutls_bin2hex (server_write_key
,
230 server_write_key_size
, buf
,
231 sizeof (buf
), NULL
));
236 /* IV generation in export and non export ciphers.
238 if (IV_size
> 0 && export_flag
== 0)
240 if (_gnutls_sset_datum
241 (&client_write
->IV
, &key_block
[pos
], IV_size
) < 0)
242 return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR
);
246 if (_gnutls_sset_datum
247 (&server_write
->IV
, &key_block
[pos
], IV_size
) < 0)
248 return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR
);
253 else if (IV_size
> 0 && export_flag
!= 0)
255 opaque iv_block
[MAX_CIPHER_BLOCK_SIZE
* 2];
257 if (session
->security_parameters
.version
== GNUTLS_SSL3
)
259 ret
= _gnutls_ssl3_hash_md5 ("", 0,
260 rrnd
, GNUTLS_RANDOM_SIZE
* 2,
264 return gnutls_assert_val (ret
);
267 ret
= _gnutls_ssl3_hash_md5 ("", 0, rnd
,
268 GNUTLS_RANDOM_SIZE
* 2,
269 IV_size
, &iv_block
[IV_size
]);
274 ret
= _gnutls_PRF (session
, "", 0,
275 ivblock
, ivblock_length
, rrnd
,
276 2 * GNUTLS_RANDOM_SIZE
, IV_size
* 2, iv_block
);
280 return gnutls_assert_val (ret
);
282 if (_gnutls_sset_datum (&client_write
->IV
, iv_block
, IV_size
) < 0)
283 return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR
);
285 if (_gnutls_sset_datum
286 (&server_write
->IV
, &iv_block
[IV_size
], IV_size
) < 0)
287 return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR
);
294 _gnutls_init_record_state (record_parameters_st
* params
, int read
,
295 record_state_st
* state
)
299 ret
= _gnutls_cipher_init (&state
->cipher_state
,
300 params
->cipher_algorithm
,
301 &state
->key
, &state
->IV
);
302 if (ret
< 0 && params
->cipher_algorithm
!= GNUTLS_CIPHER_NULL
)
303 return gnutls_assert_val (ret
);
305 state
->compression_state
=
306 _gnutls_comp_init (params
->compression_algorithm
, read
);
308 if (state
->compression_state
== GNUTLS_COMP_FAILED
)
309 return gnutls_assert_val (GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM
);
315 _gnutls_epoch_set_cipher_suite (gnutls_session_t session
,
316 int epoch_rel
, cipher_suite_st
* suite
)
318 gnutls_cipher_algorithm_t cipher_algo
;
319 gnutls_mac_algorithm_t mac_algo
;
320 record_parameters_st
*params
;
323 ret
= _gnutls_epoch_get (session
, epoch_rel
, ¶ms
);
325 return gnutls_assert_val (ret
);
327 if (params
->initialized
328 || params
->cipher_algorithm
!= GNUTLS_CIPHER_UNKNOWN
329 || params
->mac_algorithm
!= GNUTLS_MAC_UNKNOWN
)
330 return gnutls_assert_val (GNUTLS_E_INTERNAL_ERROR
);
332 cipher_algo
= _gnutls_cipher_suite_get_cipher_algo (suite
);
333 mac_algo
= _gnutls_cipher_suite_get_mac_algo (suite
);
335 if (_gnutls_cipher_is_ok (cipher_algo
) != 0
336 || _gnutls_mac_is_ok (mac_algo
) != 0)
337 return gnutls_assert_val (GNUTLS_E_UNWANTED_ALGORITHM
);
339 params
->cipher_algorithm
= cipher_algo
;
340 params
->mac_algorithm
= mac_algo
;
346 _gnutls_epoch_set_compression (gnutls_session_t session
,
348 gnutls_compression_method_t comp_algo
)
350 record_parameters_st
*params
;
353 ret
= _gnutls_epoch_get (session
, epoch_rel
, ¶ms
);
355 return gnutls_assert_val (ret
);
357 if (params
->initialized
358 || params
->compression_algorithm
!= GNUTLS_COMP_UNKNOWN
)
359 return gnutls_assert_val (GNUTLS_E_INTERNAL_ERROR
);
361 if (_gnutls_compression_is_ok (comp_algo
) != 0)
362 return gnutls_assert_val (GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM
);
364 params
->compression_algorithm
= comp_algo
;
370 _gnutls_epoch_set_null_algos (gnutls_session_t session
,
371 record_parameters_st
* params
)
373 /* This is only called on startup. We are extra paranoid about this
374 because it may cause unencrypted application data to go out on
376 if (params
->initialized
|| params
->epoch
!= 0)
382 params
->cipher_algorithm
= GNUTLS_CIPHER_NULL
;
383 params
->mac_algorithm
= GNUTLS_MAC_NULL
;
384 params
->compression_algorithm
= GNUTLS_COMP_NULL
;
385 params
->initialized
= 1;
389 _gnutls_epoch_set_keys (gnutls_session_t session
, uint16_t epoch
)
393 int key_size
, export_flag
;
394 gnutls_cipher_algorithm_t cipher_algo
;
395 gnutls_mac_algorithm_t mac_algo
;
396 gnutls_compression_method_t comp_algo
;
397 record_parameters_st
*params
;
400 ret
= _gnutls_epoch_get (session
, epoch
, ¶ms
);
402 return gnutls_assert_val (ret
);
404 if (params
->initialized
)
408 ("REC[%p]: Initializing epoch #%u\n", session
, params
->epoch
);
410 cipher_algo
= params
->cipher_algorithm
;
411 mac_algo
= params
->mac_algorithm
;
412 comp_algo
= params
->compression_algorithm
;
414 if (_gnutls_cipher_is_ok (cipher_algo
) != 0
415 || _gnutls_mac_is_ok (mac_algo
) != 0)
416 return gnutls_assert_val (GNUTLS_E_INTERNAL_ERROR
);
418 if (_gnutls_compression_is_ok (comp_algo
) != 0)
419 return gnutls_assert_val (GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM
);
421 IV_size
= _gnutls_cipher_get_iv_size (cipher_algo
);
422 key_size
= gnutls_cipher_get_key_size (cipher_algo
);
423 export_flag
= _gnutls_cipher_get_export_flag (cipher_algo
);
424 hash_size
= _gnutls_hash_get_algo_len (mac_algo
);
426 ret
= _gnutls_set_keys
427 (session
, params
, hash_size
, IV_size
, key_size
, export_flag
);
429 return gnutls_assert_val (ret
);
431 ret
= _gnutls_init_record_state (params
, 1, ¶ms
->read
);
433 return gnutls_assert_val (ret
);
435 ret
= _gnutls_init_record_state (params
, 0, ¶ms
->write
);
437 return gnutls_assert_val (ret
);
439 _gnutls_record_log ("REC[%p]: Epoch #%u ready\n", session
, params
->epoch
);
441 params
->initialized
= 1;
446 #define CPY_COMMON dst->entity = src->entity; \
447 dst->kx_algorithm = src->kx_algorithm; \
448 memcpy( &dst->current_cipher_suite, &src->current_cipher_suite, sizeof(cipher_suite_st)); \
449 memcpy( dst->master_secret, src->master_secret, GNUTLS_MASTER_SIZE); \
450 memcpy( dst->client_random, src->client_random, GNUTLS_RANDOM_SIZE); \
451 memcpy( dst->server_random, src->server_random, GNUTLS_RANDOM_SIZE); \
452 memcpy( dst->session_id, src->session_id, TLS_MAX_SESSION_ID_SIZE); \
453 dst->session_id_size = src->session_id_size; \
454 dst->cert_type = src->cert_type; \
455 dst->timestamp = src->timestamp; \
456 dst->max_record_recv_size = src->max_record_recv_size; \
457 dst->max_record_send_size = src->max_record_send_size; \
458 dst->version = src->version
461 _gnutls_set_resumed_parameters (gnutls_session_t session
)
463 security_parameters_st
*src
=
464 &session
->internals
.resumed_security_parameters
;
465 security_parameters_st
*dst
= &session
->security_parameters
;
470 /* Sets the current connection session to conform with the
471 * Security parameters(pending session), and initializes encryption.
472 * Actually it initializes and starts encryption ( so it needs
473 * secrets and random numbers to have been negotiated)
474 * This is to be called after sending the Change Cipher Spec packet.
477 _gnutls_connection_state_init (gnutls_session_t session
)
481 /* Setup the master secret
483 if ((ret
= _gnutls_generate_master (session
, 0)) < 0)
484 return gnutls_assert_val (ret
);
492 _gnutls_check_algos (gnutls_session_t session
,
493 cipher_suite_st
* suite
,
494 gnutls_compression_method_t comp_algo
)
496 gnutls_cipher_algorithm_t cipher_algo
;
497 gnutls_mac_algorithm_t mac_algo
;
499 cipher_algo
= _gnutls_cipher_suite_get_cipher_algo (suite
);
500 mac_algo
= _gnutls_cipher_suite_get_mac_algo (suite
);
502 if (_gnutls_cipher_is_ok (cipher_algo
) != 0)
503 return gnutls_assert_val (GNUTLS_E_INTERNAL_ERROR
);
505 if (_gnutls_cipher_priority (session
, cipher_algo
) < 0)
506 return gnutls_assert_val (GNUTLS_E_UNWANTED_ALGORITHM
);
509 if (_gnutls_mac_is_ok (mac_algo
) != 0)
510 return gnutls_assert_val (GNUTLS_E_INTERNAL_ERROR
);
512 if (_gnutls_mac_priority (session
, mac_algo
) < 0)
513 return gnutls_assert_val (GNUTLS_E_UNWANTED_ALGORITHM
);
516 if (_gnutls_compression_is_ok (comp_algo
) != 0)
517 return gnutls_assert_val (GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM
);
522 /* Initializes the read connection session
523 * (read encrypted data)
526 _gnutls_read_connection_state_init (gnutls_session_t session
)
528 const uint16_t epoch_next
= session
->security_parameters
.epoch_next
;
531 /* Update internals from CipherSuite selected.
532 * If we are resuming just copy the connection session
534 if (session
->internals
.resumed
== RESUME_FALSE
)
536 ret
= _gnutls_check_algos (session
,
538 security_parameters
.current_cipher_suite
,
539 session
->internals
.compression_method
);
543 ret
= _gnutls_set_kx (session
,
544 _gnutls_cipher_suite_get_kx_algo
546 security_parameters
.current_cipher_suite
));
550 else if (session
->security_parameters
.entity
== GNUTLS_CLIENT
)
551 _gnutls_set_resumed_parameters (session
);
553 ret
= _gnutls_epoch_set_keys (session
, epoch_next
);
557 _gnutls_handshake_log ("HSK[%p]: Cipher Suite: %s\n",
559 _gnutls_cipher_suite_get_name
561 security_parameters
.current_cipher_suite
));
563 session
->security_parameters
.epoch_read
= epoch_next
;
564 _gnutls_epoch_gc (session
);
571 /* Initializes the write connection session
572 * (write encrypted data)
575 _gnutls_write_connection_state_init (gnutls_session_t session
)
577 const uint16_t epoch_next
= session
->security_parameters
.epoch_next
;
580 /* Update internals from CipherSuite selected.
581 * If we are resuming just copy the connection session
583 if (session
->internals
.resumed
== RESUME_FALSE
)
585 ret
= _gnutls_check_algos (session
,
587 security_parameters
.current_cipher_suite
,
588 session
->internals
.compression_method
);
592 ret
= _gnutls_set_kx (session
,
593 _gnutls_cipher_suite_get_kx_algo
595 security_parameters
.current_cipher_suite
));
599 else if (session
->security_parameters
.entity
== GNUTLS_SERVER
)
600 _gnutls_set_resumed_parameters (session
);
602 ret
= _gnutls_epoch_set_keys (session
, epoch_next
);
604 return gnutls_assert_val (ret
);
606 _gnutls_handshake_log ("HSK[%p]: Cipher Suite: %s\n", session
,
607 _gnutls_cipher_suite_get_name
609 security_parameters
.current_cipher_suite
));
611 _gnutls_handshake_log
612 ("HSK[%p]: Initializing internal [write] cipher sessions\n", session
);
614 session
->security_parameters
.epoch_write
= epoch_next
;
615 _gnutls_epoch_gc (session
);
620 /* Sets the specified kx algorithm into pending session
623 _gnutls_set_kx (gnutls_session_t session
, gnutls_kx_algorithm_t algo
)
626 if (_gnutls_kx_is_ok (algo
) == 0)
628 session
->security_parameters
.kx_algorithm
= algo
;
631 return gnutls_assert_val (GNUTLS_E_INTERNAL_ERROR
);
633 if (_gnutls_kx_priority (session
, algo
) < 0)
634 return gnutls_assert_val (GNUTLS_E_UNWANTED_ALGORITHM
);
640 epoch_resolve (gnutls_session_t session
,
641 unsigned int epoch_rel
, uint16_t * epoch_out
)
645 case EPOCH_READ_CURRENT
:
646 *epoch_out
= session
->security_parameters
.epoch_read
;
649 case EPOCH_WRITE_CURRENT
:
650 *epoch_out
= session
->security_parameters
.epoch_write
;
654 *epoch_out
= session
->security_parameters
.epoch_next
;
658 if (epoch_rel
> 0xffffu
)
659 return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST
);
661 *epoch_out
= epoch_rel
;
666 static inline record_parameters_st
**
667 epoch_get_slot (gnutls_session_t session
, uint16_t epoch
)
669 uint16_t epoch_index
= epoch
- session
->security_parameters
.epoch_min
;
671 if (epoch_index
>= MAX_EPOCH_INDEX
)
677 /* The slot may still be empty (NULL) */
678 return &session
->record_parameters
[epoch_index
];
682 _gnutls_epoch_get (gnutls_session_t session
, unsigned int epoch_rel
,
683 record_parameters_st
** params_out
)
686 record_parameters_st
**params
;
689 ret
= epoch_resolve (session
, epoch_rel
, &epoch
);
691 return gnutls_assert_val (ret
);
693 params
= epoch_get_slot (session
, epoch
);
694 if (params
== NULL
|| *params
== NULL
)
695 return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST
);
697 *params_out
= *params
;
703 _gnutls_epoch_alloc (gnutls_session_t session
, uint16_t epoch
,
704 record_parameters_st
** out
)
706 record_parameters_st
**slot
;
708 _gnutls_record_log ("REC[%p]: Allocating epoch #%u\n", session
, epoch
);
710 slot
= epoch_get_slot (session
, epoch
);
712 /* If slot out of range or not empty. */
714 return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST
);
717 return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST
);
719 *slot
= gnutls_calloc (1, sizeof (record_parameters_st
));
721 return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR
);
723 (*slot
)->epoch
= epoch
;
724 (*slot
)->cipher_algorithm
= GNUTLS_CIPHER_UNKNOWN
;
725 (*slot
)->mac_algorithm
= GNUTLS_MAC_UNKNOWN
;
726 (*slot
)->compression_algorithm
= GNUTLS_COMP_UNKNOWN
;
735 epoch_alive (gnutls_session_t session
, record_parameters_st
* params
)
737 const security_parameters_st
*sp
= &session
->security_parameters
;
739 /* DTLS will, in addition, need to check the epoch timeout value. */
740 return (params
->epoch
== sp
->epoch_read
741 || params
->epoch
== sp
->epoch_write
742 || params
->epoch
== sp
->epoch_next
);
746 _gnutls_epoch_gc (gnutls_session_t session
)
749 unsigned int min_index
= 0;
751 _gnutls_record_log ("REC[%p]: Start of epoch cleanup\n", session
);
753 /* Free all dead cipher state */
754 for (i
= 0; i
< MAX_EPOCH_INDEX
; i
++)
755 if (session
->record_parameters
[i
] != NULL
756 && !epoch_alive (session
, session
->record_parameters
[i
]))
758 _gnutls_epoch_free (session
, session
->record_parameters
[i
]);
759 session
->record_parameters
[i
] = NULL
;
762 /* Look for contiguous NULLs at the start of the array */
763 for (i
= 0; i
< MAX_EPOCH_INDEX
&& session
->record_parameters
[i
] == NULL
;
767 /* Pick up the slack in the epoch window. */
768 for (i
= 0, j
= min_index
; j
< MAX_EPOCH_INDEX
; i
++, j
++)
769 session
->record_parameters
[i
] = session
->record_parameters
[j
];
771 /* Set the new epoch_min */
772 if (session
->record_parameters
[0] != NULL
)
773 session
->security_parameters
.epoch_min
=
774 session
->record_parameters
[0]->epoch
;
776 _gnutls_record_log ("REC[%p]: End of epoch cleanup\n", session
);
780 free_record_state (record_state_st
* state
, int read
)
782 _gnutls_free_datum (&state
->mac_secret
);
783 _gnutls_free_datum (&state
->IV
);
784 _gnutls_free_datum (&state
->key
);
786 _gnutls_cipher_deinit (&state
->cipher_state
);
788 if (state
->compression_state
!= NULL
)
789 _gnutls_comp_deinit (state
->compression_state
, read
);
793 _gnutls_epoch_free (gnutls_session_t session
, record_parameters_st
* params
)
795 _gnutls_record_log ("REC[%p]: Epoch #%u freed\n", session
, params
->epoch
);
797 free_record_state (¶ms
->read
, 1);
798 free_record_state (¶ms
->write
, 0);
800 gnutls_free (params
);