00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "gnutls_int.h"
00030 #include "gnutls_errors.h"
00031 #include "gnutls_cipher.h"
00032 #include "gnutls_algorithms.h"
00033 #include "gnutls_hash_int.h"
00034 #include "gnutls_cipher_int.h"
00035 #include "debug.h"
00036 #include "gnutls_num.h"
00037 #include "gnutls_datum.h"
00038 #include "gnutls_kx.h"
00039 #include "gnutls_record.h"
00040 #include "gnutls_constate.h"
00041 #include <gc.h>
00042
00043
00044
00045
00046
00047
00048 int
00049 MHD_gtls_encrypt (MHD_gtls_session_t session, const opaque * headers,
00050 size_t headers_size, const opaque * data,
00051 size_t data_size, opaque * ciphertext,
00052 size_t ciphertext_size, content_type_t type, int random_pad)
00053 {
00054 MHD_gnutls_datum_t plain;
00055 MHD_gnutls_datum_t comp;
00056 int ret;
00057 int free_comp = 1;
00058
00059 plain.data = (opaque *) data;
00060 plain.size = data_size;
00061
00062 comp = plain;
00063 free_comp = 0;
00064 ret = MHD_gtls_compressed2ciphertext (session, &ciphertext[headers_size],
00065 ciphertext_size - headers_size,
00066 comp, type, random_pad);
00067
00068 if (free_comp)
00069 MHD__gnutls_free_datum (&comp);
00070
00071 if (ret < 0)
00072 {
00073 MHD_gnutls_assert ();
00074 return ret;
00075 }
00076
00077
00078
00079 memcpy (ciphertext, headers, headers_size);
00080 MHD_gtls_write_uint16 (ret, &ciphertext[3]);
00081
00082 return ret + headers_size;
00083 }
00084
00085
00086
00087
00088 int
00089 MHD_gtls_decrypt (MHD_gtls_session_t session, opaque * ciphertext,
00090 size_t ciphertext_size, uint8_t * data,
00091 size_t max_data_size, content_type_t type)
00092 {
00093 MHD_gnutls_datum_t gcipher;
00094
00095 if (ciphertext_size == 0)
00096 return 0;
00097
00098 gcipher.size = ciphertext_size;
00099 gcipher.data = ciphertext;
00100
00101 return
00102 MHD_gtls_ciphertext2compressed (session, data, max_data_size,
00103 gcipher, type);
00104 }
00105
00106 inline static mac_hd_t
00107 mac_init (enum MHD_GNUTLS_HashAlgorithm mac, opaque * secret, int secret_size,
00108 int ver)
00109 {
00110 mac_hd_t td;
00111
00112 if (mac == MHD_GNUTLS_MAC_NULL)
00113 return GNUTLS_MAC_FAILED;
00114
00115 if (ver == MHD_GNUTLS_PROTOCOL_SSL3)
00116 {
00117 td = MHD_gnutls_mac_init_ssl3 (mac, secret, secret_size);
00118 }
00119 else
00120 {
00121 td = MHD_gtls_MHD_hmac_init (mac, secret, secret_size);
00122 }
00123
00124 return td;
00125 }
00126
00127 inline static void
00128 mac_deinit (mac_hd_t td, opaque * res, int ver)
00129 {
00130 if (ver == MHD_GNUTLS_PROTOCOL_SSL3)
00131 {
00132 MHD_gnutls_mac_deinit_ssl3 (td, res);
00133 }
00134 else
00135 {
00136 MHD_gnutls_MHD_hmac_deinit (td, res);
00137 }
00138 }
00139
00140 inline static int
00141 calc_enc_length (MHD_gtls_session_t session, int data_size,
00142 int hash_size, uint8_t * pad, int random_pad,
00143 cipher_type_t block_algo, uint16_t blocksize)
00144 {
00145 uint8_t rnd;
00146 int length;
00147
00148 *pad = 0;
00149
00150 switch (block_algo)
00151 {
00152 case CIPHER_STREAM:
00153 length = data_size + hash_size;
00154
00155 break;
00156 case CIPHER_BLOCK:
00157 if (MHD_gc_nonce ((char *) &rnd, 1) != GC_OK)
00158 {
00159 MHD_gnutls_assert ();
00160 return GNUTLS_E_RANDOM_FAILED;
00161 }
00162
00163
00164 if (session->security_parameters.version == MHD_GNUTLS_PROTOCOL_SSL3 ||
00165 random_pad == 0)
00166 {
00167 rnd = 0;
00168 }
00169 else
00170 {
00171 rnd = (rnd / blocksize) * blocksize;
00172
00173
00174
00175 if (rnd > blocksize)
00176 rnd -= blocksize;
00177 }
00178
00179 length = data_size + hash_size;
00180
00181 *pad = (uint8_t) (blocksize - (length % blocksize)) + rnd;
00182
00183 length += *pad;
00184 if (session->security_parameters.version >= MHD_GNUTLS_PROTOCOL_TLS1_1)
00185 length += blocksize;
00186
00187 break;
00188 default:
00189 MHD_gnutls_assert ();
00190 return GNUTLS_E_INTERNAL_ERROR;
00191 }
00192
00193 return length;
00194 }
00195
00196
00197
00198
00199
00200
00201 int
00202 MHD_gtls_compressed2ciphertext (MHD_gtls_session_t session,
00203 opaque * cipher_data, int cipher_size,
00204 MHD_gnutls_datum_t compressed,
00205 content_type_t _type, int random_pad)
00206 {
00207 uint8_t MAC[MAX_HASH_SIZE];
00208 uint16_t c_length;
00209 uint8_t pad;
00210 int length, ret;
00211 mac_hd_t td;
00212 uint8_t type = _type;
00213 uint8_t major, minor;
00214 int hash_size =
00215 MHD_gnutls_hash_get_algo_len (session->security_parameters.
00216 write_mac_algorithm);
00217 enum MHD_GNUTLS_Protocol ver;
00218 int blocksize =
00219 MHD_gtls_cipher_get_block_size (session->security_parameters.
00220 write_bulk_cipher_algorithm);
00221 cipher_type_t block_algo =
00222 MHD_gtls_cipher_is_block (session->security_parameters.
00223 write_bulk_cipher_algorithm);
00224 opaque *data_ptr;
00225
00226
00227 ver = MHD__gnutls_protocol_get_version (session);
00228 minor = MHD_gtls_version_get_minor (ver);
00229 major = MHD_gtls_version_get_major (ver);
00230
00231
00232
00233 td = mac_init (session->security_parameters.write_mac_algorithm,
00234 session->connection_state.write_mac_secret.data,
00235 session->connection_state.write_mac_secret.size, ver);
00236
00237 if (td == GNUTLS_MAC_FAILED
00238 && session->security_parameters.write_mac_algorithm !=
00239 MHD_GNUTLS_MAC_NULL)
00240 {
00241 MHD_gnutls_assert ();
00242 return GNUTLS_E_INTERNAL_ERROR;
00243 }
00244
00245 c_length = MHD_gtls_conv_uint16 (compressed.size);
00246
00247 if (td != GNUTLS_MAC_FAILED)
00248 {
00249 MHD_gnutls_hash (td,
00250 UINT64DATA (session->connection_state.
00251 write_sequence_number), 8);
00252
00253 MHD_gnutls_hash (td, &type, 1);
00254 if (ver >= MHD_GNUTLS_PROTOCOL_TLS1_0)
00255 {
00256 MHD_gnutls_hash (td, &major, 1);
00257 MHD_gnutls_hash (td, &minor, 1);
00258 }
00259 MHD_gnutls_hash (td, &c_length, 2);
00260 MHD_gnutls_hash (td, compressed.data, compressed.size);
00261 mac_deinit (td, MAC, ver);
00262 }
00263
00264
00265
00266
00267 length =
00268 calc_enc_length (session, compressed.size, hash_size, &pad,
00269 random_pad, block_algo, blocksize);
00270 if (length < 0)
00271 {
00272 MHD_gnutls_assert ();
00273 return length;
00274 }
00275
00276
00277
00278 if (cipher_size < length)
00279 {
00280 MHD_gnutls_assert ();
00281 return GNUTLS_E_MEMORY_ERROR;
00282 }
00283
00284 data_ptr = cipher_data;
00285 if (block_algo == CIPHER_BLOCK &&
00286 session->security_parameters.version >= MHD_GNUTLS_PROTOCOL_TLS1_1)
00287 {
00288
00289
00290 if (MHD_gc_nonce ((char *) data_ptr, blocksize) != GC_OK)
00291 {
00292 MHD_gnutls_assert ();
00293 return GNUTLS_E_RANDOM_FAILED;
00294 }
00295 data_ptr += blocksize;
00296 }
00297
00298 memcpy (data_ptr, compressed.data, compressed.size);
00299 data_ptr += compressed.size;
00300
00301 if (hash_size > 0)
00302 {
00303 memcpy (data_ptr, MAC, hash_size);
00304 data_ptr += hash_size;
00305 }
00306 if (block_algo == CIPHER_BLOCK && pad > 0)
00307 {
00308 memset (data_ptr, pad - 1, pad);
00309 }
00310
00311
00312
00313
00314 ret =
00315 MHD_gtls_cipher_encrypt (session->connection_state.write_cipher_state,
00316 cipher_data, length);
00317 if (ret < 0)
00318 {
00319 MHD_gnutls_assert ();
00320 return ret;
00321 }
00322
00323 return length;
00324 }
00325
00326
00327
00328
00329 int
00330 MHD_gtls_ciphertext2compressed (MHD_gtls_session_t session,
00331 opaque * compress_data,
00332 int compress_size,
00333 MHD_gnutls_datum_t ciphertext, uint8_t type)
00334 {
00335 uint8_t MAC[MAX_HASH_SIZE];
00336 uint16_t c_length;
00337 uint8_t pad;
00338 int length;
00339 mac_hd_t td;
00340 uint16_t blocksize;
00341 int ret, i, pad_failed = 0;
00342 uint8_t major, minor;
00343 enum MHD_GNUTLS_Protocol ver;
00344 int hash_size =
00345 MHD_gnutls_hash_get_algo_len (session->security_parameters.
00346 read_mac_algorithm);
00347
00348 ver = MHD__gnutls_protocol_get_version (session);
00349 minor = MHD_gtls_version_get_minor (ver);
00350 major = MHD_gtls_version_get_major (ver);
00351
00352 blocksize =
00353 MHD_gtls_cipher_get_block_size (session->security_parameters.
00354 read_bulk_cipher_algorithm);
00355
00356
00357
00358 td = mac_init (session->security_parameters.read_mac_algorithm,
00359 session->connection_state.read_mac_secret.data,
00360 session->connection_state.read_mac_secret.size, ver);
00361
00362 if (td == GNUTLS_MAC_FAILED
00363 && session->security_parameters.read_mac_algorithm !=
00364 MHD_GNUTLS_MAC_NULL)
00365 {
00366 MHD_gnutls_assert ();
00367 return GNUTLS_E_INTERNAL_ERROR;
00368 }
00369
00370
00371
00372
00373 switch (MHD_gtls_cipher_is_block
00374 (session->security_parameters.read_bulk_cipher_algorithm))
00375 {
00376 case CIPHER_STREAM:
00377 if ((ret =
00378 MHD_gtls_cipher_decrypt (session->connection_state.
00379 read_cipher_state, ciphertext.data,
00380 ciphertext.size)) < 0)
00381 {
00382 MHD_gnutls_assert ();
00383 return ret;
00384 }
00385
00386 length = ciphertext.size - hash_size;
00387
00388 break;
00389 case CIPHER_BLOCK:
00390 if ((ciphertext.size < blocksize) || (ciphertext.size % blocksize != 0))
00391 {
00392 MHD_gnutls_assert ();
00393 return GNUTLS_E_DECRYPTION_FAILED;
00394 }
00395
00396 if ((ret =
00397 MHD_gtls_cipher_decrypt (session->connection_state.
00398 read_cipher_state, ciphertext.data,
00399 ciphertext.size)) < 0)
00400 {
00401 MHD_gnutls_assert ();
00402 return ret;
00403 }
00404
00405
00406
00407 if (session->security_parameters.version >= MHD_GNUTLS_PROTOCOL_TLS1_1)
00408 {
00409 ciphertext.size -= blocksize;
00410 ciphertext.data += blocksize;
00411
00412 if (ciphertext.size == 0)
00413 {
00414 MHD_gnutls_assert ();
00415 return GNUTLS_E_DECRYPTION_FAILED;
00416 }
00417 }
00418
00419 pad = ciphertext.data[ciphertext.size - 1] + 1;
00420
00421 length = ciphertext.size - hash_size - pad;
00422
00423 if (pad > ciphertext.size - hash_size)
00424 {
00425 MHD_gnutls_assert ();
00426
00427
00428
00429 pad_failed = GNUTLS_E_DECRYPTION_FAILED;
00430 }
00431
00432
00433
00434 if (ver >= MHD_GNUTLS_PROTOCOL_TLS1_0 && pad_failed == 0)
00435 for (i = 2; i < pad; i++)
00436 {
00437 if (ciphertext.data[ciphertext.size - i] !=
00438 ciphertext.data[ciphertext.size - 1])
00439 pad_failed = GNUTLS_E_DECRYPTION_FAILED;
00440 }
00441 break;
00442 default:
00443 MHD_gnutls_assert ();
00444 return GNUTLS_E_INTERNAL_ERROR;
00445 }
00446
00447 if (length < 0)
00448 length = 0;
00449 c_length = MHD_gtls_conv_uint16 ((uint16_t) length);
00450
00451
00452
00453
00454 if (td != GNUTLS_MAC_FAILED)
00455 {
00456 MHD_gnutls_hash (td,
00457 UINT64DATA (session->connection_state.
00458 read_sequence_number), 8);
00459
00460 MHD_gnutls_hash (td, &type, 1);
00461 if (ver >= MHD_GNUTLS_PROTOCOL_TLS1_0)
00462 {
00463 MHD_gnutls_hash (td, &major, 1);
00464 MHD_gnutls_hash (td, &minor, 1);
00465 }
00466 MHD_gnutls_hash (td, &c_length, 2);
00467
00468 if (length > 0)
00469 MHD_gnutls_hash (td, ciphertext.data, length);
00470
00471 mac_deinit (td, MAC, ver);
00472 }
00473
00474
00475
00476
00477 if (pad_failed != 0)
00478 return pad_failed;
00479
00480
00481
00482 if ( (td != GNUTLS_MAC_FAILED) &&
00483 (memcmp (MAC, &ciphertext.data[length], hash_size) != 0) )
00484 {
00485 MHD_gnutls_assert ();
00486 return GNUTLS_E_DECRYPTION_FAILED;
00487 }
00488
00489
00490
00491 if (compress_size < length)
00492 {
00493 MHD_gnutls_assert ();
00494 return GNUTLS_E_DECOMPRESSION_FAILED;
00495 }
00496 memcpy (compress_data, ciphertext.data, length);
00497
00498 return length;
00499 }