2 * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009, 2010
3 * Free 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 /* Some high level functions to be used in the record encryption are
30 #include "gnutls_int.h"
31 #include "gnutls_errors.h"
32 #include "gnutls_compress.h"
33 #include "gnutls_cipher.h"
34 #include "gnutls_algorithms.h"
35 #include "gnutls_hash_int.h"
36 #include "gnutls_cipher_int.h"
38 #include "gnutls_num.h"
39 #include "gnutls_datum.h"
40 #include "gnutls_kx.h"
41 #include "gnutls_record.h"
42 #include "gnutls_constate.h"
46 is_write_comp_null (gnutls_session_t session
)
48 record_parameters_st
*record_params
;
50 _gnutls_epoch_get (session
, EPOCH_WRITE_CURRENT
, &record_params
);
51 if (record_params
->compression_algorithm
== GNUTLS_COMP_NULL
)
58 is_read_comp_null (gnutls_session_t session
)
60 record_parameters_st
*record_params
;
62 _gnutls_epoch_get (session
, EPOCH_READ_CURRENT
, &record_params
);
63 if (record_params
->compression_algorithm
== GNUTLS_COMP_NULL
)
70 /* returns ciphertext which contains the headers too. This also
71 * calculates the size in the header field.
73 * If random pad != 0 then the random pad data will be appended.
76 _gnutls_encrypt (gnutls_session_t session
, const opaque
* headers
,
77 size_t headers_size
, const opaque
* data
,
78 size_t data_size
, opaque
* ciphertext
,
79 size_t ciphertext_size
, content_type_t type
, int random_pad
,
80 record_parameters_st
* params
)
87 plain
.data
= (opaque
*) data
;
88 plain
.size
= data_size
;
90 if (plain
.size
== 0 || is_write_comp_null (session
) == 0)
97 /* Here comp is allocated and must be
100 ret
= _gnutls_m_plaintext2compressed (session
, &comp
, &plain
, params
);
108 ret
= _gnutls_compressed2ciphertext (session
, &ciphertext
[headers_size
],
109 ciphertext_size
- headers_size
,
110 comp
, type
, random_pad
, params
);
113 _gnutls_free_datum (&comp
);
122 /* copy the headers */
123 memcpy (ciphertext
, headers
, headers_size
);
124 _gnutls_write_uint16 (ret
, &ciphertext
[3]);
126 return ret
+ headers_size
;
129 /* Decrypts the given data.
130 * Returns the decrypted data length.
133 _gnutls_decrypt (gnutls_session_t session
, opaque
* ciphertext
,
134 size_t ciphertext_size
, uint8_t * data
,
135 size_t max_data_size
, content_type_t type
,
136 record_parameters_st
* params
)
139 gnutls_datum_t gcipher
;
142 if (ciphertext_size
== 0)
145 gcipher
.size
= ciphertext_size
;
146 gcipher
.data
= ciphertext
;
149 _gnutls_ciphertext2compressed (session
, data
, max_data_size
,
150 gcipher
, type
, params
);
156 if (ret
== 0 || is_read_comp_null (session
) == 0)
163 gnutls_datum_t gcomp
;
165 /* compression has this malloc overhead.
170 ret
= _gnutls_m_compressed2plaintext (session
, >xt
, &gcomp
, params
);
176 if (gtxt
.size
> MAX_RECORD_RECV_SIZE
)
179 _gnutls_free_datum (>xt
);
180 /* This shouldn't have happen and
181 * is a TLS fatal error.
183 return GNUTLS_E_DECOMPRESSION_FAILED
;
186 /* This check is not really needed */
187 if (max_data_size
< MAX_RECORD_RECV_SIZE
)
190 _gnutls_free_datum (>xt
);
191 return GNUTLS_E_INTERNAL_ERROR
;
194 memcpy (data
, gtxt
.data
, gtxt
.size
);
197 _gnutls_free_datum (>xt
);
204 mac_init (digest_hd_st
* td
, gnutls_mac_algorithm_t mac
, opaque
* secret
,
205 int secret_size
, int ver
)
209 if (mac
== GNUTLS_MAC_NULL
)
211 return GNUTLS_E_HASH_FAILED
;
214 if (ver
== GNUTLS_SSL3
)
216 ret
= _gnutls_mac_init_ssl3 (td
, mac
, secret
, secret_size
);
220 ret
= _gnutls_hmac_init (td
, mac
, secret
, secret_size
);
227 mac_hash (digest_hd_st
* td
, void *data
, int data_size
, int ver
)
229 if (ver
== GNUTLS_SSL3
)
231 _gnutls_hash (td
, data
, data_size
);
235 _gnutls_hmac (td
, data
, data_size
);
240 mac_deinit (digest_hd_st
* td
, opaque
* res
, int ver
)
242 if (ver
== GNUTLS_SSL3
)
244 _gnutls_mac_deinit_ssl3 (td
, res
);
248 _gnutls_hmac_deinit (td
, res
);
253 calc_enc_length (gnutls_session_t session
, int data_size
,
254 int hash_size
, uint8_t * pad
, int random_pad
,
255 cipher_type_t block_algo
, uint16_t blocksize
)
265 length
= data_size
+ hash_size
;
269 ret
= _gnutls_rnd (GNUTLS_RND_NONCE
, &rnd
, 1);
276 /* make rnd a multiple of blocksize */
277 if (session
->security_parameters
.version
== GNUTLS_SSL3
||
284 rnd
= (rnd
/ blocksize
) * blocksize
;
285 /* added to avoid the case of pad calculated 0
286 * seen below for pad calculation.
292 length
= data_size
+ hash_size
;
294 *pad
= (uint8_t) (blocksize
- (length
% blocksize
)) + rnd
;
297 if (_gnutls_version_has_explicit_iv
298 (session
->security_parameters
.version
))
299 length
+= blocksize
; /* for the IV */
304 return GNUTLS_E_INTERNAL_ERROR
;
310 #define PREAMBLE_SIZE 16
312 make_preamble (opaque
* uint64_data
, opaque type
, uint16_t c_length
,
313 opaque ver
, opaque
* preamble
)
315 opaque minor
= _gnutls_version_get_minor (ver
);
316 opaque major
= _gnutls_version_get_major (ver
);
317 opaque
*p
= preamble
;
319 memcpy (p
, uint64_data
, 8);
323 if (_gnutls_version_has_variable_padding (ver
))
324 { /* TLS 1.0 or higher */
330 memcpy (p
, &c_length
, 2);
335 /* This is the actual encryption
336 * Encrypts the given compressed datum, and puts the result to cipher_data,
337 * which has cipher_size size.
338 * return the actual encrypted data length.
341 _gnutls_compressed2ciphertext (gnutls_session_t session
,
342 opaque
* cipher_data
, int cipher_size
,
343 gnutls_datum_t compressed
,
344 content_type_t _type
, int random_pad
,
345 record_parameters_st
* params
)
347 uint8_t MAC
[MAX_HASH_SIZE
];
351 uint8_t type
= _type
;
352 opaque preamble
[PREAMBLE_SIZE
];
354 int hash_size
= _gnutls_hash_get_algo_len (params
->mac_algorithm
);
355 int blocksize
= gnutls_cipher_get_block_size (params
->cipher_algorithm
);
356 cipher_type_t block_algo
=
357 _gnutls_cipher_is_block (params
->cipher_algorithm
);
359 int ver
= gnutls_protocol_get_version (session
);
364 c_length
= _gnutls_conv_uint16 (compressed
.size
);
366 if (params
->mac_algorithm
!= GNUTLS_MAC_NULL
)
367 { /* actually when the algorithm in not the NULL one */
370 ret
= mac_init (&td
, params
->mac_algorithm
,
371 params
->write
.mac_secret
.data
,
372 params
->write
.mac_secret
.size
, ver
);
380 make_preamble (UINT64DATA
381 (params
->write
.sequence_number
),
382 type
, c_length
, ver
, preamble
);
383 mac_hash (&td
, preamble
, preamble_size
, ver
);
384 mac_hash (&td
, compressed
.data
, compressed
.size
, ver
);
385 mac_deinit (&td
, MAC
, ver
);
389 /* Calculate the encrypted length (padding etc.)
392 calc_enc_length (session
, compressed
.size
, hash_size
, &pad
,
393 random_pad
, block_algo
, blocksize
);
400 /* copy the encrypted data to cipher_data.
402 if (cipher_size
< length
)
405 return GNUTLS_E_MEMORY_ERROR
;
408 data_ptr
= cipher_data
;
409 if (block_algo
== CIPHER_BLOCK
&&
410 _gnutls_version_has_explicit_iv (session
->security_parameters
.version
))
412 /* copy the random IV.
414 ret
= _gnutls_rnd (GNUTLS_RND_NONCE
, data_ptr
, blocksize
);
421 data_ptr
+= blocksize
;
424 memcpy (data_ptr
, compressed
.data
, compressed
.size
);
425 data_ptr
+= compressed
.size
;
429 memcpy (data_ptr
, MAC
, hash_size
);
430 data_ptr
+= hash_size
;
432 if (block_algo
== CIPHER_BLOCK
&& pad
> 0)
434 memset (data_ptr
, pad
- 1, pad
);
438 /* Actual encryption (inplace).
441 _gnutls_cipher_encrypt (¶ms
->write
.cipher_state
, cipher_data
, length
);
452 /* Deciphers the ciphertext packet, and puts the result to compress_data, of compress_size.
453 * Returns the actual compressed packet size.
456 _gnutls_ciphertext2compressed (gnutls_session_t session
,
457 opaque
* compress_data
,
459 gnutls_datum_t ciphertext
, uint8_t type
,
460 record_parameters_st
* params
)
462 uint8_t MAC
[MAX_HASH_SIZE
];
467 int ret
, i
, pad_failed
= 0;
468 opaque preamble
[PREAMBLE_SIZE
];
470 int ver
= gnutls_protocol_get_version (session
);
471 int hash_size
= _gnutls_hash_get_algo_len (params
->mac_algorithm
);
473 blocksize
= gnutls_cipher_get_block_size (params
->cipher_algorithm
);
476 /* actual decryption (inplace)
478 switch (_gnutls_cipher_is_block (params
->cipher_algorithm
))
482 _gnutls_cipher_decrypt (¶ms
->read
.cipher_state
,
483 ciphertext
.data
, ciphertext
.size
)) < 0)
489 length
= ciphertext
.size
- hash_size
;
493 if ((ciphertext
.size
< blocksize
) || (ciphertext
.size
% blocksize
!= 0))
496 return GNUTLS_E_DECRYPTION_FAILED
;
500 _gnutls_cipher_decrypt (¶ms
->read
.cipher_state
,
501 ciphertext
.data
, ciphertext
.size
)) < 0)
507 /* ignore the IV in TLS 1.1.
509 if (_gnutls_version_has_explicit_iv
510 (session
->security_parameters
.version
))
512 ciphertext
.size
-= blocksize
;
513 ciphertext
.data
+= blocksize
;
516 if (ciphertext
.size
< hash_size
)
519 return GNUTLS_E_DECRYPTION_FAILED
;
521 pad
= ciphertext
.data
[ciphertext
.size
- 1] + 1; /* pad */
523 if ((int) pad
> (int) ciphertext
.size
- hash_size
)
527 ("REC[%p]: Short record length %d > %d - %d (under attack?)\n",
528 session
, pad
, ciphertext
.size
, hash_size
);
529 /* We do not fail here. We check below for the
530 * the pad_failed. If zero means success.
532 pad_failed
= GNUTLS_E_DECRYPTION_FAILED
;
535 length
= ciphertext
.size
- hash_size
- pad
;
537 /* Check the pading bytes (TLS 1.x)
539 if (_gnutls_version_has_variable_padding (ver
) && pad_failed
== 0)
540 for (i
= 2; i
< pad
; i
++)
542 if (ciphertext
.data
[ciphertext
.size
- i
] !=
543 ciphertext
.data
[ciphertext
.size
- 1])
544 pad_failed
= GNUTLS_E_DECRYPTION_FAILED
;
549 return GNUTLS_E_INTERNAL_ERROR
;
554 c_length
= _gnutls_conv_uint16 ((uint16_t) length
);
556 /* Pass the type, version, length and compressed through
559 if (params
->mac_algorithm
!= GNUTLS_MAC_NULL
)
563 ret
= mac_init (&td
, params
->mac_algorithm
,
564 params
->read
.mac_secret
.data
,
565 params
->read
.mac_secret
.size
, ver
);
570 return GNUTLS_E_INTERNAL_ERROR
;
574 make_preamble (UINT64DATA
575 (params
->read
.sequence_number
), type
,
576 c_length
, ver
, preamble
);
577 mac_hash (&td
, preamble
, preamble_size
, ver
);
579 mac_hash (&td
, ciphertext
.data
, length
, ver
);
581 mac_deinit (&td
, MAC
, ver
);
584 /* This one was introduced to avoid a timing attack against the TLS
593 /* HMAC was not the same.
595 if (memcmp (MAC
, &ciphertext
.data
[length
], hash_size
) != 0)
598 return GNUTLS_E_DECRYPTION_FAILED
;
601 /* copy the decrypted stuff to compress_data.
603 if (compress_size
< length
)
606 return GNUTLS_E_DECOMPRESSION_FAILED
;
608 memcpy (compress_data
, ciphertext
.data
, length
);