1/*
2 * Copyright (C) 2001-2012 Free Software Foundation, Inc.
3 *
4 * Author: Nikos Mavrogiannopoulos
5 *
6 * This file is part of GnuTLS.
7 *
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.
12 *
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.
17 *
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/>
20 *
21 */
22
23/* Functions that are supposed to run after the handshake procedure is
24 * finished. These functions activate the established security parameters.
25 */
26
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>
37
38static int
39_gnutls_set_kx (gnutls_session_t session, gnutls_kx_algorithm_t algo);
40
41static const char keyexp[] = "key expansion";
42static const int keyexp_length = sizeof (keyexp) - 1;
43
44static const char ivblock[] = "IV block";
45static const int ivblock_length = sizeof (ivblock) - 1;
46
47static const char cliwrite[] = "client write key";
48static const int cliwrite_length = sizeof (cliwrite) - 1;
49
50static const char servwrite[] = "server write key";
51static const int servwrite_length = sizeof (servwrite) - 1;
52
53/* This function is to be called after handshake, when master_secret,
54 * client_random and server_random have been initialized.
55 * This function creates the keys and stores them into pending session.
56 * (session->cipher_specs)
57 */
58static int
59_gnutls_set_keys (gnutls_session_t session, record_parameters_st * params,
60 int hash_size, int IV_size, int key_size)
61{
62 /* FIXME: This function is too long
63 */
64 uint8_t rnd[2 * GNUTLS_RANDOM_SIZE];
65 uint8_t rrnd[2 * GNUTLS_RANDOM_SIZE];
66 int pos, ret;
67 int block_size;
68 char buf[65];
69 /* avoid using malloc */
70 uint8_t key_block[2 * MAX_HASH_SIZE + 2 * MAX_CIPHER_KEY_SIZE +
71 2 * MAX_CIPHER_BLOCK_SIZE];
72 record_state_st *client_write, *server_write;
73
74 if (session->security_parameters.entity == GNUTLS_CLIENT)
75 {
76 client_write = &params->write;
77 server_write = &params->read;
78 }
79 else
80 {
81 client_write = &params->read;
82 server_write = &params->write;
83 }
84
85 block_size = 2 * hash_size + 2 * key_size;
86 block_size += 2 * IV_size;
87
88 memcpy (rnd, session->security_parameters.server_random,
89 GNUTLS_RANDOM_SIZE);
90 memcpy (&rnd[GNUTLS_RANDOM_SIZE],
91 session->security_parameters.client_random, GNUTLS_RANDOM_SIZE);
92
93 memcpy (rrnd, session->security_parameters.client_random,
94 GNUTLS_RANDOM_SIZE);
95 memcpy (&rrnd[GNUTLS_RANDOM_SIZE],
96 session->security_parameters.server_random, GNUTLS_RANDOM_SIZE);
97
98 if (get_num_version(session) == GNUTLS_SSL3)
99 { /* SSL 3 */
100 ret =
101 _gnutls_ssl3_generate_random
102 (session->security_parameters.master_secret, GNUTLS_MASTER_SIZE, rnd,
103 2 * GNUTLS_RANDOM_SIZE, block_size, key_block);
104 }
105 else
106 { /* TLS 1.0 */
107 ret =
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);
111 }
112
113 if (ret < 0)
114 return gnutls_assert_val (ret);
115
116 _gnutls_hard_log ("INT: KEY BLOCK[%d]: %s\n", block_size,
117 _gnutls_bin2hex (key_block, block_size, buf,
118 sizeof (buf), NULL));
119
120 pos = 0;
121 if (hash_size > 0)
122 {
123
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);
127
128 pos += hash_size;
129
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);
133
134 pos += hash_size;
135 }
136
137 if (key_size > 0)
138 {
139 uint8_t *client_write_key, *server_write_key;
140 int client_write_key_size, server_write_key_size;
141
142 client_write_key = &key_block[pos];
143 client_write_key_size = key_size;
144
145 pos += key_size;
146
147 server_write_key = &key_block[pos];
148 server_write_key_size = key_size;
149
150 pos += key_size;
151
152 if (_gnutls_set_datum
153 (&client_write->key, client_write_key, client_write_key_size) < 0)
154 return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);
155
156 _gnutls_hard_log ("INT: CLIENT WRITE KEY [%d]: %s\n",
157 client_write_key_size,
158 _gnutls_bin2hex (client_write_key,
159 client_write_key_size, buf,
160 sizeof (buf), NULL));
161
162 if (_gnutls_set_datum
163 (&server_write->key, server_write_key, server_write_key_size) < 0)
164 return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);
165
166 _gnutls_hard_log ("INT: SERVER WRITE KEY [%d]: %s\n",
167 server_write_key_size,
168 _gnutls_bin2hex (server_write_key,
169 server_write_key_size, buf,
170 sizeof (buf), NULL));
171
172 }
173
174 /* IV generation in export and non export ciphers.
175 */
176 if (IV_size > 0)
177 {
178 if (_gnutls_set_datum
179 (&client_write->IV, &key_block[pos], IV_size) < 0)
180 return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);
181
182 pos += IV_size;
183
184 if (_gnutls_set_datum
185 (&server_write->IV, &key_block[pos], IV_size) < 0)
186 return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);
187
188 }
189
190 return 0;
191}
192
193static int
194_gnutls_init_record_state (record_parameters_st * params, const version_entry_st* ver,
195 int read, record_state_st * state)
196{
197 int ret;
198 gnutls_datum_t * iv = NULL;
199
200 if (!_gnutls_version_has_explicit_iv(ver))
201 {
202 if (_gnutls_cipher_is_block (params->cipher) != CIPHER_STREAM)
203 iv = &state->IV;
204 }
205
206 ret = _gnutls_auth_cipher_init (&state->cipher_state,
207 params->cipher, &state->key, iv,
208 params->mac, &state->mac_secret, (ver->id==GNUTLS_SSL3)?1:0, 1-read/*1==encrypt*/);
209 if (ret < 0 && params->cipher->id != GNUTLS_CIPHER_NULL)
210 return gnutls_assert_val (ret);
211
212 ret =
213 _gnutls_comp_init (&state->compression_state, params->compression_algorithm, read/*1==decompress*/);
214
215 if (ret < 0)
216 return gnutls_assert_val (ret);
217
218 return 0;
219}
220
221int
222_gnutls_epoch_set_cipher_suite (gnutls_session_t session,
223 int epoch_rel, const uint8_t suite[2])
224{
225 const cipher_entry_st * cipher_algo;
226 const mac_entry_st* mac_algo;
227 record_parameters_st *params;
228 int ret;
229
230 ret = _gnutls_epoch_get (session, epoch_rel, &params);
231 if (ret < 0)
232 return gnutls_assert_val (ret);
233
234 if (params->initialized
235 || params->cipher != NULL
236 || params->mac != NULL)
237 return gnutls_assert_val (GNUTLS_E_INTERNAL_ERROR);
238
239 cipher_algo = _gnutls_cipher_suite_get_cipher_algo (suite);
240 mac_algo = _gnutls_cipher_suite_get_mac_algo (suite);
241
242 if (_gnutls_cipher_priority (session, cipher_algo->id) < 0)
243 return gnutls_assert_val (GNUTLS_E_UNWANTED_ALGORITHM);
244
245 if (_gnutls_mac_priority (session, mac_algo->id) < 0)
246 return gnutls_assert_val (GNUTLS_E_UNWANTED_ALGORITHM);
247
248 if (_gnutls_cipher_is_ok (cipher_algo) == 0
249 || _gnutls_mac_is_ok (mac_algo) == 0)
250 return gnutls_assert_val (GNUTLS_E_UNWANTED_ALGORITHM);
251
252 params->cipher = cipher_algo;
253 params->mac = mac_algo;
254
255 return 0;
256}
257
258int
259_gnutls_epoch_set_compression (gnutls_session_t session,
260 int epoch_rel,
261 gnutls_compression_method_t comp_algo)
262{
263 record_parameters_st *params;
264 int ret;
265
266 ret = _gnutls_epoch_get (session, epoch_rel, &params);
267 if (ret < 0)
268 return gnutls_assert_val (ret);
269
270 if (params->initialized
271 || params->compression_algorithm != GNUTLS_COMP_UNKNOWN)
272 return gnutls_assert_val (GNUTLS_E_INTERNAL_ERROR);
273
274 if (_gnutls_compression_is_ok (comp_algo) != 0)
275 return gnutls_assert_val (GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM);
276
277 params->compression_algorithm = comp_algo;
278
279 return 0;
280}
281
282void
283_gnutls_epoch_set_null_algos (gnutls_session_t session,
284 record_parameters_st * params)
285{
286 /* This is only called on startup. We are extra paranoid about this
287 because it may cause unencrypted application data to go out on
288 the wire. */
289 if (params->initialized || params->epoch != 0)
290 {
291 gnutls_assert ();
292 return;
293 }
294
295 params->cipher = cipher_to_entry(GNUTLS_CIPHER_NULL);
296 params->mac = mac_to_entry(GNUTLS_MAC_NULL);
297 params->compression_algorithm = GNUTLS_COMP_NULL;
298 params->initialized = 1;
299}
300
301int
302_gnutls_epoch_set_keys (gnutls_session_t session, uint16_t epoch)
303{
304 int hash_size;
305 int IV_size;
306 int key_size;
307 gnutls_compression_method_t comp_algo;
308 record_parameters_st *params;
309 int ret;
310 const version_entry_st* ver = get_version (session);
311
312 if (unlikely(ver == NULL))
313 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
314
315 ret = _gnutls_epoch_get (session, epoch, &params);
316 if (ret < 0)
317 return gnutls_assert_val (ret);
318
319 if (params->initialized)
320 return 0;
321
322 _gnutls_record_log
323 ("REC[%p]: Initializing epoch #%u\n", session, params->epoch);
324
325 comp_algo = params->compression_algorithm;
326
327 if (_gnutls_cipher_priority (session, params->cipher->id) < 0)
328 return gnutls_assert_val (GNUTLS_E_UNWANTED_ALGORITHM);
329
330 if (_gnutls_mac_priority (session, params->mac->id) < 0)
331 return gnutls_assert_val (GNUTLS_E_UNWANTED_ALGORITHM);
332
333 if (_gnutls_cipher_is_ok (params->cipher) == 0
334 || _gnutls_mac_is_ok (params->mac) == 0)
335 return gnutls_assert_val (GNUTLS_E_UNWANTED_ALGORITHM);
336
337 if (_gnutls_compression_is_ok (comp_algo) != 0)
338 return gnutls_assert_val (GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM);
339
340 IV_size = _gnutls_cipher_get_iv_size (params->cipher);
341 key_size = _gnutls_cipher_get_key_size (params->cipher);
342 hash_size = _gnutls_mac_get_key_size (params->mac);
343
344 ret = _gnutls_set_keys
345 (session, params, hash_size, IV_size, key_size);
346 if (ret < 0)
347 return gnutls_assert_val (ret);
348
349 ret = _gnutls_init_record_state (params, ver, 1, &params->read);
350 if (ret < 0)
351 return gnutls_assert_val (ret);
352 params->read.new_record_padding = session->security_parameters.new_record_padding;
353
354 ret = _gnutls_init_record_state (params, ver, 0, &params->write);
355 if (ret < 0)
356 return gnutls_assert_val (ret);
357 params->write.new_record_padding = session->security_parameters.new_record_padding;
358
359 params->record_sw_size = 0;
360
361 _gnutls_record_log ("REC[%p]: Epoch #%u ready\n", session, params->epoch);
362
363 params->initialized = 1;
364 return 0;
365}
366
367
368#define CPY_COMMON dst->entity = src->entity; \
369 dst->kx_algorithm = src->kx_algorithm; \
370 memcpy( dst->cipher_suite, src->cipher_suite, 2); \
371 memcpy( dst->master_secret, src->master_secret, GNUTLS_MASTER_SIZE); \
372 memcpy( dst->client_random, src->client_random, GNUTLS_RANDOM_SIZE); \
373 memcpy( dst->server_random, src->server_random, GNUTLS_RANDOM_SIZE); \
374 memcpy( dst->session_id, src->session_id, TLS_MAX_SESSION_ID_SIZE); \
375 dst->session_id_size = src->session_id_size; \
376 dst->cert_type = src->cert_type; \
377 dst->compression_method = src->compression_method; \
378 dst->timestamp = src->timestamp; \
379 dst->max_record_recv_size = src->max_record_recv_size; \
380 dst->max_record_send_size = src->max_record_send_size
381
382static void
383_gnutls_set_resumed_parameters (gnutls_session_t session)
384{
385 security_parameters_st *src =
386 &session->internals.resumed_security_parameters;
387 security_parameters_st *dst = &session->security_parameters;
388
389 CPY_COMMON;
390 dst->pversion = src->pversion;
391}
392
393/* Sets the current connection session to conform with the
394 * Security parameters(pending session), and initializes encryption.
395 * Actually it initializes and starts encryption ( so it needs
396 * secrets and random numbers to have been negotiated)
397 * This is to be called after sending the Change Cipher Spec packet.
398 */
399int
400_gnutls_connection_state_init (gnutls_session_t session)
401{
402 int ret;
403
404/* Setup the master secret
405 */
406 if ((ret = _gnutls_generate_master (session, 0)) < 0)
407 return gnutls_assert_val (ret);
408
409 return 0;
410}
411
412int _gnutls_epoch_get_compression(gnutls_session_t session, int epoch)
413{
414record_parameters_st *params;
415int ret;
416
417 ret = _gnutls_epoch_get (session, epoch, &params);
418 if (ret < 0)
419 return GNUTLS_COMP_UNKNOWN;
420
421 return params->compression_algorithm;
422}
423
424/* Initializes the read connection session
425 * (read encrypted data)
426 */
427int
428_gnutls_read_connection_state_init (gnutls_session_t session)
429{
430 const uint16_t epoch_next = session->security_parameters.epoch_next;
431 int ret;
432
433 /* Update internals from CipherSuite selected.
434 * If we are resuming just copy the connection session
435 */
436 if (session->internals.resumed == RESUME_FALSE)
437 {
438 ret = _gnutls_set_kx (session,
439 _gnutls_cipher_suite_get_kx_algo
440 (session->
441 security_parameters.cipher_suite));
442 if (ret < 0)
443 return ret;
444 }
445 else if (session->security_parameters.entity == GNUTLS_CLIENT)
446 _gnutls_set_resumed_parameters (session);
447
448 ret = _gnutls_epoch_set_keys (session, epoch_next);
449 if (ret < 0)
450 return ret;
451
452 _gnutls_handshake_log ("HSK[%p]: Cipher Suite: %s\n",
453 session,
454 _gnutls_cipher_suite_get_name
455 (session->
456 security_parameters.cipher_suite));
457
458 session->security_parameters.epoch_read = epoch_next;
459
460 return 0;
461}
462
463
464
465/* Initializes the write connection session
466 * (write encrypted data)
467 */
468int
469_gnutls_write_connection_state_init (gnutls_session_t session)
470{
471 const uint16_t epoch_next = session->security_parameters.epoch_next;
472 int ret;
473
474/* Update internals from CipherSuite selected.
475 * If we are resuming just copy the connection session
476 */
477 if (session->internals.resumed == RESUME_FALSE)
478 {
479 ret = _gnutls_set_kx (session,
480 _gnutls_cipher_suite_get_kx_algo
481 (session->
482 security_parameters.cipher_suite));
483 if (ret < 0)
484 return ret;
485 }
486 else if (session->security_parameters.entity == GNUTLS_SERVER)
487 _gnutls_set_resumed_parameters (session);
488
489 ret = _gnutls_epoch_set_keys (session, epoch_next);
490 if (ret < 0)
491 return gnutls_assert_val (ret);
492
493 _gnutls_handshake_log ("HSK[%p]: Cipher Suite: %s\n", session,
494 _gnutls_cipher_suite_get_name
495 (session->
496 security_parameters.cipher_suite));
497
498 _gnutls_handshake_log
499 ("HSK[%p]: Initializing internal [write] cipher sessions\n", session);
500
501 session->security_parameters.epoch_write = epoch_next;
502
503 return 0;
504}
505
506/* Sets the specified kx algorithm into pending session
507 */
508static int
509_gnutls_set_kx (gnutls_session_t session, gnutls_kx_algorithm_t algo)
510{
511
512 if (_gnutls_kx_is_ok (algo) == 0)
513 {
514 session->security_parameters.kx_algorithm = algo;
515 }
516 else
517 return gnutls_assert_val (GNUTLS_E_INTERNAL_ERROR);
518
519 if (_gnutls_kx_priority (session, algo) < 0)
520 return gnutls_assert_val (GNUTLS_E_UNWANTED_ALGORITHM);
521
522 return 0;
523}
524
525static inline int
526epoch_resolve (gnutls_session_t session,
527 unsigned int epoch_rel, uint16_t * epoch_out)
528{
529 switch (epoch_rel)
530 {
531 case EPOCH_READ_CURRENT:
532 *epoch_out = session->security_parameters.epoch_read;
533 return 0;
534
535 case EPOCH_WRITE_CURRENT:
536 *epoch_out = session->security_parameters.epoch_write;
537 return 0;
538
539 case EPOCH_NEXT:
540 *epoch_out = session->security_parameters.epoch_next;
541 return 0;
542
543 default:
544 if (epoch_rel > 0xffffu)
545 return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST);
546
547 *epoch_out = epoch_rel;
548 return 0;
549 }
550}
551
552static inline record_parameters_st **
553epoch_get_slot (gnutls_session_t session, uint16_t epoch)
554{
555 uint16_t epoch_index = epoch - session->security_parameters.epoch_min;
556
557 if (epoch_index >= MAX_EPOCH_INDEX)
558 {
559 _gnutls_handshake_log("Epoch %d out of range (idx: %d, max: %d)\n", (int)epoch, (int)epoch_index, MAX_EPOCH_INDEX);
560 gnutls_assert ();
561 return NULL;
562 }
563 /* The slot may still be empty (NULL) */
564 return &session->record_parameters[epoch_index];
565}
566
567int
568_gnutls_epoch_get (gnutls_session_t session, unsigned int epoch_rel,
569 record_parameters_st ** params_out)
570{
571 uint16_t epoch;
572 record_parameters_st **params;
573 int ret;
574
575 ret = epoch_resolve (session, epoch_rel, &epoch);
576 if (ret < 0)
577 return gnutls_assert_val (ret);
578
579 params = epoch_get_slot (session, epoch);
580 if (params == NULL || *params == NULL)
581 return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST);
582
583 *params_out = *params;
584
585 return 0;
586}
587
588int
589_gnutls_epoch_alloc (gnutls_session_t session, uint16_t epoch,
590 record_parameters_st ** out)
591{
592 record_parameters_st **slot;
593
594 _gnutls_record_log ("REC[%p]: Allocating epoch #%u\n", session, epoch);
595
596 slot = epoch_get_slot (session, epoch);
597
598 /* If slot out of range or not empty. */
599 if (slot == NULL)
600 return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST);
601
602 if (*slot != NULL)
603 return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST);
604
605 *slot = gnutls_calloc (1, sizeof (record_parameters_st));
606 if (*slot == NULL)
607 return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);
608
609 (*slot)->epoch = epoch;
610 (*slot)->cipher = NULL;
611 (*slot)->mac = NULL;
612 (*slot)->compression_algorithm = GNUTLS_COMP_UNKNOWN;
613
614 if (IS_DTLS (session))
615 _gnutls_write_uint16 (epoch, UINT64DATA((*slot)->write.sequence_number));
616
617 if (out != NULL)
618 *out = *slot;
619
620 return 0;
621}
622
623static inline int
624epoch_is_active(gnutls_session_t session, record_parameters_st * params)
625{
626 const security_parameters_st *sp = &session->security_parameters;
627
628 if (params->epoch == sp->epoch_read)
629 return 1;
630
631 if (params->epoch == sp->epoch_write)
632 return 1;
633
634 if (params->epoch == sp->epoch_next)
635 return 1;
636
637 return 0;
638}
639
640static inline int
641epoch_alive (gnutls_session_t session, record_parameters_st * params)
642{
643 if (params->usage_cnt > 0)
644 return 1;
645
646 return epoch_is_active(session, params);
647}
648
649void
650_gnutls_epoch_gc (gnutls_session_t session)
651{
652 int i, j;
653 unsigned int min_index = 0;
654
655 _gnutls_record_log ("REC[%p]: Start of epoch cleanup\n", session);
656
657 /* Free all dead cipher state */
658 for (i = 0; i < MAX_EPOCH_INDEX; i++)
659 {
660 if (session->record_parameters[i] != NULL)
661 {
662 if (!epoch_is_active(session, session->record_parameters[i]) && session->record_parameters[i]->usage_cnt)
663 _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);
664 if (!epoch_alive (session, session->record_parameters[i]))
665 {
666 _gnutls_epoch_free (session, session->record_parameters[i]);
667 session->record_parameters[i] = NULL;
668 }
669 }
670 }
671
672 /* Look for contiguous NULLs at the start of the array */
673 for (i = 0; i < MAX_EPOCH_INDEX && session->record_parameters[i] == NULL;
674 i++);
675 min_index = i;
676
677 /* Pick up the slack in the epoch window. */
678 for (i = 0, j = min_index; j < MAX_EPOCH_INDEX; i++, j++)
679 session->record_parameters[i] = session->record_parameters[j];
680
681 /* Set the new epoch_min */
682 if (session->record_parameters[0] != NULL)
683 session->security_parameters.epoch_min =
684 session->record_parameters[0]->epoch;
685
686 _gnutls_record_log ("REC[%p]: End of epoch cleanup\n", session);
687}
688
689static inline void
690free_record_state (record_state_st * state, int d)
691{
692 _gnutls_free_datum (&state->mac_secret);
693 _gnutls_free_datum (&state->IV);
694 _gnutls_free_datum (&state->key);
695
696 _gnutls_auth_cipher_deinit (&state->cipher_state);
697
698 if (state->compression_state.handle != NULL)
699 _gnutls_comp_deinit (&state->compression_state, d);
700}
701
702void
703_gnutls_epoch_free (gnutls_session_t session, record_parameters_st * params)
704{
705 _gnutls_record_log ("REC[%p]: Epoch #%u freed\n", session, params->epoch);
706
707 free_record_state (&params->read, 1);
708 free_record_state (&params->write, 0);
709
710 gnutls_free (params);
711}
712