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 2.1 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>
39 _gnutls_set_kx(gnutls_session_t session, gnutls_kx_algorithm_t algo);
41 static const char keyexp[] = "key expansion";
42 static const int keyexp_length = sizeof(keyexp) - 1;
44 /* This function is to be called after handshake, when master_secret,
45 * client_random and server_random have been initialized.
46 * This function creates the keys and stores them into pending session.
47 * (session->cipher_specs)
50 _gnutls_set_keys(gnutls_session_t session, record_parameters_st * params,
51 int hash_size, int IV_size, int key_size)
53 /* FIXME: This function is too long
55 uint8_t rnd[2 * GNUTLS_RANDOM_SIZE];
56 uint8_t rrnd[2 * GNUTLS_RANDOM_SIZE];
60 /* avoid using malloc */
61 uint8_t key_block[2 * MAX_HASH_SIZE + 2 * MAX_CIPHER_KEY_SIZE +
62 2 * MAX_CIPHER_BLOCK_SIZE];
63 record_state_st *client_write, *server_write;
65 if (session->security_parameters.entity == GNUTLS_CLIENT) {
66 client_write = ¶ms->write;
67 server_write = ¶ms->read;
69 client_write = ¶ms->read;
70 server_write = ¶ms->write;
73 block_size = 2 * hash_size + 2 * key_size;
74 block_size += 2 * IV_size;
76 memcpy(rnd, session->security_parameters.server_random,
78 memcpy(&rnd[GNUTLS_RANDOM_SIZE],
79 session->security_parameters.client_random,
82 memcpy(rrnd, session->security_parameters.client_random,
84 memcpy(&rrnd[GNUTLS_RANDOM_SIZE],
85 session->security_parameters.server_random,
88 if (get_num_version(session) == GNUTLS_SSL3) { /* SSL 3 */
90 _gnutls_ssl3_generate_random
91 (session->security_parameters.master_secret,
92 GNUTLS_MASTER_SIZE, rnd, 2 * GNUTLS_RANDOM_SIZE,
93 block_size, key_block);
94 } else { /* TLS 1.0 */
97 session->security_parameters.master_secret,
98 GNUTLS_MASTER_SIZE, keyexp, keyexp_length,
99 rnd, 2 * GNUTLS_RANDOM_SIZE, block_size,
104 return gnutls_assert_val(ret);
106 _gnutls_hard_log("INT: KEY BLOCK[%d]: %s\n", block_size,
107 _gnutls_bin2hex(key_block, block_size, buf,
113 if (_gnutls_set_datum
114 (&client_write->mac_secret, &key_block[pos],
116 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
120 if (_gnutls_set_datum
121 (&server_write->mac_secret, &key_block[pos],
123 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
129 uint8_t *client_write_key, *server_write_key;
130 int client_write_key_size, server_write_key_size;
132 client_write_key = &key_block[pos];
133 client_write_key_size = key_size;
137 server_write_key = &key_block[pos];
138 server_write_key_size = key_size;
142 if (_gnutls_set_datum
143 (&client_write->key, client_write_key,
144 client_write_key_size) < 0)
145 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
147 _gnutls_hard_log("INT: CLIENT WRITE KEY [%d]: %s\n",
148 client_write_key_size,
149 _gnutls_bin2hex(client_write_key,
150 client_write_key_size,
151 buf, sizeof(buf), NULL));
153 if (_gnutls_set_datum
154 (&server_write->key, server_write_key,
155 server_write_key_size) < 0)
156 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
158 _gnutls_hard_log("INT: SERVER WRITE KEY [%d]: %s\n",
159 server_write_key_size,
160 _gnutls_bin2hex(server_write_key,
161 server_write_key_size,
162 buf, sizeof(buf), NULL));
166 /* IV generation in export and non export ciphers.
169 if (_gnutls_set_datum
170 (&client_write->IV, &key_block[pos], IV_size) < 0)
171 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
175 if (_gnutls_set_datum
176 (&server_write->IV, &key_block[pos], IV_size) < 0)
177 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
185 _gnutls_init_record_state(record_parameters_st * params,
186 const version_entry_st * ver, int read,
187 record_state_st * state)
190 gnutls_datum_t *iv = NULL;
192 if (!_gnutls_version_has_explicit_iv(ver)) {
193 if (_gnutls_cipher_type(params->cipher) == CIPHER_BLOCK)
197 ret = _gnutls_auth_cipher_init(&state->cipher_state,
198 params->cipher, &state->key, iv,
199 params->mac, &state->mac_secret,
201 (ver->id == GNUTLS_SSL3) ? 1 : 0,
202 1 - read /*1==encrypt */ );
203 if (ret < 0 && params->cipher->id != GNUTLS_CIPHER_NULL)
204 return gnutls_assert_val(ret);
207 _gnutls_comp_init(&state->compression_state,
208 params->compression_algorithm,
209 read /*1==decompress */ );
212 return gnutls_assert_val(ret);
218 _gnutls_epoch_set_cipher_suite(gnutls_session_t session,
219 int epoch_rel, const uint8_t suite[2])
221 const cipher_entry_st *cipher_algo;
222 const mac_entry_st *mac_algo;
223 record_parameters_st *params;
226 ret = _gnutls_epoch_get(session, epoch_rel, ¶ms);
228 return gnutls_assert_val(ret);
230 if (params->initialized
231 || params->cipher != NULL || params->mac != NULL)
232 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
234 cipher_algo = _gnutls_cipher_suite_get_cipher_algo(suite);
235 mac_algo = _gnutls_cipher_suite_get_mac_algo(suite);
237 if (_gnutls_cipher_is_ok(cipher_algo) == 0
238 || _gnutls_mac_is_ok(mac_algo) == 0)
239 return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
241 if (_gnutls_cipher_priority(session, cipher_algo->id) < 0)
242 return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
244 if (_gnutls_mac_priority(session, mac_algo->id) < 0)
245 return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
247 params->cipher = cipher_algo;
248 params->mac = mac_algo;
254 _gnutls_epoch_set_compression(gnutls_session_t session,
256 gnutls_compression_method_t comp_algo)
258 record_parameters_st *params;
261 ret = _gnutls_epoch_get(session, epoch_rel, ¶ms);
263 return gnutls_assert_val(ret);
265 if (params->initialized
266 || params->compression_algorithm != GNUTLS_COMP_UNKNOWN)
267 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
269 if (_gnutls_compression_is_ok(comp_algo) != 0)
272 (GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM);
274 params->compression_algorithm = comp_algo;
280 _gnutls_epoch_set_null_algos(gnutls_session_t session,
281 record_parameters_st * params)
283 /* This is only called on startup. We are extra paranoid about this
284 because it may cause unencrypted application data to go out on
286 if (params->initialized || params->epoch != 0) {
291 params->cipher = cipher_to_entry(GNUTLS_CIPHER_NULL);
292 params->mac = mac_to_entry(GNUTLS_MAC_NULL);
293 params->compression_algorithm = GNUTLS_COMP_NULL;
294 params->initialized = 1;
297 int _gnutls_epoch_set_keys(gnutls_session_t session, uint16_t epoch)
302 gnutls_compression_method_t comp_algo;
303 record_parameters_st *params;
305 const version_entry_st *ver = get_version(session);
307 if (unlikely(ver == NULL))
308 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
310 ret = _gnutls_epoch_get(session, epoch, ¶ms);
312 return gnutls_assert_val(ret);
314 if (params->initialized)
318 ("REC[%p]: Initializing epoch #%u\n", session, params->epoch);
320 comp_algo = params->compression_algorithm;
322 if (_gnutls_cipher_is_ok(params->cipher) == 0
323 || _gnutls_mac_is_ok(params->mac) == 0)
324 return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
326 if (_gnutls_cipher_priority(session, params->cipher->id) < 0)
327 return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
329 if (_gnutls_mac_priority(session, params->mac->id) < 0)
330 return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
332 if (_gnutls_compression_is_ok(comp_algo) != 0)
335 (GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM);
337 if (!_gnutls_version_has_explicit_iv(ver) &&
338 _gnutls_cipher_type(params->cipher) == CIPHER_BLOCK) {
339 IV_size = _gnutls_cipher_get_iv_size(params->cipher);
341 IV_size = _gnutls_cipher_get_implicit_iv_size(params->cipher);
344 key_size = _gnutls_cipher_get_key_size(params->cipher);
345 hash_size = _gnutls_mac_get_key_size(params->mac);
346 params->etm = session->security_parameters.etm;
348 ret = _gnutls_set_keys
349 (session, params, hash_size, IV_size, key_size);
351 return gnutls_assert_val(ret);
353 ret = _gnutls_init_record_state(params, ver, 1, ¶ms->read);
355 return gnutls_assert_val(ret);
357 ret = _gnutls_init_record_state(params, ver, 0, ¶ms->write);
359 return gnutls_assert_val(ret);
361 params->record_sw_size = 0;
363 _gnutls_record_log("REC[%p]: Epoch #%u ready\n", session,
366 params->initialized = 1;
371 #define CPY_COMMON dst->entity = src->entity; \
372 dst->kx_algorithm = src->kx_algorithm; \
373 memcpy( dst->cipher_suite, src->cipher_suite, 2); \
374 memcpy( dst->master_secret, src->master_secret, GNUTLS_MASTER_SIZE); \
375 memcpy( dst->client_random, src->client_random, GNUTLS_RANDOM_SIZE); \
376 memcpy( dst->server_random, src->server_random, GNUTLS_RANDOM_SIZE); \
377 memcpy( dst->session_id, src->session_id, GNUTLS_MAX_SESSION_ID_SIZE); \
378 dst->session_id_size = src->session_id_size; \
379 dst->cert_type = src->cert_type; \
380 dst->compression_method = src->compression_method; \
381 dst->timestamp = src->timestamp; \
382 dst->ext_master_secret = src->ext_master_secret; \
383 dst->etm = src->etm; \
384 dst->max_record_recv_size = src->max_record_recv_size; \
385 dst->max_record_send_size = src->max_record_send_size
387 static void _gnutls_set_resumed_parameters(gnutls_session_t session)
389 security_parameters_st *src =
390 &session->internals.resumed_security_parameters;
391 security_parameters_st *dst = &session->security_parameters;
394 dst->pversion = src->pversion;
397 /* Sets the current connection session to conform with the
398 * Security parameters(pending session), and initializes encryption.
399 * Actually it initializes and starts encryption ( so it needs
400 * secrets and random numbers to have been negotiated)
401 * This is to be called after sending the Change Cipher Spec packet.
403 int _gnutls_connection_state_init(gnutls_session_t session)
407 /* Setup the master secret
409 if ((ret = _gnutls_generate_master(session, 0)) < 0)
410 return gnutls_assert_val(ret);
415 int _gnutls_epoch_get_compression(gnutls_session_t session, int epoch)
417 record_parameters_st *params;
420 ret = _gnutls_epoch_get(session, epoch, ¶ms);
422 return GNUTLS_COMP_UNKNOWN;
424 return params->compression_algorithm;
427 /* Initializes the read connection session
428 * (read encrypted data)
430 int _gnutls_read_connection_state_init(gnutls_session_t session)
432 const uint16_t epoch_next =
433 session->security_parameters.epoch_next;
436 /* Update internals from CipherSuite selected.
437 * If we are resuming just copy the connection session
439 if (session->internals.resumed == RESUME_FALSE) {
440 ret = _gnutls_set_kx(session,
441 _gnutls_cipher_suite_get_kx_algo
442 (session->security_parameters.
446 } else if (session->security_parameters.entity == GNUTLS_CLIENT)
447 _gnutls_set_resumed_parameters(session);
449 ret = _gnutls_epoch_set_keys(session, epoch_next);
453 _gnutls_handshake_log("HSK[%p]: Cipher Suite: %s\n",
455 _gnutls_cipher_suite_get_name
456 (session->security_parameters.cipher_suite));
458 session->security_parameters.epoch_read = epoch_next;
465 /* Initializes the write connection session
466 * (write encrypted data)
468 int _gnutls_write_connection_state_init(gnutls_session_t session)
470 const uint16_t epoch_next =
471 session->security_parameters.epoch_next;
474 /* Update internals from CipherSuite selected.
475 * If we are resuming just copy the connection session
477 if (session->internals.resumed == RESUME_FALSE) {
478 ret = _gnutls_set_kx(session,
479 _gnutls_cipher_suite_get_kx_algo
480 (session->security_parameters.
484 } else if (session->security_parameters.entity == GNUTLS_SERVER)
485 _gnutls_set_resumed_parameters(session);
487 ret = _gnutls_epoch_set_keys(session, epoch_next);
489 return gnutls_assert_val(ret);
491 _gnutls_handshake_log("HSK[%p]: Cipher Suite: %s\n", session,
492 _gnutls_cipher_suite_get_name
493 (session->security_parameters.cipher_suite));
495 _gnutls_handshake_log
496 ("HSK[%p]: Initializing internal [write] cipher sessions\n",
499 session->security_parameters.epoch_write = epoch_next;
504 /* Sets the specified kx algorithm into pending session
507 _gnutls_set_kx(gnutls_session_t session, gnutls_kx_algorithm_t algo)
510 if (_gnutls_kx_is_ok(algo) == 0) {
511 session->security_parameters.kx_algorithm = algo;
513 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
515 if (_gnutls_kx_priority(session, algo) < 0)
516 return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
522 epoch_resolve(gnutls_session_t session,
523 unsigned int epoch_rel, uint16_t * epoch_out)
526 case EPOCH_READ_CURRENT:
527 *epoch_out = session->security_parameters.epoch_read;
530 case EPOCH_WRITE_CURRENT:
531 *epoch_out = session->security_parameters.epoch_write;
535 *epoch_out = session->security_parameters.epoch_next;
539 if (epoch_rel > 0xffffu)
540 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
542 *epoch_out = epoch_rel;
547 static inline record_parameters_st **epoch_get_slot(gnutls_session_t
551 uint16_t epoch_index =
552 epoch - session->security_parameters.epoch_min;
554 if (epoch_index >= MAX_EPOCH_INDEX) {
555 _gnutls_handshake_log
556 ("Epoch %d out of range (idx: %d, max: %d)\n",
557 (int) epoch, (int) epoch_index, MAX_EPOCH_INDEX);
561 /* The slot may still be empty (NULL) */
562 return &session->record_parameters[epoch_index];
566 _gnutls_epoch_get(gnutls_session_t session, unsigned int epoch_rel,
567 record_parameters_st ** params_out)
570 record_parameters_st **params;
573 ret = epoch_resolve(session, epoch_rel, &epoch);
575 return gnutls_assert_val(ret);
577 params = epoch_get_slot(session, epoch);
578 if (params == NULL || *params == NULL)
579 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
581 *params_out = *params;
587 _gnutls_epoch_alloc(gnutls_session_t session, uint16_t epoch,
588 record_parameters_st ** out)
590 record_parameters_st **slot;
592 _gnutls_record_log("REC[%p]: Allocating epoch #%u\n", session,
595 slot = epoch_get_slot(session, epoch);
597 /* If slot out of range or not empty. */
599 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
602 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
604 *slot = gnutls_calloc(1, sizeof(record_parameters_st));
606 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
608 (*slot)->epoch = epoch;
609 (*slot)->cipher = NULL;
611 (*slot)->compression_algorithm = GNUTLS_COMP_UNKNOWN;
613 if (IS_DTLS(session))
614 _gnutls_write_uint16(epoch,
615 UINT64DATA((*slot)->write.
625 epoch_is_active(gnutls_session_t session, record_parameters_st * params)
627 const security_parameters_st *sp = &session->security_parameters;
629 if (params->epoch == sp->epoch_read)
632 if (params->epoch == sp->epoch_write)
635 if (params->epoch == sp->epoch_next)
642 epoch_alive(gnutls_session_t session, record_parameters_st * params)
644 if (params->usage_cnt > 0)
647 return epoch_is_active(session, params);
650 void _gnutls_epoch_gc(gnutls_session_t session)
653 unsigned int min_index = 0;
655 _gnutls_record_log("REC[%p]: Start of epoch cleanup\n", session);
657 /* Free all dead cipher state */
658 for (i = 0; i < MAX_EPOCH_INDEX; i++) {
659 if (session->record_parameters[i] != NULL) {
661 (session, session->record_parameters[i])
662 && session->record_parameters[i]->usage_cnt)
664 ("REC[%p]: Note inactive epoch %d has %d users\n",
666 session->record_parameters[i]->epoch,
667 session->record_parameters[i]->
670 (session, session->record_parameters[i])) {
671 _gnutls_epoch_free(session,
673 record_parameters[i]);
674 session->record_parameters[i] = NULL;
679 /* Look for contiguous NULLs at the start of the array */
681 i < MAX_EPOCH_INDEX && session->record_parameters[i] == NULL;
685 /* Pick up the slack in the epoch window. */
686 for (i = 0, j = min_index; j < MAX_EPOCH_INDEX; i++, j++)
687 session->record_parameters[i] =
688 session->record_parameters[j];
690 /* Set the new epoch_min */
691 if (session->record_parameters[0] != NULL)
692 session->security_parameters.epoch_min =
693 session->record_parameters[0]->epoch;
695 _gnutls_record_log("REC[%p]: End of epoch cleanup\n", session);
698 static inline void free_record_state(record_state_st * state, int d)
700 _gnutls_free_datum(&state->mac_secret);
701 _gnutls_free_datum(&state->IV);
702 _gnutls_free_datum(&state->key);
704 _gnutls_auth_cipher_deinit(&state->cipher_state);
706 if (state->compression_state.handle != NULL)
707 _gnutls_comp_deinit(&state->compression_state, d);
711 _gnutls_epoch_free(gnutls_session_t session, record_parameters_st * params)
713 _gnutls_record_log("REC[%p]: Epoch #%u freed\n", session,
716 free_record_state(¶ms->read, 1);
717 free_record_state(¶ms->write, 0);