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
);
252 else if (IV_size
> 0 && export_flag
!= 0)
254 uint8_t iv_block
[MAX_CIPHER_BLOCK_SIZE
* 2];
256 if (session
->security_parameters
.version
== GNUTLS_SSL3
)
258 ret
= _gnutls_ssl3_hash_md5 ("", 0,
259 rrnd
, GNUTLS_RANDOM_SIZE
* 2,
263 return gnutls_assert_val (ret
);
266 ret
= _gnutls_ssl3_hash_md5 ("", 0, rnd
,
267 GNUTLS_RANDOM_SIZE
* 2,
268 IV_size
, &iv_block
[IV_size
]);
273 ret
= _gnutls_PRF (session
, (uint8_t*)"", 0,
274 ivblock
, ivblock_length
, rrnd
,
275 2 * GNUTLS_RANDOM_SIZE
, IV_size
* 2, iv_block
);
279 return gnutls_assert_val (ret
);
281 if (_gnutls_set_datum (&client_write
->IV
, iv_block
, IV_size
) < 0)
282 return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR
);
284 if (_gnutls_set_datum
285 (&server_write
->IV
, &iv_block
[IV_size
], IV_size
) < 0)
286 return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR
);
293 _gnutls_init_record_state (record_parameters_st
* params
, gnutls_protocol_t ver
, int read
,
294 record_state_st
* state
)
297 gnutls_datum_t
* iv
= NULL
;
299 if (!_gnutls_version_has_explicit_iv(ver
))
304 ret
= _gnutls_auth_cipher_init (&state
->cipher_state
,
305 params
->cipher_algorithm
, &state
->key
, iv
,
306 params
->mac_algorithm
, &state
->mac_secret
, (ver
==GNUTLS_SSL3
)?1:0, 1-read
/*1==encrypt*/);
307 if (ret
< 0 && params
->cipher_algorithm
!= GNUTLS_CIPHER_NULL
)
308 return gnutls_assert_val (ret
);
311 _gnutls_comp_init (&state
->compression_state
, params
->compression_algorithm
, read
/*1==decompress*/);
314 return gnutls_assert_val (ret
);
320 _gnutls_epoch_set_cipher_suite (gnutls_session_t session
,
321 int epoch_rel
, const uint8_t suite
[2])
323 gnutls_cipher_algorithm_t cipher_algo
;
324 gnutls_mac_algorithm_t mac_algo
;
325 record_parameters_st
*params
;
328 ret
= _gnutls_epoch_get (session
, epoch_rel
, ¶ms
);
330 return gnutls_assert_val (ret
);
332 if (params
->initialized
333 || params
->cipher_algorithm
!= GNUTLS_CIPHER_UNKNOWN
334 || params
->mac_algorithm
!= GNUTLS_MAC_UNKNOWN
)
335 return gnutls_assert_val (GNUTLS_E_INTERNAL_ERROR
);
337 cipher_algo
= _gnutls_cipher_suite_get_cipher_algo (suite
);
338 mac_algo
= _gnutls_cipher_suite_get_mac_algo (suite
);
340 if (_gnutls_cipher_is_ok (cipher_algo
) != 0
341 || _gnutls_mac_is_ok (mac_algo
) != 0)
342 return gnutls_assert_val (GNUTLS_E_UNWANTED_ALGORITHM
);
344 params
->cipher_algorithm
= cipher_algo
;
345 params
->mac_algorithm
= mac_algo
;
351 _gnutls_epoch_set_compression (gnutls_session_t session
,
353 gnutls_compression_method_t comp_algo
)
355 record_parameters_st
*params
;
358 ret
= _gnutls_epoch_get (session
, epoch_rel
, ¶ms
);
360 return gnutls_assert_val (ret
);
362 if (params
->initialized
363 || params
->compression_algorithm
!= GNUTLS_COMP_UNKNOWN
)
364 return gnutls_assert_val (GNUTLS_E_INTERNAL_ERROR
);
366 if (_gnutls_compression_is_ok (comp_algo
) != 0)
367 return gnutls_assert_val (GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM
);
369 params
->compression_algorithm
= comp_algo
;
375 _gnutls_epoch_set_null_algos (gnutls_session_t session
,
376 record_parameters_st
* params
)
378 /* This is only called on startup. We are extra paranoid about this
379 because it may cause unencrypted application data to go out on
381 if (params
->initialized
|| params
->epoch
!= 0)
387 params
->cipher_algorithm
= GNUTLS_CIPHER_NULL
;
388 params
->mac_algorithm
= GNUTLS_MAC_NULL
;
389 params
->compression_algorithm
= GNUTLS_COMP_NULL
;
390 params
->initialized
= 1;
394 _gnutls_epoch_set_keys (gnutls_session_t session
, uint16_t epoch
)
398 int key_size
, export_flag
;
399 gnutls_cipher_algorithm_t cipher_algo
;
400 gnutls_mac_algorithm_t mac_algo
;
401 gnutls_compression_method_t comp_algo
;
402 record_parameters_st
*params
;
404 gnutls_protocol_t ver
= gnutls_protocol_get_version (session
);
406 ret
= _gnutls_epoch_get (session
, epoch
, ¶ms
);
408 return gnutls_assert_val (ret
);
410 if (params
->initialized
)
414 ("REC[%p]: Initializing epoch #%u\n", session
, params
->epoch
);
416 cipher_algo
= params
->cipher_algorithm
;
417 mac_algo
= params
->mac_algorithm
;
418 comp_algo
= params
->compression_algorithm
;
420 if (_gnutls_cipher_is_ok (cipher_algo
) != 0
421 || _gnutls_mac_is_ok (mac_algo
) != 0)
422 return gnutls_assert_val (GNUTLS_E_INTERNAL_ERROR
);
424 if (_gnutls_compression_is_ok (comp_algo
) != 0)
425 return gnutls_assert_val (GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM
);
427 IV_size
= _gnutls_cipher_get_iv_size (cipher_algo
);
428 key_size
= gnutls_cipher_get_key_size (cipher_algo
);
429 export_flag
= _gnutls_cipher_get_export_flag (cipher_algo
);
430 hash_size
= _gnutls_hmac_get_algo_len (mac_algo
);
432 ret
= _gnutls_set_keys
433 (session
, params
, hash_size
, IV_size
, key_size
, export_flag
);
435 return gnutls_assert_val (ret
);
437 ret
= _gnutls_init_record_state (params
, ver
, 1, ¶ms
->read
);
439 return gnutls_assert_val (ret
);
441 ret
= _gnutls_init_record_state (params
, ver
, 0, ¶ms
->write
);
443 return gnutls_assert_val (ret
);
445 params
->record_sw_size
= 0;
447 _gnutls_record_log ("REC[%p]: Epoch #%u ready\n", session
, params
->epoch
);
449 params
->initialized
= 1;
454 #define CPY_COMMON dst->entity = src->entity; \
455 dst->kx_algorithm = src->kx_algorithm; \
456 memcpy( dst->cipher_suite, src->cipher_suite, 2); \
457 memcpy( dst->master_secret, src->master_secret, GNUTLS_MASTER_SIZE); \
458 memcpy( dst->client_random, src->client_random, GNUTLS_RANDOM_SIZE); \
459 memcpy( dst->server_random, src->server_random, GNUTLS_RANDOM_SIZE); \
460 memcpy( dst->session_id, src->session_id, TLS_MAX_SESSION_ID_SIZE); \
461 dst->session_id_size = src->session_id_size; \
462 dst->cert_type = src->cert_type; \
463 dst->compression_method = src->compression_method; \
464 dst->timestamp = src->timestamp; \
465 dst->max_record_recv_size = src->max_record_recv_size; \
466 dst->max_record_send_size = src->max_record_send_size; \
467 dst->version = src->version;
470 _gnutls_set_resumed_parameters (gnutls_session_t session
)
472 security_parameters_st
*src
=
473 &session
->internals
.resumed_security_parameters
;
474 security_parameters_st
*dst
= &session
->security_parameters
;
479 /* Sets the current connection session to conform with the
480 * Security parameters(pending session), and initializes encryption.
481 * Actually it initializes and starts encryption ( so it needs
482 * secrets and random numbers to have been negotiated)
483 * This is to be called after sending the Change Cipher Spec packet.
486 _gnutls_connection_state_init (gnutls_session_t session
)
490 /* Setup the master secret
492 if ((ret
= _gnutls_generate_master (session
, 0)) < 0)
493 return gnutls_assert_val (ret
);
501 _gnutls_check_algos (gnutls_session_t session
,
502 const uint8_t suite
[2],
503 gnutls_compression_method_t comp_algo
)
505 gnutls_cipher_algorithm_t cipher_algo
;
506 gnutls_mac_algorithm_t mac_algo
;
508 cipher_algo
= _gnutls_cipher_suite_get_cipher_algo (suite
);
509 mac_algo
= _gnutls_cipher_suite_get_mac_algo (suite
);
511 if (_gnutls_cipher_is_ok (cipher_algo
) != 0)
512 return gnutls_assert_val (GNUTLS_E_INTERNAL_ERROR
);
514 if (_gnutls_cipher_priority (session
, cipher_algo
) < 0)
515 return gnutls_assert_val (GNUTLS_E_UNWANTED_ALGORITHM
);
518 if (_gnutls_mac_is_ok (mac_algo
) != 0)
519 return gnutls_assert_val (GNUTLS_E_INTERNAL_ERROR
);
521 if (_gnutls_mac_priority (session
, mac_algo
) < 0)
522 return gnutls_assert_val (GNUTLS_E_UNWANTED_ALGORITHM
);
525 if (_gnutls_compression_is_ok (comp_algo
) != 0)
526 return gnutls_assert_val (GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM
);
531 int _gnutls_epoch_get_compression(gnutls_session_t session
, int epoch
)
533 record_parameters_st
*params
;
536 ret
= _gnutls_epoch_get (session
, epoch
, ¶ms
);
538 return GNUTLS_COMP_UNKNOWN
;
540 return params
->compression_algorithm
;
543 /* Initializes the read connection session
544 * (read encrypted data)
547 _gnutls_read_connection_state_init (gnutls_session_t session
)
549 const uint16_t epoch_next
= session
->security_parameters
.epoch_next
;
552 /* Update internals from CipherSuite selected.
553 * If we are resuming just copy the connection session
555 if (session
->internals
.resumed
== RESUME_FALSE
)
558 ret
= _gnutls_check_algos (session
,
560 security_parameters
.cipher_suite
,
561 _gnutls_epoch_get_compression(session
, epoch_next
));
565 ret
= _gnutls_set_kx (session
,
566 _gnutls_cipher_suite_get_kx_algo
568 security_parameters
.cipher_suite
));
572 else if (session
->security_parameters
.entity
== GNUTLS_CLIENT
)
573 _gnutls_set_resumed_parameters (session
);
575 ret
= _gnutls_epoch_set_keys (session
, epoch_next
);
579 _gnutls_handshake_log ("HSK[%p]: Cipher Suite: %s\n",
581 _gnutls_cipher_suite_get_name
583 security_parameters
.cipher_suite
));
585 session
->security_parameters
.epoch_read
= epoch_next
;
592 /* Initializes the write connection session
593 * (write encrypted data)
596 _gnutls_write_connection_state_init (gnutls_session_t session
)
598 const uint16_t epoch_next
= session
->security_parameters
.epoch_next
;
601 /* Update internals from CipherSuite selected.
602 * If we are resuming just copy the connection session
604 if (session
->internals
.resumed
== RESUME_FALSE
)
606 ret
= _gnutls_check_algos (session
,
608 security_parameters
.cipher_suite
,
609 _gnutls_epoch_get_compression(session
, epoch_next
));
613 ret
= _gnutls_set_kx (session
,
614 _gnutls_cipher_suite_get_kx_algo
616 security_parameters
.cipher_suite
));
620 else if (session
->security_parameters
.entity
== GNUTLS_SERVER
)
621 _gnutls_set_resumed_parameters (session
);
623 ret
= _gnutls_epoch_set_keys (session
, epoch_next
);
625 return gnutls_assert_val (ret
);
627 _gnutls_handshake_log ("HSK[%p]: Cipher Suite: %s\n", session
,
628 _gnutls_cipher_suite_get_name
630 security_parameters
.cipher_suite
));
632 _gnutls_handshake_log
633 ("HSK[%p]: Initializing internal [write] cipher sessions\n", session
);
635 session
->security_parameters
.epoch_write
= epoch_next
;
640 /* Sets the specified kx algorithm into pending session
643 _gnutls_set_kx (gnutls_session_t session
, gnutls_kx_algorithm_t algo
)
646 if (_gnutls_kx_is_ok (algo
) == 0)
648 session
->security_parameters
.kx_algorithm
= algo
;
651 return gnutls_assert_val (GNUTLS_E_INTERNAL_ERROR
);
653 if (_gnutls_kx_priority (session
, algo
) < 0)
654 return gnutls_assert_val (GNUTLS_E_UNWANTED_ALGORITHM
);
660 epoch_resolve (gnutls_session_t session
,
661 unsigned int epoch_rel
, uint16_t * epoch_out
)
665 case EPOCH_READ_CURRENT
:
666 *epoch_out
= session
->security_parameters
.epoch_read
;
669 case EPOCH_WRITE_CURRENT
:
670 *epoch_out
= session
->security_parameters
.epoch_write
;
674 *epoch_out
= session
->security_parameters
.epoch_next
;
678 if (epoch_rel
> 0xffffu
)
679 return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST
);
681 *epoch_out
= epoch_rel
;
686 static inline record_parameters_st
**
687 epoch_get_slot (gnutls_session_t session
, uint16_t epoch
)
689 uint16_t epoch_index
= epoch
- session
->security_parameters
.epoch_min
;
691 if (epoch_index
>= MAX_EPOCH_INDEX
)
693 _gnutls_handshake_log("Epoch %d out of range (idx: %d, max: %d)\n", (int)epoch
, (int)epoch_index
, MAX_EPOCH_INDEX
);
697 /* The slot may still be empty (NULL) */
698 return &session
->record_parameters
[epoch_index
];
702 _gnutls_epoch_get (gnutls_session_t session
, unsigned int epoch_rel
,
703 record_parameters_st
** params_out
)
706 record_parameters_st
**params
;
709 ret
= epoch_resolve (session
, epoch_rel
, &epoch
);
711 return gnutls_assert_val (ret
);
713 params
= epoch_get_slot (session
, epoch
);
714 if (params
== NULL
|| *params
== NULL
)
715 return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST
);
717 *params_out
= *params
;
723 _gnutls_epoch_alloc (gnutls_session_t session
, uint16_t epoch
,
724 record_parameters_st
** out
)
726 record_parameters_st
**slot
;
728 _gnutls_record_log ("REC[%p]: Allocating epoch #%u\n", session
, epoch
);
730 slot
= epoch_get_slot (session
, epoch
);
732 /* If slot out of range or not empty. */
734 return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST
);
737 return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST
);
739 *slot
= gnutls_calloc (1, sizeof (record_parameters_st
));
741 return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR
);
743 (*slot
)->epoch
= epoch
;
744 (*slot
)->cipher_algorithm
= GNUTLS_CIPHER_UNKNOWN
;
745 (*slot
)->mac_algorithm
= GNUTLS_MAC_UNKNOWN
;
746 (*slot
)->compression_algorithm
= GNUTLS_COMP_UNKNOWN
;
748 if (IS_DTLS (session
))
749 _gnutls_write_uint16 (epoch
, UINT64DATA((*slot
)->write
.sequence_number
));
758 epoch_is_active(gnutls_session_t session
, record_parameters_st
* params
)
760 const security_parameters_st
*sp
= &session
->security_parameters
;
762 if (params
->epoch
== sp
->epoch_read
)
765 if (params
->epoch
== sp
->epoch_write
)
768 if (params
->epoch
== sp
->epoch_next
)
775 epoch_alive (gnutls_session_t session
, record_parameters_st
* params
)
777 if (params
->usage_cnt
> 0)
780 return epoch_is_active(session
, params
);
784 _gnutls_epoch_gc (gnutls_session_t session
)
787 unsigned int min_index
= 0;
789 _gnutls_record_log ("REC[%p]: Start of epoch cleanup\n", session
);
791 /* Free all dead cipher state */
792 for (i
= 0; i
< MAX_EPOCH_INDEX
; i
++)
794 if (session
->record_parameters
[i
] != NULL
)
796 if (!epoch_is_active(session
, session
->record_parameters
[i
]) && session
->record_parameters
[i
]->usage_cnt
)
797 _gnutls_record_log ("REC[%p]: Note inactive epoch %d has %d users\n", session
, session
->record_parameters
[i
]->epoch
, session
->record_parameters
[i
]->usage_cnt
);
798 if (!epoch_alive (session
, session
->record_parameters
[i
]))
800 _gnutls_epoch_free (session
, session
->record_parameters
[i
]);
801 session
->record_parameters
[i
] = NULL
;
806 /* Look for contiguous NULLs at the start of the array */
807 for (i
= 0; i
< MAX_EPOCH_INDEX
&& session
->record_parameters
[i
] == NULL
;
811 /* Pick up the slack in the epoch window. */
812 for (i
= 0, j
= min_index
; j
< MAX_EPOCH_INDEX
; i
++, j
++)
813 session
->record_parameters
[i
] = session
->record_parameters
[j
];
815 /* Set the new epoch_min */
816 if (session
->record_parameters
[0] != NULL
)
817 session
->security_parameters
.epoch_min
=
818 session
->record_parameters
[0]->epoch
;
820 _gnutls_record_log ("REC[%p]: End of epoch cleanup\n", session
);
824 free_record_state (record_state_st
* state
, int d
)
826 _gnutls_free_datum (&state
->mac_secret
);
827 _gnutls_free_datum (&state
->IV
);
828 _gnutls_free_datum (&state
->key
);
830 _gnutls_auth_cipher_deinit (&state
->cipher_state
);
832 if (state
->compression_state
.handle
!= NULL
)
833 _gnutls_comp_deinit (&state
->compression_state
, d
);
837 _gnutls_epoch_free (gnutls_session_t session
, record_parameters_st
* params
)
839 _gnutls_record_log ("REC[%p]: Epoch #%u freed\n", session
, params
->epoch
);
841 free_record_state (¶ms
->read
, 1);
842 free_record_state (¶ms
->write
, 0);
844 gnutls_free (params
);