2 * Copyright (C) 2001-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
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 3 of
11 * the License, or (at your option) any later version.
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.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 /* Functions that are supposed to run after the handshake procedure is
24 * finished. These functions activate the established security parameters.
27 #include <gnutls_int.h>
28 #include <gnutls_constate.h>
29 #include <gnutls_errors.h>
30 #include <gnutls_kx.h>
31 #include <algorithms.h>
32 #include <gnutls_num.h>
33 #include <gnutls_datum.h>
34 #include <gnutls_state.h>
35 #include <gnutls_extensions.h>
36 #include <gnutls_buffers.h>
38 static const char keyexp
[] = "key expansion";
39 static const int keyexp_length
= sizeof (keyexp
) - 1;
41 static const char ivblock
[] = "IV block";
42 static const int ivblock_length
= sizeof (ivblock
) - 1;
44 static const char cliwrite
[] = "client write key";
45 static const int cliwrite_length
= sizeof (cliwrite
) - 1;
47 static const char servwrite
[] = "server write key";
48 static const int servwrite_length
= sizeof (servwrite
) - 1;
50 #define EXPORT_FINAL_KEY_SIZE 16
52 /* This function is to be called after handshake, when master_secret,
53 * client_random and server_random have been initialized.
54 * This function creates the keys and stores them into pending session.
55 * (session->cipher_specs)
58 _gnutls_set_keys (gnutls_session_t session
, record_parameters_st
* params
,
59 int hash_size
, int IV_size
, int key_size
, int export_flag
)
61 /* FIXME: This function is too long
63 uint8_t rnd
[2 * GNUTLS_RANDOM_SIZE
];
64 uint8_t rrnd
[2 * GNUTLS_RANDOM_SIZE
];
68 /* avoid using malloc */
69 uint8_t key_block
[2 * MAX_HASH_SIZE
+ 2 * MAX_CIPHER_KEY_SIZE
+
70 2 * MAX_CIPHER_BLOCK_SIZE
];
71 record_state_st
*client_write
, *server_write
;
73 if (session
->security_parameters
.entity
== GNUTLS_CLIENT
)
75 client_write
= ¶ms
->write
;
76 server_write
= ¶ms
->read
;
80 client_write
= ¶ms
->read
;
81 server_write
= ¶ms
->write
;
84 block_size
= 2 * hash_size
+ 2 * key_size
;
86 block_size
+= 2 * IV_size
;
88 memcpy (rnd
, session
->security_parameters
.server_random
,
90 memcpy (&rnd
[GNUTLS_RANDOM_SIZE
],
91 session
->security_parameters
.client_random
, GNUTLS_RANDOM_SIZE
);
93 memcpy (rrnd
, session
->security_parameters
.client_random
,
95 memcpy (&rrnd
[GNUTLS_RANDOM_SIZE
],
96 session
->security_parameters
.server_random
, GNUTLS_RANDOM_SIZE
);
98 if (session
->security_parameters
.version
== GNUTLS_SSL3
)
101 _gnutls_ssl3_generate_random
102 (session
->security_parameters
.master_secret
, GNUTLS_MASTER_SIZE
, rnd
,
103 2 * GNUTLS_RANDOM_SIZE
, block_size
, key_block
);
108 _gnutls_PRF (session
, session
->security_parameters
.master_secret
,
109 GNUTLS_MASTER_SIZE
, keyexp
, keyexp_length
,
110 rnd
, 2 * GNUTLS_RANDOM_SIZE
, block_size
, key_block
);
114 return gnutls_assert_val (ret
);
116 _gnutls_hard_log ("INT: KEY BLOCK[%d]: %s\n", block_size
,
117 _gnutls_bin2hex (key_block
, block_size
, buf
,
118 sizeof (buf
), NULL
));
124 if (_gnutls_set_datum
125 (&client_write
->mac_secret
, &key_block
[pos
], hash_size
) < 0)
126 return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR
);
130 if (_gnutls_set_datum
131 (&server_write
->mac_secret
, &key_block
[pos
], hash_size
) < 0)
132 return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR
);
139 uint8_t key1
[EXPORT_FINAL_KEY_SIZE
];
140 uint8_t key2
[EXPORT_FINAL_KEY_SIZE
];
141 uint8_t *client_write_key
, *server_write_key
;
142 int client_write_key_size
, server_write_key_size
;
144 if (export_flag
== 0)
146 client_write_key
= &key_block
[pos
];
147 client_write_key_size
= key_size
;
151 server_write_key
= &key_block
[pos
];
152 server_write_key_size
= key_size
;
159 client_write_key
= key1
;
160 server_write_key
= key2
;
162 /* generate the final keys */
164 if (session
->security_parameters
.version
== GNUTLS_SSL3
)
167 _gnutls_ssl3_hash_md5 (&key_block
[pos
],
169 2 * GNUTLS_RANDOM_SIZE
,
170 EXPORT_FINAL_KEY_SIZE
,
177 _gnutls_PRF (session
, &key_block
[pos
], key_size
,
178 cliwrite
, cliwrite_length
,
180 2 * GNUTLS_RANDOM_SIZE
,
181 EXPORT_FINAL_KEY_SIZE
, client_write_key
);
185 return gnutls_assert_val (ret
);
187 client_write_key_size
= EXPORT_FINAL_KEY_SIZE
;
190 if (session
->security_parameters
.version
== GNUTLS_SSL3
)
193 _gnutls_ssl3_hash_md5 (&key_block
[pos
], key_size
,
194 rnd
, 2 * GNUTLS_RANDOM_SIZE
,
195 EXPORT_FINAL_KEY_SIZE
,
201 _gnutls_PRF (session
, &key_block
[pos
], key_size
,
202 servwrite
, servwrite_length
,
203 rrnd
, 2 * GNUTLS_RANDOM_SIZE
,
204 EXPORT_FINAL_KEY_SIZE
, server_write_key
);
208 return gnutls_assert_val (ret
);
210 server_write_key_size
= EXPORT_FINAL_KEY_SIZE
;
214 if (_gnutls_set_datum
215 (&client_write
->key
, client_write_key
, client_write_key_size
) < 0)
216 return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR
);
218 _gnutls_hard_log ("INT: CLIENT WRITE KEY [%d]: %s\n",
219 client_write_key_size
,
220 _gnutls_bin2hex (client_write_key
,
221 client_write_key_size
, buf
,
222 sizeof (buf
), NULL
));
224 if (_gnutls_set_datum
225 (&server_write
->key
, server_write_key
, server_write_key_size
) < 0)
226 return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR
);
228 _gnutls_hard_log ("INT: SERVER WRITE KEY [%d]: %s\n",
229 server_write_key_size
,
230 _gnutls_bin2hex (server_write_key
,
231 server_write_key_size
, buf
,
232 sizeof (buf
), NULL
));
237 /* IV generation in export and non export ciphers.
239 if (IV_size
> 0 && export_flag
== 0)
241 if (_gnutls_set_datum
242 (&client_write
->IV
, &key_block
[pos
], IV_size
) < 0)
243 return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR
);
247 if (_gnutls_set_datum
248 (&server_write
->IV
, &key_block
[pos
], IV_size
) < 0)
249 return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR
);
254 else if (IV_size
> 0 && export_flag
!= 0)
256 uint8_t iv_block
[MAX_CIPHER_BLOCK_SIZE
* 2];
258 if (session
->security_parameters
.version
== GNUTLS_SSL3
)
260 ret
= _gnutls_ssl3_hash_md5 ("", 0,
261 rrnd
, GNUTLS_RANDOM_SIZE
* 2,
265 return gnutls_assert_val (ret
);
268 ret
= _gnutls_ssl3_hash_md5 ("", 0, rnd
,
269 GNUTLS_RANDOM_SIZE
* 2,
270 IV_size
, &iv_block
[IV_size
]);
275 ret
= _gnutls_PRF (session
, (uint8_t*)"", 0,
276 ivblock
, ivblock_length
, rrnd
,
277 2 * GNUTLS_RANDOM_SIZE
, IV_size
* 2, iv_block
);
281 return gnutls_assert_val (ret
);
283 if (_gnutls_set_datum (&client_write
->IV
, iv_block
, IV_size
) < 0)
284 return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR
);
286 if (_gnutls_set_datum
287 (&server_write
->IV
, &iv_block
[IV_size
], IV_size
) < 0)
288 return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR
);
295 _gnutls_init_record_state (record_parameters_st
* params
, gnutls_protocol_t ver
, int read
,
296 record_state_st
* state
)
299 gnutls_datum_t
* iv
= NULL
;
301 if (!_gnutls_version_has_explicit_iv(ver
))
306 ret
= _gnutls_auth_cipher_init (&state
->cipher_state
,
307 params
->cipher_algorithm
, &state
->key
, iv
,
308 params
->mac_algorithm
, &state
->mac_secret
, (ver
==GNUTLS_SSL3
)?1:0, 1-read
/*1==encrypt*/);
309 if (ret
< 0 && params
->cipher_algorithm
!= GNUTLS_CIPHER_NULL
)
310 return gnutls_assert_val (ret
);
313 _gnutls_comp_init (&state
->compression_state
, params
->compression_algorithm
, read
/*1==decompress*/);
316 return gnutls_assert_val (ret
);
322 _gnutls_epoch_set_cipher_suite (gnutls_session_t session
,
323 int epoch_rel
, const uint8_t suite
[2])
325 gnutls_cipher_algorithm_t cipher_algo
;
326 gnutls_mac_algorithm_t mac_algo
;
327 record_parameters_st
*params
;
330 ret
= _gnutls_epoch_get (session
, epoch_rel
, ¶ms
);
332 return gnutls_assert_val (ret
);
334 if (params
->initialized
335 || params
->cipher_algorithm
!= GNUTLS_CIPHER_UNKNOWN
336 || params
->mac_algorithm
!= GNUTLS_MAC_UNKNOWN
)
337 return gnutls_assert_val (GNUTLS_E_INTERNAL_ERROR
);
339 cipher_algo
= _gnutls_cipher_suite_get_cipher_algo (suite
);
340 mac_algo
= _gnutls_cipher_suite_get_mac_algo (suite
);
342 if (_gnutls_cipher_is_ok (cipher_algo
) != 0
343 || _gnutls_mac_is_ok (mac_algo
) != 0)
344 return gnutls_assert_val (GNUTLS_E_UNWANTED_ALGORITHM
);
346 params
->cipher_algorithm
= cipher_algo
;
347 params
->mac_algorithm
= mac_algo
;
353 _gnutls_epoch_set_compression (gnutls_session_t session
,
355 gnutls_compression_method_t comp_algo
)
357 record_parameters_st
*params
;
360 ret
= _gnutls_epoch_get (session
, epoch_rel
, ¶ms
);
362 return gnutls_assert_val (ret
);
364 if (params
->initialized
365 || params
->compression_algorithm
!= GNUTLS_COMP_UNKNOWN
)
366 return gnutls_assert_val (GNUTLS_E_INTERNAL_ERROR
);
368 if (_gnutls_compression_is_ok (comp_algo
) != 0)
369 return gnutls_assert_val (GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM
);
371 params
->compression_algorithm
= comp_algo
;
377 _gnutls_epoch_set_null_algos (gnutls_session_t session
,
378 record_parameters_st
* params
)
380 /* This is only called on startup. We are extra paranoid about this
381 because it may cause unencrypted application data to go out on
383 if (params
->initialized
|| params
->epoch
!= 0)
389 params
->cipher_algorithm
= GNUTLS_CIPHER_NULL
;
390 params
->mac_algorithm
= GNUTLS_MAC_NULL
;
391 params
->compression_algorithm
= GNUTLS_COMP_NULL
;
392 params
->initialized
= 1;
396 _gnutls_epoch_set_keys (gnutls_session_t session
, uint16_t epoch
)
400 int key_size
, export_flag
;
401 gnutls_cipher_algorithm_t cipher_algo
;
402 gnutls_mac_algorithm_t mac_algo
;
403 gnutls_compression_method_t comp_algo
;
404 record_parameters_st
*params
;
406 gnutls_protocol_t ver
= gnutls_protocol_get_version (session
);
408 ret
= _gnutls_epoch_get (session
, epoch
, ¶ms
);
410 return gnutls_assert_val (ret
);
412 if (params
->initialized
)
416 ("REC[%p]: Initializing epoch #%u\n", session
, params
->epoch
);
418 cipher_algo
= params
->cipher_algorithm
;
419 mac_algo
= params
->mac_algorithm
;
420 comp_algo
= params
->compression_algorithm
;
422 if (_gnutls_cipher_is_ok (cipher_algo
) != 0
423 || _gnutls_mac_is_ok (mac_algo
) != 0)
424 return gnutls_assert_val (GNUTLS_E_INTERNAL_ERROR
);
426 if (_gnutls_compression_is_ok (comp_algo
) != 0)
427 return gnutls_assert_val (GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM
);
429 IV_size
= _gnutls_cipher_get_iv_size (cipher_algo
);
430 key_size
= gnutls_cipher_get_key_size (cipher_algo
);
431 export_flag
= _gnutls_cipher_get_export_flag (cipher_algo
);
432 hash_size
= _gnutls_hash_get_algo_len (mac_algo
);
434 ret
= _gnutls_set_keys
435 (session
, params
, hash_size
, IV_size
, key_size
, export_flag
);
437 return gnutls_assert_val (ret
);
439 ret
= _gnutls_init_record_state (params
, ver
, 1, ¶ms
->read
);
441 return gnutls_assert_val (ret
);
443 ret
= _gnutls_init_record_state (params
, ver
, 0, ¶ms
->write
);
445 return gnutls_assert_val (ret
);
447 params
->record_sw_size
= 0;
449 _gnutls_record_log ("REC[%p]: Epoch #%u ready\n", session
, params
->epoch
);
451 params
->initialized
= 1;
456 #define CPY_COMMON dst->entity = src->entity; \
457 dst->kx_algorithm = src->kx_algorithm; \
458 memcpy( dst->cipher_suite, src->cipher_suite, 2); \
459 memcpy( dst->master_secret, src->master_secret, GNUTLS_MASTER_SIZE); \
460 memcpy( dst->client_random, src->client_random, GNUTLS_RANDOM_SIZE); \
461 memcpy( dst->server_random, src->server_random, GNUTLS_RANDOM_SIZE); \
462 memcpy( dst->session_id, src->session_id, TLS_MAX_SESSION_ID_SIZE); \
463 dst->session_id_size = src->session_id_size; \
464 dst->cert_type = src->cert_type; \
465 dst->compression_method = src->compression_method; \
466 dst->timestamp = src->timestamp; \
467 dst->max_record_recv_size = src->max_record_recv_size; \
468 dst->max_record_send_size = src->max_record_send_size; \
469 dst->version = src->version
472 _gnutls_set_resumed_parameters (gnutls_session_t session
)
474 security_parameters_st
*src
=
475 &session
->internals
.resumed_security_parameters
;
476 security_parameters_st
*dst
= &session
->security_parameters
;
481 /* Sets the current connection session to conform with the
482 * Security parameters(pending session), and initializes encryption.
483 * Actually it initializes and starts encryption ( so it needs
484 * secrets and random numbers to have been negotiated)
485 * This is to be called after sending the Change Cipher Spec packet.
488 _gnutls_connection_state_init (gnutls_session_t session
)
492 /* Setup the master secret
494 if ((ret
= _gnutls_generate_master (session
, 0)) < 0)
495 return gnutls_assert_val (ret
);
503 _gnutls_check_algos (gnutls_session_t session
,
504 const uint8_t suite
[2],
505 gnutls_compression_method_t comp_algo
)
507 gnutls_cipher_algorithm_t cipher_algo
;
508 gnutls_mac_algorithm_t mac_algo
;
510 cipher_algo
= _gnutls_cipher_suite_get_cipher_algo (suite
);
511 mac_algo
= _gnutls_cipher_suite_get_mac_algo (suite
);
513 if (_gnutls_cipher_is_ok (cipher_algo
) != 0)
514 return gnutls_assert_val (GNUTLS_E_INTERNAL_ERROR
);
516 if (_gnutls_cipher_priority (session
, cipher_algo
) < 0)
517 return gnutls_assert_val (GNUTLS_E_UNWANTED_ALGORITHM
);
520 if (_gnutls_mac_is_ok (mac_algo
) != 0)
521 return gnutls_assert_val (GNUTLS_E_INTERNAL_ERROR
);
523 if (_gnutls_mac_priority (session
, mac_algo
) < 0)
524 return gnutls_assert_val (GNUTLS_E_UNWANTED_ALGORITHM
);
527 if (_gnutls_compression_is_ok (comp_algo
) != 0)
528 return gnutls_assert_val (GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM
);
533 int _gnutls_epoch_get_compression(gnutls_session_t session
, int epoch
)
535 record_parameters_st
*params
;
538 ret
= _gnutls_epoch_get (session
, epoch
, ¶ms
);
540 return GNUTLS_COMP_UNKNOWN
;
542 return params
->compression_algorithm
;
545 /* Initializes the read connection session
546 * (read encrypted data)
549 _gnutls_read_connection_state_init (gnutls_session_t session
)
551 const uint16_t epoch_next
= session
->security_parameters
.epoch_next
;
554 /* Update internals from CipherSuite selected.
555 * If we are resuming just copy the connection session
557 if (session
->internals
.resumed
== RESUME_FALSE
)
560 ret
= _gnutls_check_algos (session
,
562 security_parameters
.cipher_suite
,
563 _gnutls_epoch_get_compression(session
, epoch_next
));
567 ret
= _gnutls_set_kx (session
,
568 _gnutls_cipher_suite_get_kx_algo
570 security_parameters
.cipher_suite
));
574 else if (session
->security_parameters
.entity
== GNUTLS_CLIENT
)
575 _gnutls_set_resumed_parameters (session
);
577 ret
= _gnutls_epoch_set_keys (session
, epoch_next
);
581 _gnutls_handshake_log ("HSK[%p]: Cipher Suite: %s\n",
583 _gnutls_cipher_suite_get_name
585 security_parameters
.cipher_suite
));
587 session
->security_parameters
.epoch_read
= epoch_next
;
594 /* Initializes the write connection session
595 * (write encrypted data)
598 _gnutls_write_connection_state_init (gnutls_session_t session
)
600 const uint16_t epoch_next
= session
->security_parameters
.epoch_next
;
603 /* Update internals from CipherSuite selected.
604 * If we are resuming just copy the connection session
606 if (session
->internals
.resumed
== RESUME_FALSE
)
608 ret
= _gnutls_check_algos (session
,
610 security_parameters
.cipher_suite
,
611 _gnutls_epoch_get_compression(session
, epoch_next
));
615 ret
= _gnutls_set_kx (session
,
616 _gnutls_cipher_suite_get_kx_algo
618 security_parameters
.cipher_suite
));
622 else if (session
->security_parameters
.entity
== GNUTLS_SERVER
)
623 _gnutls_set_resumed_parameters (session
);
625 ret
= _gnutls_epoch_set_keys (session
, epoch_next
);
627 return gnutls_assert_val (ret
);
629 _gnutls_handshake_log ("HSK[%p]: Cipher Suite: %s\n", session
,
630 _gnutls_cipher_suite_get_name
632 security_parameters
.cipher_suite
));
634 _gnutls_handshake_log
635 ("HSK[%p]: Initializing internal [write] cipher sessions\n", session
);
637 session
->security_parameters
.epoch_write
= epoch_next
;
642 /* Sets the specified kx algorithm into pending session
645 _gnutls_set_kx (gnutls_session_t session
, gnutls_kx_algorithm_t algo
)
648 if (_gnutls_kx_is_ok (algo
) == 0)
650 session
->security_parameters
.kx_algorithm
= algo
;
653 return gnutls_assert_val (GNUTLS_E_INTERNAL_ERROR
);
655 if (_gnutls_kx_priority (session
, algo
) < 0)
656 return gnutls_assert_val (GNUTLS_E_UNWANTED_ALGORITHM
);
662 epoch_resolve (gnutls_session_t session
,
663 unsigned int epoch_rel
, uint16_t * epoch_out
)
667 case EPOCH_READ_CURRENT
:
668 *epoch_out
= session
->security_parameters
.epoch_read
;
671 case EPOCH_WRITE_CURRENT
:
672 *epoch_out
= session
->security_parameters
.epoch_write
;
676 *epoch_out
= session
->security_parameters
.epoch_next
;
680 if (epoch_rel
> 0xffffu
)
681 return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST
);
683 *epoch_out
= epoch_rel
;
688 static inline record_parameters_st
**
689 epoch_get_slot (gnutls_session_t session
, uint16_t epoch
)
691 uint16_t epoch_index
= epoch
- session
->security_parameters
.epoch_min
;
693 if (epoch_index
>= MAX_EPOCH_INDEX
)
695 _gnutls_handshake_log("Epoch %d out of range (idx: %d, max: %d)\n", (int)epoch
, (int)epoch_index
, MAX_EPOCH_INDEX
);
699 /* The slot may still be empty (NULL) */
700 return &session
->record_parameters
[epoch_index
];
704 _gnutls_epoch_get (gnutls_session_t session
, unsigned int epoch_rel
,
705 record_parameters_st
** params_out
)
708 record_parameters_st
**params
;
711 ret
= epoch_resolve (session
, epoch_rel
, &epoch
);
713 return gnutls_assert_val (ret
);
715 params
= epoch_get_slot (session
, epoch
);
716 if (params
== NULL
|| *params
== NULL
)
717 return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST
);
719 *params_out
= *params
;
725 _gnutls_epoch_alloc (gnutls_session_t session
, uint16_t epoch
,
726 record_parameters_st
** out
)
728 record_parameters_st
**slot
;
730 _gnutls_record_log ("REC[%p]: Allocating epoch #%u\n", session
, epoch
);
732 slot
= epoch_get_slot (session
, epoch
);
734 /* If slot out of range or not empty. */
736 return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST
);
739 return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST
);
741 *slot
= gnutls_calloc (1, sizeof (record_parameters_st
));
743 return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR
);
745 (*slot
)->epoch
= epoch
;
746 (*slot
)->cipher_algorithm
= GNUTLS_CIPHER_UNKNOWN
;
747 (*slot
)->mac_algorithm
= GNUTLS_MAC_UNKNOWN
;
748 (*slot
)->compression_algorithm
= GNUTLS_COMP_UNKNOWN
;
750 if (IS_DTLS (session
))
751 _gnutls_write_uint16 (epoch
, UINT64DATA((*slot
)->write
.sequence_number
));
760 epoch_alive (gnutls_session_t session
, record_parameters_st
* params
)
762 const security_parameters_st
*sp
= &session
->security_parameters
;
764 /* DTLS will, in addition, need to check the epoch timeout value. */
765 if (params
->usage_cnt
> 0)
768 if (params
->epoch
== sp
->epoch_read
)
771 if (params
->epoch
== sp
->epoch_write
)
774 if (params
->epoch
== sp
->epoch_next
)
781 _gnutls_epoch_gc (gnutls_session_t session
)
784 unsigned int min_index
= 0;
786 _gnutls_record_log ("REC[%p]: Start of epoch cleanup\n", session
);
788 /* Free all dead cipher state */
789 for (i
= 0; i
< MAX_EPOCH_INDEX
; i
++)
790 if (session
->record_parameters
[i
] != NULL
791 && !epoch_alive (session
, session
->record_parameters
[i
]))
793 _gnutls_epoch_free (session
, session
->record_parameters
[i
]);
794 session
->record_parameters
[i
] = NULL
;
797 /* Look for contiguous NULLs at the start of the array */
798 for (i
= 0; i
< MAX_EPOCH_INDEX
&& session
->record_parameters
[i
] == NULL
;
802 /* Pick up the slack in the epoch window. */
803 for (i
= 0, j
= min_index
; j
< MAX_EPOCH_INDEX
; i
++, j
++)
804 session
->record_parameters
[i
] = session
->record_parameters
[j
];
806 /* Set the new epoch_min */
807 if (session
->record_parameters
[0] != NULL
)
808 session
->security_parameters
.epoch_min
=
809 session
->record_parameters
[0]->epoch
;
811 _gnutls_record_log ("REC[%p]: End of epoch cleanup\n", session
);
815 free_record_state (record_state_st
* state
, int d
)
817 _gnutls_free_datum (&state
->mac_secret
);
818 _gnutls_free_datum (&state
->IV
);
819 _gnutls_free_datum (&state
->key
);
821 _gnutls_auth_cipher_deinit (&state
->cipher_state
);
823 if (state
->compression_state
.handle
!= NULL
)
824 _gnutls_comp_deinit (&state
->compression_state
, d
);
828 _gnutls_epoch_free (gnutls_session_t session
, record_parameters_st
* params
)
830 _gnutls_record_log ("REC[%p]: Epoch #%u freed\n", session
, params
->epoch
);
832 free_record_state (¶ms
->read
, 1);
833 free_record_state (¶ms
->write
, 0);
835 gnutls_free (params
);