gnutls_constate.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006  Free Software Foundation
00003  *
00004  * Author: Nikos Mavrogiannopoulos
00005  *
00006  * This file is part of GNUTLS.
00007  *
00008  * The GNUTLS library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public License
00010  * as published by the Free Software Foundation; either version 2.1 of
00011  * the License, or (at your option) any later version.
00012  *
00013  * This library is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with this library; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
00021  * USA
00022  *
00023  */
00024 
00025 /* Functions that are supposed to run after the handshake procedure is
00026  * finished. These functions activate the established security parameters.
00027  */
00028 
00029 #include "MHD_config.h"
00030 #include <gnutls_int.h>
00031 #include <gnutls_constate.h>
00032 #include <gnutls_errors.h>
00033 #include <gnutls_kx.h>
00034 #include <gnutls_algorithms.h>
00035 #include <gnutls_num.h>
00036 #include <gnutls_datum.h>
00037 #include <gnutls_state.h>
00038 
00039 static const char keyexp[] = "key expansion";
00040 static const int keyexp_length = sizeof (keyexp) - 1;
00041 
00042 static const char ivblock[] = "IV block";
00043 static const int ivblock_length = sizeof (ivblock) - 1;
00044 
00045 static const char cliwrite[] = "client write key";
00046 static const int cliwrite_length = sizeof (cliwrite) - 1;
00047 
00048 static const char servwrite[] = "server write key";
00049 static const int servwrite_length = sizeof (servwrite) - 1;
00050 
00051 #define EXPORT_FINAL_KEY_SIZE 16
00052 
00053 /* This function is to be called after handshake, when master_secret,
00054  *  client_random and server_random have been initialized.
00055  * This function creates the keys and stores them into pending session.
00056  * (session->cipher_specs)
00057  */
00058 int
00059 MHD__gnutls_set_keys (MHD_gtls_session_t session, int hash_size, int IV_size,
00060                       int key_size, int export_flag)
00061 {
00062   opaque *key_block;
00063   opaque rnd[2 * TLS_RANDOM_SIZE];
00064   opaque rrnd[2 * TLS_RANDOM_SIZE];
00065   int pos, ret;
00066   int block_size;
00067   char buf[65];
00068 
00069   if (session->cipher_specs.generated_keys != 0)
00070     {
00071       /* keys have already been generated.
00072        * reset generated_keys and exit normally.
00073        */
00074       session->cipher_specs.generated_keys = 0;
00075       return 0;
00076     }
00077 
00078   block_size = 2 * hash_size + 2 * key_size;
00079   if (export_flag == 0)
00080     block_size += 2 * IV_size;
00081 
00082   key_block = MHD_gnutls_secure_malloc (block_size);
00083   if (key_block == NULL)
00084     {
00085       MHD_gnutls_assert ();
00086       return GNUTLS_E_MEMORY_ERROR;
00087     }
00088 
00089   memcpy (rnd, session->security_parameters.server_random, TLS_RANDOM_SIZE);
00090   memcpy (&rnd[TLS_RANDOM_SIZE],
00091           session->security_parameters.client_random, TLS_RANDOM_SIZE);
00092 
00093   memcpy (rrnd, session->security_parameters.client_random, TLS_RANDOM_SIZE);
00094   memcpy (&rrnd[TLS_RANDOM_SIZE],
00095           session->security_parameters.server_random, TLS_RANDOM_SIZE);
00096 
00097   if (session->security_parameters.version == MHD_GNUTLS_PROTOCOL_SSL3)
00098     {                           /* SSL 3 */
00099       ret =
00100         MHD_gnutls_ssl3_generate_random
00101         (session->security_parameters.master_secret, TLS_MASTER_SIZE, rnd,
00102          2 * TLS_RANDOM_SIZE, block_size, key_block);
00103     }
00104   else
00105     {                           /* TLS 1.0 */
00106       ret =
00107         MHD_gtls_PRF (session,
00108                       (const unsigned char *) session->
00109                       security_parameters.master_secret, TLS_MASTER_SIZE,
00110                       keyexp, keyexp_length, rnd, 2 * TLS_RANDOM_SIZE,
00111                       block_size, key_block);
00112     }
00113 
00114   if (ret < 0)
00115     {
00116       MHD_gnutls_assert ();
00117       MHD_gnutls_free (key_block);
00118       return ret;
00119     }
00120 
00121   MHD__gnutls_hard_log ("INT: KEY BLOCK[%d]: %s\n", block_size,
00122                         MHD_gtls_bin2hex (key_block, block_size, buf,
00123                                           sizeof (buf)));
00124 
00125   pos = 0;
00126   if (hash_size > 0)
00127     {
00128       if (MHD__gnutls_sset_datum
00129           (&session->cipher_specs.client_write_mac_secret,
00130            &key_block[pos], hash_size) < 0)
00131         {
00132           MHD_gnutls_free (key_block);
00133           return GNUTLS_E_MEMORY_ERROR;
00134         }
00135       pos += hash_size;
00136 
00137       if (MHD__gnutls_sset_datum
00138           (&session->cipher_specs.server_write_mac_secret,
00139            &key_block[pos], hash_size) < 0)
00140         {
00141           MHD_gnutls_free (key_block);
00142           return GNUTLS_E_MEMORY_ERROR;
00143         }
00144       pos += hash_size;
00145     }
00146 
00147   if (key_size > 0)
00148     {
00149       opaque *client_write_key, *server_write_key;
00150       int client_write_key_size, server_write_key_size;
00151       int free_keys = 0;
00152 
00153       if (export_flag == 0)
00154         {
00155           client_write_key = &key_block[pos];
00156           client_write_key_size = key_size;
00157 
00158           pos += key_size;
00159 
00160           server_write_key = &key_block[pos];
00161           server_write_key_size = key_size;
00162 
00163           pos += key_size;
00164 
00165         }
00166       else
00167         {                       /* export */
00168           free_keys = 1;
00169 
00170           client_write_key = MHD_gnutls_secure_malloc (EXPORT_FINAL_KEY_SIZE);
00171           if (client_write_key == NULL)
00172             {
00173               MHD_gnutls_assert ();
00174               MHD_gnutls_free (key_block);
00175               return GNUTLS_E_MEMORY_ERROR;
00176             }
00177 
00178           server_write_key = MHD_gnutls_secure_malloc (EXPORT_FINAL_KEY_SIZE);
00179           if (server_write_key == NULL)
00180             {
00181               MHD_gnutls_assert ();
00182               MHD_gnutls_free (key_block);
00183               MHD_gnutls_free (client_write_key);
00184               return GNUTLS_E_MEMORY_ERROR;
00185             }
00186 
00187           /* generate the final keys */
00188 
00189           if (session->security_parameters.version ==
00190               MHD_GNUTLS_PROTOCOL_SSL3)
00191             {                   /* SSL 3 */
00192               ret =
00193                 MHD_gnutls_ssl3_hash_md5 (&key_block[pos],
00194                                           key_size, rrnd,
00195                                           2 * TLS_RANDOM_SIZE,
00196                                           EXPORT_FINAL_KEY_SIZE,
00197                                           client_write_key);
00198 
00199             }
00200           else
00201             {                   /* TLS 1.0 */
00202               ret =
00203                 MHD_gtls_PRF (session, &key_block[pos], key_size,
00204                               cliwrite, cliwrite_length,
00205                               rrnd,
00206                               2 * TLS_RANDOM_SIZE,
00207                               EXPORT_FINAL_KEY_SIZE, client_write_key);
00208             }
00209 
00210           if (ret < 0)
00211             {
00212               MHD_gnutls_assert ();
00213               MHD_gnutls_free (key_block);
00214               MHD_gnutls_free (server_write_key);
00215               MHD_gnutls_free (client_write_key);
00216               return ret;
00217             }
00218 
00219           client_write_key_size = EXPORT_FINAL_KEY_SIZE;
00220           pos += key_size;
00221 
00222           if (session->security_parameters.version ==
00223               MHD_GNUTLS_PROTOCOL_SSL3)
00224             {                   /* SSL 3 */
00225               ret =
00226                 MHD_gnutls_ssl3_hash_md5 (&key_block[pos], key_size,
00227                                           rnd, 2 * TLS_RANDOM_SIZE,
00228                                           EXPORT_FINAL_KEY_SIZE,
00229                                           server_write_key);
00230             }
00231           else
00232             {                   /* TLS 1.0 */
00233               ret =
00234                 MHD_gtls_PRF (session, &key_block[pos], key_size,
00235                               servwrite, servwrite_length,
00236                               rrnd, 2 * TLS_RANDOM_SIZE,
00237                               EXPORT_FINAL_KEY_SIZE, server_write_key);
00238             }
00239 
00240           if (ret < 0)
00241             {
00242               MHD_gnutls_assert ();
00243               MHD_gnutls_free (key_block);
00244               MHD_gnutls_free (server_write_key);
00245               MHD_gnutls_free (client_write_key);
00246               return ret;
00247             }
00248 
00249           server_write_key_size = EXPORT_FINAL_KEY_SIZE;
00250           pos += key_size;
00251         }
00252 
00253       if (MHD__gnutls_sset_datum
00254           (&session->cipher_specs.client_write_key,
00255            client_write_key, client_write_key_size) < 0)
00256         {
00257           MHD_gnutls_free (key_block);
00258           MHD_gnutls_free (server_write_key);
00259           MHD_gnutls_free (client_write_key);
00260           return GNUTLS_E_MEMORY_ERROR;
00261         }
00262       MHD__gnutls_hard_log ("INT: CLIENT WRITE KEY [%d]: %s\n",
00263                             client_write_key_size,
00264                             MHD_gtls_bin2hex (client_write_key,
00265                                               client_write_key_size, buf,
00266                                               sizeof (buf)));
00267 
00268       if (MHD__gnutls_sset_datum
00269           (&session->cipher_specs.server_write_key,
00270            server_write_key, server_write_key_size) < 0)
00271         {
00272           MHD_gnutls_free (key_block);
00273           MHD_gnutls_free (server_write_key);
00274           MHD_gnutls_free (client_write_key);
00275           return GNUTLS_E_MEMORY_ERROR;
00276         }
00277 
00278       MHD__gnutls_hard_log ("INT: SERVER WRITE KEY [%d]: %s\n",
00279                             server_write_key_size,
00280                             MHD_gtls_bin2hex (server_write_key,
00281                                               server_write_key_size, buf,
00282                                               sizeof (buf)));
00283 
00284       if (free_keys != 0)
00285         {
00286           MHD_gnutls_free (server_write_key);
00287           MHD_gnutls_free (client_write_key);
00288         }
00289     }
00290 
00291 
00292   /* IV generation in export and non export ciphers.
00293    */
00294   if (IV_size > 0 && export_flag == 0)
00295     {
00296       if (MHD__gnutls_sset_datum
00297           (&session->cipher_specs.client_write_IV, &key_block[pos],
00298            IV_size) < 0)
00299         {
00300           MHD_gnutls_free (key_block);
00301           return GNUTLS_E_MEMORY_ERROR;
00302         }
00303       pos += IV_size;
00304 
00305       if (MHD__gnutls_sset_datum
00306           (&session->cipher_specs.server_write_IV, &key_block[pos],
00307            IV_size) < 0)
00308         {
00309           MHD_gnutls_free (key_block);
00310           return GNUTLS_E_MEMORY_ERROR;
00311         }
00312       pos += IV_size;
00313 
00314     }
00315   else if (IV_size > 0 && export_flag != 0)
00316     {
00317       opaque *iv_block = MHD_gnutls_alloca (IV_size * 2);
00318       if (iv_block == NULL)
00319         {
00320           MHD_gnutls_assert ();
00321           MHD_gnutls_free (key_block);
00322           return GNUTLS_E_MEMORY_ERROR;
00323         }
00324 
00325       if (session->security_parameters.version == MHD_GNUTLS_PROTOCOL_SSL3)
00326         {                       /* SSL 3 */
00327           ret = MHD_gnutls_ssl3_hash_md5 ("", 0,
00328                                           rrnd, TLS_RANDOM_SIZE * 2,
00329                                           IV_size, iv_block);
00330 
00331           if (ret < 0)
00332             {
00333               MHD_gnutls_assert ();
00334               MHD_gnutls_free (key_block);
00335               MHD_gnutls_afree (iv_block);
00336               return ret;
00337             }
00338 
00339           ret = MHD_gnutls_ssl3_hash_md5 ("", 0, rnd,
00340                                           TLS_RANDOM_SIZE * 2,
00341                                           IV_size, &iv_block[IV_size]);
00342 
00343         }
00344       else
00345         {                       /* TLS 1.0 */
00346           ret = MHD_gtls_PRF (session, (const unsigned char *) "", 0,
00347                               ivblock, ivblock_length, rrnd,
00348                               2 * TLS_RANDOM_SIZE, IV_size * 2, iv_block);
00349         }
00350 
00351       if (ret < 0)
00352         {
00353           MHD_gnutls_assert ();
00354           MHD_gnutls_afree (iv_block);
00355           MHD_gnutls_free (key_block);
00356           return ret;
00357         }
00358 
00359       if (MHD__gnutls_sset_datum
00360           (&session->cipher_specs.client_write_IV, iv_block, IV_size) < 0)
00361         {
00362           MHD_gnutls_afree (iv_block);
00363           MHD_gnutls_free (key_block);
00364           return GNUTLS_E_MEMORY_ERROR;
00365         }
00366 
00367       if (MHD__gnutls_sset_datum
00368           (&session->cipher_specs.server_write_IV,
00369            &iv_block[IV_size], IV_size) < 0)
00370         {
00371           MHD_gnutls_afree (iv_block);
00372           MHD_gnutls_free (key_block);
00373           return GNUTLS_E_MEMORY_ERROR;
00374         }
00375 
00376       MHD_gnutls_afree (iv_block);
00377     }
00378 
00379   MHD_gnutls_free (key_block);
00380 
00381   session->cipher_specs.generated_keys = 1;
00382 
00383   return 0;
00384 }
00385 
00386 int
00387 MHD__gnutls_set_read_keys (MHD_gtls_session_t session)
00388 {
00389   int hash_size;
00390   int IV_size;
00391   int key_size, export_flag;
00392   enum MHD_GNUTLS_CipherAlgorithm algo;
00393   enum MHD_GNUTLS_HashAlgorithm mac_algo;
00394 
00395   mac_algo = session->security_parameters.read_mac_algorithm;
00396   algo = session->security_parameters.read_bulk_cipher_algorithm;
00397 
00398   hash_size = MHD_gnutls_hash_get_algo_len (mac_algo);
00399   IV_size = MHD_gtls_cipher_get_iv_size (algo);
00400   key_size = MHD__gnutls_cipher_get_key_size (algo);
00401   export_flag = MHD_gtls_cipher_get_export_flag (algo);
00402 
00403   return MHD__gnutls_set_keys (session, hash_size, IV_size, key_size,
00404                                export_flag);
00405 }
00406 
00407 int
00408 MHD__gnutls_set_write_keys (MHD_gtls_session_t session)
00409 {
00410   int hash_size;
00411   int IV_size;
00412   int key_size, export_flag;
00413   enum MHD_GNUTLS_CipherAlgorithm algo;
00414   enum MHD_GNUTLS_HashAlgorithm mac_algo;
00415 
00416   mac_algo = session->security_parameters.write_mac_algorithm;
00417   algo = session->security_parameters.write_bulk_cipher_algorithm;
00418 
00419   hash_size = MHD_gnutls_hash_get_algo_len (mac_algo);
00420   IV_size = MHD_gtls_cipher_get_iv_size (algo);
00421   key_size = MHD__gnutls_cipher_get_key_size (algo);
00422   export_flag = MHD_gtls_cipher_get_export_flag (algo);
00423 
00424   return MHD__gnutls_set_keys (session, hash_size, IV_size, key_size,
00425                                export_flag);
00426 }
00427 
00428 #define CPY_COMMON dst->entity = src->entity; \
00429         dst->kx_algorithm = src->kx_algorithm; \
00430         memcpy( &dst->current_cipher_suite, &src->current_cipher_suite, sizeof(cipher_suite_st)); \
00431         memcpy( dst->master_secret, src->master_secret, TLS_MASTER_SIZE); \
00432         memcpy( dst->client_random, src->client_random, TLS_RANDOM_SIZE); \
00433         memcpy( dst->server_random, src->server_random, TLS_RANDOM_SIZE); \
00434         memcpy( dst->session_id, src->session_id, TLS_MAX_SESSION_ID_SIZE); \
00435         dst->session_id_size = src->session_id_size; \
00436         dst->cert_type = src->cert_type; \
00437         dst->timestamp = src->timestamp; \
00438         dst->max_record_recv_size = src->max_record_recv_size; \
00439         dst->max_record_send_size = src->max_record_send_size; \
00440         dst->version = src->version; \
00441         memcpy( &dst->extensions, &src->extensions, sizeof(MHD_gtls_ext_st)); \
00442         memcpy( &dst->inner_secret, &src->inner_secret, TLS_MASTER_SIZE);
00443 
00444 static void
00445 MHD__gnutls_cpy_read_security_parameters (MHD_gtls_security_param_st *
00446                                           dst,
00447                                           MHD_gtls_security_param_st * src)
00448 {
00449   CPY_COMMON;
00450 
00451   dst->read_bulk_cipher_algorithm = src->read_bulk_cipher_algorithm;
00452   dst->read_mac_algorithm = src->read_mac_algorithm;
00453   dst->read_compression_algorithm = src->read_compression_algorithm;
00454 }
00455 
00456 static void
00457 MHD__gnutls_cpy_write_security_parameters (MHD_gtls_security_param_st *
00458                                            dst,
00459                                            MHD_gtls_security_param_st * src)
00460 {
00461   CPY_COMMON;
00462 
00463   dst->write_bulk_cipher_algorithm = src->write_bulk_cipher_algorithm;
00464   dst->write_mac_algorithm = src->write_mac_algorithm;
00465   dst->write_compression_algorithm = src->write_compression_algorithm;
00466 }
00467 
00468 /* Sets the current connection session to conform with the
00469  * Security parameters(pending session), and initializes encryption.
00470  * Actually it initializes and starts encryption ( so it needs
00471  * secrets and random numbers to have been negotiated)
00472  * This is to be called after sending the Change Cipher Spec packet.
00473  */
00474 int
00475 MHD_gtls_connection_state_init (MHD_gtls_session_t session)
00476 {
00477   int ret;
00478 
00479 /* Setup the master secret
00480  */
00481   if ((ret = MHD_gtls_generate_master (session, 0), 0) < 0)
00482     {
00483       MHD_gnutls_assert ();
00484       return ret;
00485     }
00486 
00487 
00488   return 0;
00489 }
00490 
00491 
00492 /* Initializes the read connection session
00493  * (read encrypted data)
00494  */
00495 int
00496 MHD_gtls_read_connection_state_init (MHD_gtls_session_t session)
00497 {
00498   int mac_size;
00499   int rc;
00500 
00501   MHD__gnutls_uint64zero (session->connection_state.read_sequence_number);
00502 
00503 /* Update internals from CipherSuite selected.
00504  * If we are resuming just copy the connection session
00505  */
00506   if (session->internals.resumed == RESUME_FALSE)
00507     {
00508       rc = MHD_gtls_set_read_cipher (session,
00509                                      MHD_gtls_cipher_suite_get_cipher_algo
00510                                      (&session->security_parameters.
00511                                       current_cipher_suite));
00512       if (rc < 0)
00513         return rc;
00514       rc = MHD_gtls_set_read_mac (session,
00515                                   MHD_gtls_cipher_suite_get_mac_algo
00516                                   (&session->security_parameters.
00517                                    current_cipher_suite));
00518       if (rc < 0)
00519         return rc;
00520 
00521       rc = MHD_gtls_set_kx (session,
00522                             MHD_gtls_cipher_suite_get_kx_algo
00523                             (&session->security_parameters.
00524                              current_cipher_suite));
00525       if (rc < 0)
00526         return rc;
00527 
00528       rc = MHD_gtls_set_read_compression (session,
00529                                           session->internals.
00530                                           compression_method);
00531       if (rc < 0)
00532         return rc;
00533     }
00534   else
00535     {                           /* RESUME_TRUE */
00536       MHD__gnutls_cpy_read_security_parameters (&session->security_parameters,
00537                                                 &session->internals.
00538                                                 resumed_security_parameters);
00539     }
00540 
00541 
00542   rc = MHD__gnutls_set_read_keys (session);
00543   if (rc < 0)
00544     return rc;
00545 
00546   MHD__gnutls_handshake_log ("HSK[%x]: Cipher Suite: %s\n",
00547                              session,
00548                              MHD_gtls_cipher_suite_get_name
00549                              (&session->security_parameters.
00550                               current_cipher_suite));
00551 
00552   if (MHD_gtls_compression_is_ok
00553       (session->security_parameters.read_compression_algorithm) != 0)
00554     {
00555       MHD_gnutls_assert ();
00556       return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM;
00557     }
00558 
00559   if (MHD_gnutls_mac_is_ok
00560       (session->security_parameters.read_mac_algorithm) != 0)
00561     {
00562       MHD_gnutls_assert ();
00563       return GNUTLS_E_INTERNAL_ERROR;
00564     }
00565 
00566   /* Free all the previous keys/ sessions etc.
00567    */
00568   if (session->connection_state.read_mac_secret.data != NULL)
00569     MHD__gnutls_free_datum (&session->connection_state.read_mac_secret);
00570 
00571   if (session->connection_state.read_cipher_state != NULL)
00572     MHD_gnutls_cipher_deinit (session->connection_state.read_cipher_state);
00573 
00574   mac_size =
00575     MHD_gnutls_hash_get_algo_len (session->security_parameters.
00576                                   read_mac_algorithm);
00577 
00578   MHD__gnutls_handshake_log
00579     ("HSK[%x]: Initializing internal [read] cipher sessions\n", session);
00580 
00581   switch (session->security_parameters.entity)
00582     {
00583     case GNUTLS_SERVER:
00584       /* initialize cipher session
00585        */
00586       session->connection_state.read_cipher_state =
00587         MHD_gtls_cipher_init (session->security_parameters.
00588                               read_bulk_cipher_algorithm,
00589                               &session->cipher_specs.client_write_key,
00590                               &session->cipher_specs.client_write_IV);
00591       if (session->connection_state.read_cipher_state == GNUTLS_CIPHER_FAILED
00592           && session->security_parameters.read_bulk_cipher_algorithm !=
00593           MHD_GNUTLS_CIPHER_NULL)
00594         {
00595           MHD_gnutls_assert ();
00596           return GNUTLS_E_INTERNAL_ERROR;
00597         }
00598 
00599       /* copy mac secrets from cipherspecs, to connection
00600        * session.
00601        */
00602       if (mac_size > 0)
00603         {
00604           if (MHD__gnutls_sset_datum
00605               (&session->connection_state.read_mac_secret,
00606                session->cipher_specs.client_write_mac_secret.data,
00607                session->cipher_specs.client_write_mac_secret.size) < 0)
00608             {
00609               MHD_gnutls_assert ();
00610               return GNUTLS_E_MEMORY_ERROR;
00611             }
00612 
00613         }
00614 
00615       break;
00616 #if MHD_DEBUG_TLS
00617     case GNUTLS_CLIENT:
00618       session->connection_state.read_cipher_state =
00619         MHD_gtls_cipher_init (session->security_parameters.
00620                               read_bulk_cipher_algorithm,
00621                               &session->cipher_specs.server_write_key,
00622                               &session->cipher_specs.server_write_IV);
00623 
00624       if (session->connection_state.read_cipher_state ==
00625           GNUTLS_CIPHER_FAILED
00626           && session->security_parameters.read_bulk_cipher_algorithm !=
00627           MHD_GNUTLS_CIPHER_NULL)
00628         {
00629           MHD_gnutls_assert ();
00630           return GNUTLS_E_INTERNAL_ERROR;
00631         }
00632 
00633 
00634       /* copy mac secret to connection session
00635        */
00636       if (mac_size > 0)
00637         {
00638           if (MHD__gnutls_sset_datum
00639               (&session->connection_state.read_mac_secret,
00640                session->cipher_specs.server_write_mac_secret.data,
00641                session->cipher_specs.server_write_mac_secret.size) < 0)
00642             {
00643               MHD_gnutls_assert ();
00644               return GNUTLS_E_MEMORY_ERROR;
00645             }
00646         }
00647 
00648       break;
00649 #endif
00650     default:                   /* this check is useless */
00651       MHD_gnutls_assert ();
00652       return GNUTLS_E_INTERNAL_ERROR;
00653     }
00654 
00655   return 0;
00656 }
00657 
00658 
00659 
00660 /* Initializes the write connection session
00661  * (write encrypted data)
00662  */
00663 int
00664 MHD_gtls_write_connection_state_init (MHD_gtls_session_t session)
00665 {
00666   int mac_size;
00667   int rc;
00668 
00669   MHD__gnutls_uint64zero (session->connection_state.write_sequence_number);
00670 
00671 /* Update internals from CipherSuite selected.
00672  * If we are resuming just copy the connection session
00673  */
00674   if (session->internals.resumed == RESUME_FALSE)
00675     {
00676       rc = MHD_gtls_set_write_cipher (session,
00677                                       MHD_gtls_cipher_suite_get_cipher_algo
00678                                       (&session->security_parameters.
00679                                        current_cipher_suite));
00680       if (rc < 0)
00681         return rc;
00682       rc = MHD_gtls_set_write_mac (session,
00683                                    MHD_gtls_cipher_suite_get_mac_algo
00684                                    (&session->security_parameters.
00685                                     current_cipher_suite));
00686       if (rc < 0)
00687         return rc;
00688 
00689       rc = MHD_gtls_set_kx (session,
00690                             MHD_gtls_cipher_suite_get_kx_algo
00691                             (&session->security_parameters.
00692                              current_cipher_suite));
00693       if (rc < 0)
00694         return rc;
00695 
00696       rc = MHD_gtls_set_write_compression (session,
00697                                            session->internals.
00698                                            compression_method);
00699       if (rc < 0)
00700         return rc;
00701     }
00702   else
00703     {                           /* RESUME_TRUE */
00704       MHD__gnutls_cpy_write_security_parameters
00705         (&session->security_parameters,
00706          &session->internals.resumed_security_parameters);
00707     }
00708 
00709   rc = MHD__gnutls_set_write_keys (session);
00710   if (rc < 0)
00711     return rc;
00712 
00713   MHD__gnutls_handshake_log ("HSK[%x]: Cipher Suite: %s\n", session,
00714                              MHD_gtls_cipher_suite_get_name
00715                              (&session->security_parameters.
00716                               current_cipher_suite));
00717 
00718   if (MHD_gtls_compression_is_ok
00719       (session->security_parameters.write_compression_algorithm) != 0)
00720     {
00721       MHD_gnutls_assert ();
00722       return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM;
00723     }
00724 
00725   if (MHD_gnutls_mac_is_ok
00726       (session->security_parameters.write_mac_algorithm) != 0)
00727     {
00728       MHD_gnutls_assert ();
00729       return GNUTLS_E_INTERNAL_ERROR;
00730     }
00731 
00732 
00733 
00734   /* Free all the previous keys/ sessions etc.
00735    */
00736   if (session->connection_state.write_mac_secret.data != NULL)
00737     MHD__gnutls_free_datum (&session->connection_state.write_mac_secret);
00738 
00739   if (session->connection_state.write_cipher_state != NULL)
00740     MHD_gnutls_cipher_deinit (session->connection_state.write_cipher_state);
00741 
00742   mac_size =
00743     MHD_gnutls_hash_get_algo_len (session->security_parameters.
00744                                   write_mac_algorithm);
00745 
00746   MHD__gnutls_handshake_log
00747     ("HSK[%x]: Initializing internal [write] cipher sessions\n", session);
00748 
00749   switch (session->security_parameters.entity)
00750     {
00751     case GNUTLS_SERVER:
00752       /* initialize cipher session
00753        */
00754       session->connection_state.write_cipher_state =
00755         MHD_gtls_cipher_init (session->security_parameters.
00756                               write_bulk_cipher_algorithm,
00757                               &session->cipher_specs.server_write_key,
00758                               &session->cipher_specs.server_write_IV);
00759 
00760       if (session->connection_state.write_cipher_state ==
00761           GNUTLS_CIPHER_FAILED
00762           && session->security_parameters.write_bulk_cipher_algorithm !=
00763           MHD_GNUTLS_CIPHER_NULL)
00764         {
00765           MHD_gnutls_assert ();
00766           return GNUTLS_E_INTERNAL_ERROR;
00767         }
00768 
00769 
00770       /* copy mac secrets from cipherspecs, to connection
00771        * session.
00772        */
00773       if (mac_size > 0)
00774         {
00775           if (MHD__gnutls_sset_datum
00776               (&session->connection_state.write_mac_secret,
00777                session->cipher_specs.server_write_mac_secret.data,
00778                session->cipher_specs.server_write_mac_secret.size) < 0)
00779             {
00780               MHD_gnutls_assert ();
00781               return GNUTLS_E_MEMORY_ERROR;
00782             }
00783 
00784         }
00785 
00786 
00787       break;
00788 #if MHD_DEBUG_TLS
00789     case GNUTLS_CLIENT:
00790       session->connection_state.write_cipher_state =
00791         MHD_gtls_cipher_init (session->security_parameters.
00792                               write_bulk_cipher_algorithm,
00793                               &session->cipher_specs.client_write_key,
00794                               &session->cipher_specs.client_write_IV);
00795 
00796       if (session->connection_state.write_cipher_state ==
00797           GNUTLS_CIPHER_FAILED
00798           && session->security_parameters.write_bulk_cipher_algorithm !=
00799           MHD_GNUTLS_CIPHER_NULL)
00800         {
00801           MHD_gnutls_assert ();
00802           return GNUTLS_E_INTERNAL_ERROR;
00803         }
00804 
00805       /* copy mac secret to connection session
00806        */
00807       if (mac_size > 0)
00808         {
00809           if (MHD__gnutls_sset_datum
00810               (&session->connection_state.write_mac_secret,
00811                session->cipher_specs.client_write_mac_secret.data,
00812                session->cipher_specs.client_write_mac_secret.size) < 0)
00813             {
00814               MHD_gnutls_assert ();
00815               return GNUTLS_E_MEMORY_ERROR;
00816             }
00817         }
00818 
00819       break;
00820 #endif
00821     default:
00822       MHD_gnutls_assert ();
00823       return GNUTLS_E_INTERNAL_ERROR;
00824     }
00825 
00826 
00827   return 0;
00828 }
00829 
00830 /* Sets the specified cipher into the pending session
00831  */
00832 int
00833 MHD_gtls_set_read_cipher (MHD_gtls_session_t session,
00834                           enum MHD_GNUTLS_CipherAlgorithm algo)
00835 {
00836 
00837   if (MHD_gtls_cipher_is_ok (algo) == 0)
00838     {
00839       if (MHD_gtls_cipher_priority (session, algo) < 0)
00840         {
00841           MHD_gnutls_assert ();
00842           return GNUTLS_E_UNWANTED_ALGORITHM;
00843         }
00844 
00845       session->security_parameters.read_bulk_cipher_algorithm = algo;
00846 
00847     }
00848   else
00849     {
00850       MHD_gnutls_assert ();
00851       return GNUTLS_E_INTERNAL_ERROR;
00852     }
00853 
00854   return 0;
00855 
00856 }
00857 
00858 int
00859 MHD_gtls_set_write_cipher (MHD_gtls_session_t session,
00860                            enum MHD_GNUTLS_CipherAlgorithm algo)
00861 {
00862 
00863   if (MHD_gtls_cipher_is_ok (algo) == 0)
00864     {
00865       if (MHD_gtls_cipher_priority (session, algo) < 0)
00866         {
00867           MHD_gnutls_assert ();
00868           return GNUTLS_E_UNWANTED_ALGORITHM;
00869         }
00870 
00871       session->security_parameters.write_bulk_cipher_algorithm = algo;
00872 
00873     }
00874   else
00875     {
00876       MHD_gnutls_assert ();
00877       return GNUTLS_E_INTERNAL_ERROR;
00878     }
00879 
00880   return 0;
00881 
00882 }
00883 
00884 
00885 /* Sets the specified algorithm into pending compression session
00886  */
00887 int
00888 MHD_gtls_set_read_compression (MHD_gtls_session_t session,
00889                                enum MHD_GNUTLS_CompressionMethod algo)
00890 {
00891 
00892   if (MHD_gtls_compression_is_ok (algo) == 0)
00893     {
00894       session->security_parameters.read_compression_algorithm = algo;
00895     }
00896   else
00897     {
00898       MHD_gnutls_assert ();
00899       return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM;
00900     }
00901   return 0;
00902 
00903 }
00904 
00905 int
00906 MHD_gtls_set_write_compression (MHD_gtls_session_t session,
00907                                 enum MHD_GNUTLS_CompressionMethod algo)
00908 {
00909 
00910   if (MHD_gtls_compression_is_ok (algo) == 0)
00911     {
00912       session->security_parameters.write_compression_algorithm = algo;
00913     }
00914   else
00915     {
00916       MHD_gnutls_assert ();
00917       return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM;
00918     }
00919   return 0;
00920 
00921 }
00922 
00923 /* Sets the specified kx algorithm into pending session
00924  */
00925 int
00926 MHD_gtls_set_kx (MHD_gtls_session_t session,
00927                  enum MHD_GNUTLS_KeyExchangeAlgorithm algo)
00928 {
00929 
00930   if (MHD_gtls_kx_is_ok (algo) == 0)
00931     {
00932       session->security_parameters.kx_algorithm = algo;
00933     }
00934   else
00935     {
00936       MHD_gnutls_assert ();
00937       return GNUTLS_E_INTERNAL_ERROR;
00938     }
00939   if (MHD_gtls_kx_priority (session, algo) < 0)
00940     {
00941       MHD_gnutls_assert ();
00942       /* we shouldn't get here */
00943       return GNUTLS_E_UNWANTED_ALGORITHM;
00944     }
00945 
00946   return 0;
00947 
00948 }
00949 
00950 /* Sets the specified mac algorithm into pending session */
00951 int
00952 MHD_gtls_set_read_mac (MHD_gtls_session_t session,
00953                        enum MHD_GNUTLS_HashAlgorithm algo)
00954 {
00955 
00956   if (MHD_gnutls_mac_is_ok (algo) == 0)
00957     {
00958       session->security_parameters.read_mac_algorithm = algo;
00959     }
00960   else
00961     {
00962       MHD_gnutls_assert ();
00963       return GNUTLS_E_INTERNAL_ERROR;
00964     }
00965   if (MHD_gtls_mac_priority (session, algo) < 0)
00966     {
00967       MHD_gnutls_assert ();
00968       return GNUTLS_E_UNWANTED_ALGORITHM;
00969     }
00970 
00971 
00972   return 0;
00973 
00974 }
00975 
00976 int
00977 MHD_gtls_set_write_mac (MHD_gtls_session_t session,
00978                         enum MHD_GNUTLS_HashAlgorithm algo)
00979 {
00980 
00981   if (MHD_gnutls_mac_is_ok (algo) == 0)
00982     {
00983       session->security_parameters.write_mac_algorithm = algo;
00984     }
00985   else
00986     {
00987       MHD_gnutls_assert ();
00988       return GNUTLS_E_INTERNAL_ERROR;
00989     }
00990   if (MHD_gtls_mac_priority (session, algo) < 0)
00991     {
00992       MHD_gnutls_assert ();
00993       return GNUTLS_E_UNWANTED_ALGORITHM;
00994     }
00995 
00996 
00997   return 0;
00998 
00999 }

Generated on Fri Feb 27 18:31:58 2009 for GNU libmicrohttpd by  doxygen 1.5.7.1