gnutls_handshake.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 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 relate to the TLS handshake procedure.
00026  */
00027 
00028 #include "MHD_config.h"
00029 #include "gnutls_int.h"
00030 #include "gnutls_errors.h"
00031 #include "gnutls_dh.h"
00032 #include "debug.h"
00033 #include "gnutls_algorithms.h"
00034 #include "gnutls_cipher.h"
00035 #include "gnutls_buffers.h"
00036 #include "gnutls_kx.h"
00037 #include "gnutls_handshake.h"
00038 #include "gnutls_num.h"
00039 #include "gnutls_hash_int.h"
00040 #include "gnutls_extensions.h"
00041 #include "gnutls_supplemental.h"
00042 #include "gnutls_auth_int.h"
00043 #include "auth_cert.h"
00044 #include "gnutls_cert.h"
00045 #include "gnutls_constate.h"
00046 #include "gnutls_record.h"
00047 #include "gnutls_state.h"
00048 #include "gnutls_rsa_export.h"  /* for MHD_gnutls_get_rsa_params() */
00049 #include "gc.h"
00050 
00051 #ifdef HANDSHAKE_DEBUG
00052 #define ERR(x, y) MHD__gnutls_handshake_log( "HSK[%x]: %s (%d)\n", session, x,y)
00053 #else
00054 #define ERR(x, y)
00055 #endif
00056 
00057 #define TRUE 1
00058 #define FALSE 0
00059 
00060 
00061 /* This should be sufficient by now. It should hold all the extensions
00062  * plus the headers in a hello message.
00063  */
00064 #define MAX_EXT_DATA_LENGTH 1024
00065 
00066 
00067 static int MHD_gtls_remove_unwanted_ciphersuites (MHD_gtls_session_t session,
00068                                                   cipher_suite_st **
00069                                                   cipherSuites,
00070                                                   int numCipherSuites,
00071                                                   enum
00072                                                   MHD_GNUTLS_PublicKeyAlgorithm);
00073 static int MHD_gtls_server_select_suite (MHD_gtls_session_t session,
00074                                          opaque * data, int datalen);
00075 
00076 static int MHD_gtls_generate_session_id (opaque * session_id, uint8_t * len);
00077 
00078 static int MHD_gtls_handshake_common (MHD_gtls_session_t session);
00079 
00080 static int MHD_gtls_handshake_server (MHD_gtls_session_t session);
00081 
00082 #if MHD_DEBUG_TLS
00083 static int MHD_gtls_handshake_client (MHD_gtls_session_t session);
00084 #endif
00085 
00086 
00087 static int MHD__gnutls_server_select_comp_method (MHD_gtls_session_t session,
00088                                                   opaque * data, int datalen);
00089 
00090 
00091 /* Clears the handshake hash buffers and handles.
00092  */
00093 static void
00094 MHD__gnutls_handshake_hash_buffers_clear (MHD_gtls_session_t session)
00095 {
00096   MHD_gnutls_hash_deinit (session->internals.handshake_mac_handle_md5, NULL);
00097   MHD_gnutls_hash_deinit (session->internals.handshake_mac_handle_sha, NULL);
00098   session->internals.handshake_mac_handle_md5 = NULL;
00099   session->internals.handshake_mac_handle_sha = NULL;
00100   MHD_gtls_handshake_buffer_clear (session);
00101 }
00102 
00114 void
00115 MHD__gnutls_handshake_set_max_packet_length (MHD_gtls_session_t session,
00116                                              size_t max)
00117 {
00118   session->internals.max_handshake_data_buffer_size = max;
00119 }
00120 
00121 
00122 static void
00123 MHD_gtls_set_server_random (MHD_gtls_session_t session, uint8_t * rnd)
00124 {
00125   memcpy (session->security_parameters.server_random, rnd, TLS_RANDOM_SIZE);
00126 }
00127 
00128 static void
00129 MHD_gtls_set_client_random (MHD_gtls_session_t session, uint8_t * rnd)
00130 {
00131   memcpy (session->security_parameters.client_random, rnd, TLS_RANDOM_SIZE);
00132 }
00133 
00134 /* Calculate The SSL3 Finished message */
00135 #define SSL3_CLIENT_MSG "CLNT"
00136 #define SSL3_SERVER_MSG "SRVR"
00137 #define SSL_MSG_LEN 4
00138 static int
00139 MHD__gnutls_ssl3_finished (MHD_gtls_session_t session, int type, opaque * ret)
00140 {
00141   const int siz = SSL_MSG_LEN;
00142   mac_hd_t td_md5;
00143   mac_hd_t td_sha;
00144   const char *mesg;
00145 
00146   td_md5 = MHD_gnutls_hash_copy (session->internals.handshake_mac_handle_md5);
00147   if (td_md5 == NULL)
00148     {
00149       MHD_gnutls_assert ();
00150       return GNUTLS_E_HASH_FAILED;
00151     }
00152 
00153   td_sha = MHD_gnutls_hash_copy (session->internals.handshake_mac_handle_sha);
00154   if (td_sha == NULL)
00155     {
00156       MHD_gnutls_assert ();
00157       MHD_gnutls_hash_deinit (td_md5, NULL);
00158       return GNUTLS_E_HASH_FAILED;
00159     }
00160 
00161   if (type == GNUTLS_SERVER)
00162     {
00163       mesg = SSL3_SERVER_MSG;
00164     }
00165   else
00166     {
00167       mesg = SSL3_CLIENT_MSG;
00168     }
00169 
00170   MHD_gnutls_hash (td_md5, mesg, siz);
00171   MHD_gnutls_hash (td_sha, mesg, siz);
00172 
00173   MHD_gnutls_mac_deinit_ssl3_handshake (td_md5, ret,
00174                                         session->security_parameters.
00175                                         master_secret, TLS_MASTER_SIZE);
00176   MHD_gnutls_mac_deinit_ssl3_handshake (td_sha, &ret[16],
00177                                         session->security_parameters.
00178                                         master_secret, TLS_MASTER_SIZE);
00179 
00180   return 0;
00181 }
00182 
00183 /* Hash the handshake messages as required by TLS 1.0 */
00184 #define SERVER_MSG "server finished"
00185 #define CLIENT_MSG "client finished"
00186 #define TLS_MSG_LEN 15
00187 static int
00188 MHD__gnutls_finished (MHD_gtls_session_t session, int type, void *ret)
00189 {
00190   const int siz = TLS_MSG_LEN;
00191   opaque concat[36];
00192   size_t len;
00193   const char *mesg;
00194   mac_hd_t td_md5 = NULL;
00195   mac_hd_t td_sha;
00196   enum MHD_GNUTLS_Protocol ver = MHD__gnutls_protocol_get_version (session);
00197 
00198   if (ver < MHD_GNUTLS_PROTOCOL_TLS1_2)
00199     {
00200       td_md5 =
00201         MHD_gnutls_hash_copy (session->internals.handshake_mac_handle_md5);
00202       if (td_md5 == NULL)
00203         {
00204           MHD_gnutls_assert ();
00205           return GNUTLS_E_HASH_FAILED;
00206         }
00207     }
00208 
00209   td_sha = MHD_gnutls_hash_copy (session->internals.handshake_mac_handle_sha);
00210   if (td_sha == NULL)
00211     {
00212       MHD_gnutls_assert ();
00213       if (td_md5 != NULL)
00214         MHD_gnutls_hash_deinit (td_md5, NULL);
00215       return GNUTLS_E_HASH_FAILED;
00216     }
00217 
00218   if (ver < MHD_GNUTLS_PROTOCOL_TLS1_2)
00219     {
00220       MHD_gnutls_hash_deinit (td_md5, concat);
00221       MHD_gnutls_hash_deinit (td_sha, &concat[16]);
00222       len = 20 + 16;
00223     }
00224   else
00225     {
00226       MHD_gnutls_hash_deinit (td_sha, concat);
00227       len = 20;
00228     }
00229 
00230   if (type == GNUTLS_SERVER)
00231     {
00232       mesg = SERVER_MSG;
00233     }
00234   else
00235     {
00236       mesg = CLIENT_MSG;
00237     }
00238 
00239   return MHD_gtls_PRF (session, session->security_parameters.master_secret,
00240                        TLS_MASTER_SIZE, mesg, siz, concat, len, 12, ret);
00241 }
00242 
00243 /* this function will produce TLS_RANDOM_SIZE==32 bytes of random data
00244  * and put it to dst.
00245  */
00246 static int
00247 MHD_gtls_tls_create_random (opaque * dst)
00248 {
00249   uint32_t tim;
00250 
00251   /* Use weak random numbers for the most of the
00252    * buffer except for the first 4 that are the
00253    * system's time.
00254    */
00255 
00256   tim = time (NULL);
00257   /* generate server random value */
00258   MHD_gtls_write_uint32 (tim, dst);
00259 
00260   if (MHD_gc_nonce ((char *) &dst[4], TLS_RANDOM_SIZE - 4) != GC_OK)
00261     {
00262       MHD_gnutls_assert ();
00263       return GNUTLS_E_RANDOM_FAILED;
00264     }
00265 
00266   return 0;
00267 }
00268 
00269 /* returns the 0 on success or a negative value.
00270  */
00271 static int
00272 MHD_gtls_negotiate_version (MHD_gtls_session_t session,
00273                             enum MHD_GNUTLS_Protocol adv_version)
00274 {
00275   int ret;
00276 
00277   /* if we do not support that version  */
00278   if (MHD_gtls_version_is_supported (session, adv_version) == 0)
00279     {
00280       /* If he requested something we do not support
00281        * then we send him the highest we support.
00282        */
00283       ret = MHD_gtls_version_max (session);
00284     }
00285   else
00286     {
00287       ret = adv_version;
00288     }
00289   MHD_gtls_set_current_version (session, ret);
00290 
00291   return ret;
00292 }
00293 
00294 /* Read a client hello packet.
00295  * A client hello must be a known version client hello
00296  * or version 2.0 client hello (only for compatibility
00297  * since SSL version 2.0 is not supported).
00298  */
00299 static int
00300 MHD__gnutls_read_client_hello (MHD_gtls_session_t session, opaque * data,
00301                                int datalen)
00302 {
00303   uint8_t session_id_len;
00304   int pos = 0, ret = 0;
00305   uint16_t suite_size, comp_size;
00306   enum MHD_GNUTLS_Protocol adv_version;
00307   int neg_version;
00308   int len = datalen;
00309   opaque rnd[TLS_RANDOM_SIZE], *suite_ptr, *comp_ptr;
00310 
00311   DECR_LEN (len, 2);
00312 
00313   MHD__gnutls_handshake_log ("HSK[%x]: Client's version: %d.%d\n", session,
00314                              data[pos], data[pos + 1]);
00315 
00316   adv_version = MHD_gtls_version_get (data[pos], data[pos + 1]);
00317   set_adv_version (session, data[pos], data[pos + 1]);
00318   pos += 2;
00319 
00320   neg_version = MHD_gtls_negotiate_version (session, adv_version);
00321   if (neg_version < 0)
00322     {
00323       MHD_gnutls_assert ();
00324       return ret;
00325     }
00326 
00327   /* Read client random value.
00328    */
00329   DECR_LEN (len, TLS_RANDOM_SIZE);
00330   MHD_gtls_set_client_random (session, &data[pos]);
00331   pos += TLS_RANDOM_SIZE;
00332 
00333   MHD_gtls_tls_create_random (rnd);
00334   MHD_gtls_set_server_random (session, rnd);
00335 
00336   session->security_parameters.timestamp = time (NULL);
00337 
00338   DECR_LEN (len, 1);
00339   session_id_len = data[pos++];
00340 
00341   /* RESUME SESSION */
00342   if (session_id_len > TLS_MAX_SESSION_ID_SIZE)
00343     {
00344       MHD_gnutls_assert ();
00345       return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
00346     }
00347   DECR_LEN (len, session_id_len);
00348 
00349   pos += session_id_len;
00350 
00351   MHD_gtls_generate_session_id (session->security_parameters.session_id,
00352                                 &session->security_parameters.
00353                                 session_id_size);
00354 
00355   session->internals.resumed = RESUME_FALSE;
00356   /* Remember ciphersuites for later
00357    */
00358   DECR_LEN (len, 2);
00359   suite_size = MHD_gtls_read_uint16 (&data[pos]);
00360   pos += 2;
00361 
00362   DECR_LEN (len, suite_size);
00363   suite_ptr = &data[pos];
00364   pos += suite_size;
00365 
00366   /* Point to the compression methods
00367    */
00368   DECR_LEN (len, 1);
00369   comp_size = data[pos++];      /* z is the number of compression methods */
00370 
00371   DECR_LEN (len, comp_size);
00372   comp_ptr = &data[pos];
00373   pos += comp_size;
00374 
00375   /* Parse the extensions (if any)
00376    */
00377   if (neg_version >= MHD_GNUTLS_PROTOCOL_TLS1_0)
00378     {
00379       ret = MHD_gtls_parse_extensions (session, EXTENSION_APPLICATION, &data[pos], len);        /* len is the rest of the parsed length */
00380       if (ret < 0)
00381         {
00382           MHD_gnutls_assert ();
00383           return ret;
00384         }
00385     }
00386 
00387   if (neg_version >= MHD_GNUTLS_PROTOCOL_TLS1_0)
00388     {
00389       ret = MHD_gtls_parse_extensions (session, EXTENSION_TLS, &data[pos], len);        /* len is the rest of the parsed length */
00390       if (ret < 0)
00391         {
00392           MHD_gnutls_assert ();
00393           return ret;
00394         }
00395     }
00396 
00397   /* select an appropriate cipher suite
00398    */
00399   ret = MHD_gtls_server_select_suite (session, suite_ptr, suite_size);
00400   if (ret < 0)
00401     {
00402       MHD_gnutls_assert ();
00403       return ret;
00404     }
00405 
00406   /* select appropriate compression method */
00407   ret = MHD__gnutls_server_select_comp_method (session, comp_ptr, comp_size);
00408   if (ret < 0)
00409     {
00410       MHD_gnutls_assert ();
00411       return ret;
00412     }
00413 
00414   return 0;
00415 }
00416 
00417 /* here we hash all pending data.
00418  */
00419 static int
00420 MHD__gnutls_handshake_hash_pending (MHD_gtls_session_t session)
00421 {
00422   size_t siz;
00423   int ret;
00424   opaque *data;
00425 
00426   if (session->internals.handshake_mac_handle_sha == NULL ||
00427       session->internals.handshake_mac_handle_md5 == NULL)
00428     {
00429       MHD_gnutls_assert ();
00430       return GNUTLS_E_INTERNAL_ERROR;
00431     }
00432 
00433   /* We check if there are pending data to hash.
00434    */
00435   if ((ret = MHD_gtls_handshake_buffer_get_ptr (session, &data, &siz)) < 0)
00436     {
00437       MHD_gnutls_assert ();
00438       return ret;
00439     }
00440 
00441   if (siz > 0)
00442     {
00443       MHD_gnutls_hash (session->internals.handshake_mac_handle_sha, data,
00444                        siz);
00445       MHD_gnutls_hash (session->internals.handshake_mac_handle_md5, data,
00446                        siz);
00447     }
00448 
00449   MHD_gtls_handshake_buffer_empty (session);
00450 
00451   return 0;
00452 }
00453 
00454 
00455 /* This is to be called after sending CHANGE CIPHER SPEC packet
00456  * and initializing encryption. This is the first encrypted message
00457  * we send.
00458  */
00459 static int
00460 MHD__gnutls_send_finished (MHD_gtls_session_t session, int again)
00461 {
00462   uint8_t data[36];
00463   int ret;
00464   int data_size = 0;
00465 
00466 
00467   if (again == 0)
00468     {
00469 
00470       /* This is needed in order to hash all the required
00471        * messages.
00472        */
00473       if ((ret = MHD__gnutls_handshake_hash_pending (session)) < 0)
00474         {
00475           MHD_gnutls_assert ();
00476           return ret;
00477         }
00478 
00479       if (MHD__gnutls_protocol_get_version (session) ==
00480           MHD_GNUTLS_PROTOCOL_SSL3)
00481         {
00482           ret =
00483             MHD__gnutls_ssl3_finished (session,
00484                                        session->security_parameters.entity,
00485                                        data);
00486           data_size = 36;
00487         }
00488       else
00489         {                       /* TLS 1.0 */
00490           ret =
00491             MHD__gnutls_finished (session,
00492                                   session->security_parameters.entity, data);
00493           data_size = 12;
00494         }
00495 
00496       if (ret < 0)
00497         {
00498           MHD_gnutls_assert ();
00499           return ret;
00500         }
00501 
00502     }
00503 
00504   ret =
00505     MHD_gtls_send_handshake (session, data, data_size,
00506                              GNUTLS_HANDSHAKE_FINISHED);
00507 
00508   return ret;
00509 }
00510 
00511 /* This is to be called after sending our finished message. If everything
00512  * went fine we have negotiated a secure connection
00513  */
00514 static int
00515 MHD__gnutls_recv_finished (MHD_gtls_session_t session)
00516 {
00517   uint8_t data[36], *vrfy;
00518   int data_size;
00519   int ret;
00520   int vrfysize;
00521 
00522   ret =
00523     MHD_gtls_recv_handshake (session, &vrfy, &vrfysize,
00524                              GNUTLS_HANDSHAKE_FINISHED, MANDATORY_PACKET);
00525   if (ret < 0)
00526     {
00527       ERR ("recv finished int", ret);
00528       MHD_gnutls_assert ();
00529       return ret;
00530     }
00531 
00532 
00533   if (MHD__gnutls_protocol_get_version (session) == MHD_GNUTLS_PROTOCOL_SSL3)
00534     {
00535       data_size = 36;
00536     }
00537   else
00538     {
00539       data_size = 12;
00540     }
00541 
00542   if (vrfysize != data_size)
00543     {
00544       MHD_gnutls_assert ();
00545       MHD_gnutls_free (vrfy);
00546       return GNUTLS_E_ERROR_IN_FINISHED_PACKET;
00547     }
00548 
00549   if (MHD__gnutls_protocol_get_version (session) == MHD_GNUTLS_PROTOCOL_SSL3)
00550     {
00551       ret =
00552         MHD__gnutls_ssl3_finished (session,
00553                                    (session->security_parameters.entity +
00554                                     1) % 2, data);
00555     }
00556   else
00557     {                           /* TLS 1.0 */
00558       ret =
00559         MHD__gnutls_finished (session,
00560                               (session->security_parameters.entity +
00561                                1) % 2, data);
00562     }
00563 
00564   if (ret < 0)
00565     {
00566       MHD_gnutls_assert ();
00567       MHD_gnutls_free (vrfy);
00568       return ret;
00569     }
00570 
00571   if (memcmp (vrfy, data, data_size) != 0)
00572     {
00573       MHD_gnutls_assert ();
00574       ret = GNUTLS_E_ERROR_IN_FINISHED_PACKET;
00575     }
00576   MHD_gnutls_free (vrfy);
00577 
00578   return ret;
00579 }
00580 
00581 /* returns PK_RSA if the given cipher suite list only supports,
00582  * RSA algorithms, PK_DSA if DSS, and PK_ANY for both or PK_NONE for none.
00583  */
00584 static int
00585 MHD__gnutls_server_find_pk_algos_in_ciphersuites (const opaque *
00586                                                   data, int datalen)
00587 {
00588   int j;
00589   enum MHD_GNUTLS_PublicKeyAlgorithm algo = GNUTLS_PK_NONE, prev_algo = 0;
00590   enum MHD_GNUTLS_KeyExchangeAlgorithm kx;
00591   cipher_suite_st cs;
00592 
00593   if (datalen % 2 != 0)
00594     {
00595       MHD_gnutls_assert ();
00596       return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
00597     }
00598 
00599   for (j = 0; j < datalen; j += 2)
00600     {
00601       memcpy (&cs.suite, &data[j], 2);
00602       kx = MHD_gtls_cipher_suite_get_kx_algo (&cs);
00603 
00604       if (MHD_gtls_map_kx_get_cred (kx, 1) == MHD_GNUTLS_CRD_CERTIFICATE)
00605         {
00606           algo = MHD_gtls_map_pk_get_pk (kx);
00607 
00608           if (algo != prev_algo && prev_algo != 0)
00609             return GNUTLS_PK_ANY;
00610           prev_algo = algo;
00611         }
00612     }
00613 
00614   return algo;
00615 }
00616 
00617 
00618 /* This selects the best supported ciphersuite from the given ones. Then
00619  * it adds the suite to the session and performs some checks.
00620  */
00621 static int
00622 MHD_gtls_server_select_suite (MHD_gtls_session_t session, opaque * data,
00623                               int datalen)
00624 {
00625   int x, i, j;
00626   cipher_suite_st *ciphers, cs;
00627   int retval, err;
00628   enum MHD_GNUTLS_PublicKeyAlgorithm pk_algo;   /* will hold the pk algorithms
00629                                                  * supported by the peer.
00630                                                  */
00631 
00632   pk_algo = MHD__gnutls_server_find_pk_algos_in_ciphersuites (data, datalen);
00633 
00634   x = MHD_gtls_supported_ciphersuites (session, &ciphers);
00635   if (x < 0)
00636     {                           /* the case x==0 is handled within the function. */
00637       MHD_gnutls_assert ();
00638       return x;
00639     }
00640 
00641   /* Here we remove any ciphersuite that does not conform
00642    * the certificate requested, or to the
00643    * authentication requested (e.g. SRP).
00644    */
00645   x = MHD_gtls_remove_unwanted_ciphersuites (session, &ciphers, x, pk_algo);
00646   if (x <= 0)
00647     {
00648       MHD_gnutls_assert ();
00649       MHD_gnutls_free (ciphers);
00650       if (x < 0)
00651         return x;
00652       else
00653         return GNUTLS_E_UNKNOWN_CIPHER_SUITE;
00654     }
00655 
00656   /* Data length should be zero mod 2 since
00657    * every ciphersuite is 2 bytes. (this check is needed
00658    * see below).
00659    */
00660   if (datalen % 2 != 0)
00661     {
00662       MHD_gnutls_assert ();
00663       return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
00664     }
00665   memset (session->security_parameters.current_cipher_suite.suite, '\0', 2);
00666 
00667   retval = GNUTLS_E_UNKNOWN_CIPHER_SUITE;
00668 
00669   for (j = 0; j < datalen; j += 2)
00670     {
00671       for (i = 0; i < x; i++)
00672         {
00673           if (memcmp (ciphers[i].suite, &data[j], 2) == 0)
00674             {
00675               memcpy (&cs.suite, &data[j], 2);
00676 
00677               MHD__gnutls_handshake_log
00678                 ("HSK[%x]: Selected cipher suite: %s\n", session,
00679                  MHD_gtls_cipher_suite_get_name (&cs));
00680               memcpy (session->security_parameters.current_cipher_suite.suite,
00681                       ciphers[i].suite, 2);
00682               retval = 0;
00683               goto finish;
00684             }
00685         }
00686     }
00687 
00688 finish:
00689   MHD_gnutls_free (ciphers);
00690 
00691   if (retval != 0)
00692     {
00693       MHD_gnutls_assert ();
00694       return retval;
00695     }
00696 
00697   /* check if the credentials (username, public key etc.) are ok
00698    */
00699   if (MHD_gtls_get_kx_cred
00700       (session,
00701        MHD_gtls_cipher_suite_get_kx_algo (&session->security_parameters.
00702                                           current_cipher_suite), &err) == NULL
00703       && err != 0)
00704     {
00705       MHD_gnutls_assert ();
00706       return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
00707     }
00708 
00709 
00710   /* set the MHD_gtls_mod_auth_st to the appropriate struct
00711    * according to the KX algorithm. This is needed since all the
00712    * handshake functions are read from there;
00713    */
00714   session->internals.auth_struct =
00715     MHD_gtls_kx_auth_struct (MHD_gtls_cipher_suite_get_kx_algo
00716                              (&session->security_parameters.
00717                               current_cipher_suite));
00718   if (session->internals.auth_struct == NULL)
00719     {
00720 
00721       MHD__gnutls_handshake_log
00722         ("HSK[%x]: Cannot find the appropriate handler for the KX algorithm\n",
00723          session);
00724       MHD_gnutls_assert ();
00725       return GNUTLS_E_INTERNAL_ERROR;
00726     }
00727 
00728   return 0;
00729 
00730 }
00731 
00732 
00733 /* This selects the best supported compression method from the ones provided
00734  */
00735 static int
00736 MHD__gnutls_server_select_comp_method (MHD_gtls_session_t session,
00737                                        opaque * data, int datalen)
00738 {
00739   int x, i, j;
00740   uint8_t *comps;
00741 
00742   x = MHD_gtls_supported_compression_methods (session, &comps);
00743   if (x < 0)
00744     {
00745       MHD_gnutls_assert ();
00746       return x;
00747     }
00748 
00749   memset (&session->internals.compression_method, 0,
00750           sizeof (enum MHD_GNUTLS_CompressionMethod));
00751 
00752   for (j = 0; j < datalen; j++)
00753     {
00754       for (i = 0; i < x; i++)
00755         {
00756           if (comps[i] == data[j])
00757             {
00758               enum MHD_GNUTLS_CompressionMethod method =
00759                 MHD_gtls_compression_get_id_from_int (comps[i]);
00760 
00761               session->internals.compression_method = method;
00762               MHD_gnutls_free (comps);
00763               return 0;
00764             }
00765         }
00766     }
00767 
00768   /* we were not able to find a compatible compression
00769    * algorithm
00770    */
00771   MHD_gnutls_free (comps);
00772   MHD_gnutls_assert ();
00773   return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM;
00774 
00775 }
00776 
00777 /* This function sends an empty handshake packet. (like hello request).
00778  * If the previous MHD__gnutls_send_empty_handshake() returned
00779  * GNUTLS_E_AGAIN or GNUTLS_E_INTERRUPTED, then it must be called again
00780  * (until it returns ok), with NULL parameters.
00781  */
00782 static int
00783 MHD__gnutls_send_empty_handshake (MHD_gtls_session_t session,
00784                                   MHD_gnutls_handshake_description_t type,
00785                                   int again)
00786 {
00787   opaque data = 0;
00788   opaque *ptr;
00789 
00790   if (again == 0)
00791     ptr = &data;
00792   else
00793     ptr = NULL;
00794 
00795   return MHD_gtls_send_handshake (session, ptr, 0, type);
00796 }
00797 
00798 
00799 /* This function will hash the handshake message we sent. */
00800 static int
00801 MHD__gnutls_handshake_hash_add_sent (MHD_gtls_session_t session,
00802                                      MHD_gnutls_handshake_description_t type,
00803                                      opaque * dataptr, uint32_t datalen)
00804 {
00805   int ret;
00806 
00807   if ((ret = MHD__gnutls_handshake_hash_pending (session)) < 0)
00808     {
00809       MHD_gnutls_assert ();
00810       return ret;
00811     }
00812 
00813   if (type != GNUTLS_HANDSHAKE_HELLO_REQUEST)
00814     {
00815       MHD_gnutls_hash (session->internals.handshake_mac_handle_sha, dataptr,
00816                        datalen);
00817       MHD_gnutls_hash (session->internals.handshake_mac_handle_md5, dataptr,
00818                        datalen);
00819     }
00820 
00821   return 0;
00822 }
00823 
00824 
00825 /* This function sends a handshake message of type 'type' containing the
00826  * data specified here. If the previous MHD_gtls_send_handshake() returned
00827  * GNUTLS_E_AGAIN or GNUTLS_E_INTERRUPTED, then it must be called again
00828  * (until it returns ok), with NULL parameters.
00829  */
00830 int
00831 MHD_gtls_send_handshake (MHD_gtls_session_t session, void *i_data,
00832                          uint32_t i_datasize,
00833                          MHD_gnutls_handshake_description_t type)
00834 {
00835   int ret;
00836   uint8_t *data;
00837   uint32_t datasize;
00838   int pos = 0;
00839 
00840   if (i_data == NULL && i_datasize == 0)
00841     {
00842       /* we are resuming a previously interrupted
00843        * send.
00844        */
00845       ret = MHD_gtls_handshake_io_write_flush (session);
00846       return ret;
00847 
00848     }
00849 
00850   if (i_data == NULL && i_datasize > 0)
00851     {
00852       MHD_gnutls_assert ();
00853       return GNUTLS_E_INVALID_REQUEST;
00854     }
00855 
00856   /* first run */
00857   datasize = i_datasize + HANDSHAKE_HEADER_SIZE;
00858   data = MHD_gnutls_alloca (datasize);
00859   if (data == NULL)
00860     {
00861       MHD_gnutls_assert ();
00862       return GNUTLS_E_MEMORY_ERROR;
00863     }
00864 
00865   data[pos++] = (uint8_t) type;
00866   MHD_gtls_write_uint24 (i_datasize, &data[pos]);
00867   pos += 3;
00868 
00869   if (i_datasize > 0)
00870     memcpy (&data[pos], i_data, i_datasize);
00871 
00872   /* Here we keep the handshake messages in order to hash them...
00873    */
00874   if (type != GNUTLS_HANDSHAKE_HELLO_REQUEST)
00875     if ((ret =
00876          MHD__gnutls_handshake_hash_add_sent (session, type, data,
00877                                               datasize)) < 0)
00878       {
00879         MHD_gnutls_assert ();
00880         MHD_gnutls_afree (data);
00881         return ret;
00882       }
00883 
00884   session->internals.last_handshake_out = type;
00885 
00886   ret =
00887     MHD_gtls_handshake_io_send_int (session, GNUTLS_HANDSHAKE, type,
00888                                     data, datasize);
00889 
00890   MHD__gnutls_handshake_log ("HSK[%x]: %s was sent [%ld bytes]\n",
00891                              session, MHD__gnutls_handshake2str (type),
00892                              (long) datasize);
00893 
00894   MHD_gnutls_afree (data);
00895 
00896   return ret;
00897 }
00898 
00899 /* This function will read the handshake header and return it to the caller. If the
00900  * received handshake packet is not the one expected then it buffers the header, and
00901  * returns UNEXPECTED_HANDSHAKE_PACKET.
00902  *
00903  * FIXME: This function is complex.
00904  */
00905 #define SSL2_HEADERS 1
00906 static int
00907 MHD__gnutls_recv_handshake_header (MHD_gtls_session_t session,
00908                                    MHD_gnutls_handshake_description_t type,
00909                                    MHD_gnutls_handshake_description_t *
00910                                    recv_type)
00911 {
00912   int ret;
00913   uint32_t length32 = 0;
00914   uint8_t *dataptr = NULL;      /* for realloc */
00915   size_t handshake_header_size = HANDSHAKE_HEADER_SIZE;
00916 
00917   /* if we have data into the buffer then return them, do not read the next packet.
00918    * In order to return we need a full TLS handshake header, or in case of a version 2
00919    * packet, then we return the first byte.
00920    */
00921   if (session->internals.handshake_header_buffer.header_size ==
00922       handshake_header_size || (session->internals.v2_hello != 0
00923                                 && type == GNUTLS_HANDSHAKE_CLIENT_HELLO
00924                                 && session->internals.
00925                                 handshake_header_buffer.packet_length > 0))
00926     {
00927 
00928       *recv_type = session->internals.handshake_header_buffer.recv_type;
00929 
00930       return session->internals.handshake_header_buffer.packet_length;
00931     }
00932 
00933   /* Note: SSL2_HEADERS == 1 */
00934 
00935   dataptr = session->internals.handshake_header_buffer.header;
00936 
00937   /* If we haven't already read the handshake headers.
00938    */
00939   if (session->internals.handshake_header_buffer.header_size < SSL2_HEADERS)
00940     {
00941       ret =
00942         MHD_gtls_handshake_io_recv_int (session, GNUTLS_HANDSHAKE,
00943                                         type, dataptr, SSL2_HEADERS);
00944 
00945       if (ret < 0)
00946         {
00947           MHD_gnutls_assert ();
00948           return ret;
00949         }
00950 
00951       /* The case ret==0 is caught here.
00952        */
00953       if (ret != SSL2_HEADERS)
00954         {
00955           MHD_gnutls_assert ();
00956           return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
00957         }
00958       session->internals.handshake_header_buffer.header_size = SSL2_HEADERS;
00959     }
00960 
00961   if (session->internals.v2_hello == 0
00962       || type != GNUTLS_HANDSHAKE_CLIENT_HELLO)
00963     {
00964       ret =
00965         MHD_gtls_handshake_io_recv_int (session, GNUTLS_HANDSHAKE,
00966                                         type,
00967                                         &dataptr
00968                                         [session->internals.
00969                                          handshake_header_buffer.header_size],
00970                                         HANDSHAKE_HEADER_SIZE -
00971                                         session->internals.
00972                                         handshake_header_buffer.header_size);
00973       if (ret <= 0)
00974         {
00975           MHD_gnutls_assert ();
00976           return (ret < 0) ? ret : GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
00977         }
00978       if ((size_t) ret !=
00979           HANDSHAKE_HEADER_SIZE -
00980           session->internals.handshake_header_buffer.header_size)
00981         {
00982           MHD_gnutls_assert ();
00983           return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
00984         }
00985       *recv_type = dataptr[0];
00986 
00987       /* we do not use DECR_LEN because we know
00988        * that the packet has enough data.
00989        */
00990       length32 = MHD_gtls_read_uint24 (&dataptr[1]);
00991       handshake_header_size = HANDSHAKE_HEADER_SIZE;
00992 
00993       MHD__gnutls_handshake_log ("HSK[%x]: %s was received [%ld bytes]\n",
00994                                  session,
00995                                  MHD__gnutls_handshake2str (dataptr[0]),
00996                                  length32 + HANDSHAKE_HEADER_SIZE);
00997 
00998     }
00999   else
01000     {                           /* v2 hello */
01001       length32 = session->internals.v2_hello - SSL2_HEADERS;    /* we've read the first byte */
01002 
01003       handshake_header_size = SSL2_HEADERS;     /* we've already read one byte */
01004 
01005       *recv_type = dataptr[0];
01006 
01007       MHD__gnutls_handshake_log ("HSK[%x]: %s(v2) was received [%ld bytes]\n",
01008                                  session,
01009                                  MHD__gnutls_handshake2str (*recv_type),
01010                                  length32 + handshake_header_size);
01011 
01012       if (*recv_type != GNUTLS_HANDSHAKE_CLIENT_HELLO)
01013         {                       /* it should be one or nothing */
01014           MHD_gnutls_assert ();
01015           return GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET;
01016         }
01017     }
01018 
01019   /* put the packet into the buffer */
01020   session->internals.handshake_header_buffer.header_size =
01021     handshake_header_size;
01022   session->internals.handshake_header_buffer.packet_length = length32;
01023   session->internals.handshake_header_buffer.recv_type = *recv_type;
01024 
01025   if (*recv_type != type)
01026     {
01027       MHD_gnutls_assert ();
01028       return GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET;
01029     }
01030 
01031   return length32;
01032 }
01033 
01034 #define MHD__gnutls_handshake_header_buffer_clear( session) session->internals.handshake_header_buffer.header_size = 0
01035 
01036 /* This function will hash the handshake headers and the
01037  * handshake data.
01038  */
01039 static int
01040 MHD__gnutls_handshake_hash_add_recvd (MHD_gtls_session_t session,
01041                                       MHD_gnutls_handshake_description_t
01042                                       recv_type, opaque * header,
01043                                       uint16_t header_size, opaque * dataptr,
01044                                       uint32_t datalen)
01045 {
01046   int ret;
01047 
01048   /* The idea here is to hash the previous message we received,
01049    * and add the one we just received into the handshake_hash_buffer.
01050    */
01051 
01052   if ((ret = MHD__gnutls_handshake_hash_pending (session)) < 0)
01053     {
01054       MHD_gnutls_assert ();
01055       return ret;
01056     }
01057 
01058   /* here we buffer the handshake messages - needed at Finished message */
01059   if (recv_type != GNUTLS_HANDSHAKE_HELLO_REQUEST)
01060     {
01061 
01062       if ((ret =
01063            MHD_gtls_handshake_buffer_put (session, header, header_size)) < 0)
01064         {
01065           MHD_gnutls_assert ();
01066           return ret;
01067         }
01068 
01069       if (datalen > 0)
01070         {
01071           if ((ret =
01072                MHD_gtls_handshake_buffer_put (session, dataptr, datalen)) < 0)
01073             {
01074               MHD_gnutls_assert ();
01075               return ret;
01076             }
01077         }
01078     }
01079 
01080   return 0;
01081 }
01082 
01083 /* This function will receive handshake messages of the given types,
01084  * and will pass the message to the right place in order to be processed.
01085  * E.g. for the SERVER_HELLO message (if it is expected), it will be
01086  * passed to MHD_gtls_recv_hello().
01087  */
01088 int
01089 MHD_gtls_recv_handshake (MHD_gtls_session_t session, uint8_t ** data,
01090                          int *datalen,
01091                          MHD_gnutls_handshake_description_t type,
01092                          Optional optional)
01093 {
01094   int ret;
01095   uint32_t length32 = 0;
01096   opaque *dataptr = NULL;
01097   MHD_gnutls_handshake_description_t recv_type;
01098 
01099   ret = MHD__gnutls_recv_handshake_header (session, type, &recv_type);
01100   if (ret < 0)
01101     {
01102 
01103       if (ret == GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET
01104           && optional == OPTIONAL_PACKET)
01105         {
01106           if (datalen != NULL)
01107             *datalen = 0;
01108           if (data != NULL)
01109             *data = NULL;
01110           return 0;             /* ok just ignore the packet */
01111         }
01112 
01113       return ret;
01114     }
01115 
01116   session->internals.last_handshake_in = recv_type;
01117 
01118   length32 = ret;
01119 
01120   if (length32 > 0)
01121     dataptr = MHD_gnutls_malloc (length32);
01122   else if (recv_type != GNUTLS_HANDSHAKE_SERVER_HELLO_DONE)
01123     {
01124       MHD_gnutls_assert ();
01125       return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
01126     }
01127 
01128   if (dataptr == NULL && length32 > 0)
01129     {
01130       MHD_gnutls_assert ();
01131       return GNUTLS_E_MEMORY_ERROR;
01132     }
01133 
01134   if (datalen != NULL)
01135     *datalen = length32;
01136 
01137   if (length32 > 0)
01138     {
01139       ret =
01140         MHD_gtls_handshake_io_recv_int (session, GNUTLS_HANDSHAKE,
01141                                         type, dataptr, length32);
01142       if (ret <= 0)
01143         {
01144           MHD_gnutls_assert ();
01145           MHD_gnutls_free (dataptr);
01146           return (ret == 0) ? GNUTLS_E_UNEXPECTED_PACKET_LENGTH : ret;
01147         }
01148     }
01149 
01150   if (data != NULL && length32 > 0)
01151     *data = dataptr;
01152 
01153 
01154   ret = MHD__gnutls_handshake_hash_add_recvd (session, recv_type,
01155                                               session->internals.
01156                                               handshake_header_buffer.header,
01157                                               session->internals.
01158                                               handshake_header_buffer.header_size,
01159                                               dataptr, length32);
01160   if (ret < 0)
01161     {
01162       MHD_gnutls_assert ();
01163       MHD__gnutls_handshake_header_buffer_clear (session);
01164       return ret;
01165     }
01166 
01167   /* If we fail before this then we will reuse the handshake header
01168    * have have received above. if we get here the we clear the handshake
01169    * header we received.
01170    */
01171   MHD__gnutls_handshake_header_buffer_clear (session);
01172 
01173   switch (recv_type)
01174     {
01175     case GNUTLS_HANDSHAKE_CLIENT_HELLO:
01176     case GNUTLS_HANDSHAKE_SERVER_HELLO:
01177       ret = MHD_gtls_recv_hello (session, dataptr, length32);
01178       /* dataptr is freed because the caller does not
01179        * need it */
01180       MHD_gnutls_free (dataptr);
01181       if (data != NULL)
01182         *data = NULL;
01183       break;
01184     case GNUTLS_HANDSHAKE_SERVER_HELLO_DONE:
01185       if (length32 == 0)
01186         ret = 0;
01187       else
01188         ret = GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
01189       break;
01190     case GNUTLS_HANDSHAKE_CERTIFICATE_PKT:
01191     case GNUTLS_HANDSHAKE_FINISHED:
01192     case GNUTLS_HANDSHAKE_SERVER_KEY_EXCHANGE:
01193     case GNUTLS_HANDSHAKE_CLIENT_KEY_EXCHANGE:
01194     case GNUTLS_HANDSHAKE_CERTIFICATE_REQUEST:
01195     case GNUTLS_HANDSHAKE_CERTIFICATE_VERIFY:
01196     case GNUTLS_HANDSHAKE_SUPPLEMENTAL:
01197       ret = length32;
01198       break;
01199     default:
01200       MHD_gnutls_assert ();
01201       MHD_gnutls_free (dataptr);
01202       if (data != NULL)
01203         *data = NULL;
01204       ret = GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET;
01205     }
01206 
01207   return ret;
01208 }
01209 
01210 #if MHD_DEBUG_TLS
01211 /* This function checks if the given cipher suite is supported, and sets it
01212  * to the session;
01213  */
01214 static int
01215 MHD__gnutls_client_set_ciphersuite (MHD_gtls_session_t session,
01216                                     opaque suite[2])
01217 {
01218   uint8_t z;
01219   cipher_suite_st *cipher_suites;
01220   int cipher_suite_num;
01221   int i, err;
01222 
01223   z = 1;
01224   cipher_suite_num =
01225     MHD_gtls_supported_ciphersuites (session, &cipher_suites);
01226   if (cipher_suite_num < 0)
01227     {
01228       MHD_gnutls_assert ();
01229       return cipher_suite_num;
01230     }
01231 
01232   for (i = 0; i < cipher_suite_num; i++)
01233     {
01234       if (memcmp (&cipher_suites[i], suite, 2) == 0)
01235         {
01236           z = 0;
01237           break;
01238         }
01239     }
01240 
01241   MHD_gnutls_free (cipher_suites);
01242 
01243   if (z != 0)
01244     {
01245       MHD_gnutls_assert ();
01246       return GNUTLS_E_UNKNOWN_CIPHER_SUITE;
01247     }
01248 
01249   memcpy (session->security_parameters.current_cipher_suite.suite, suite, 2);
01250 
01251   MHD__gnutls_handshake_log ("HSK[%x]: Selected cipher suite: %s\n", session,
01252                              MHD_gtls_cipher_suite_get_name
01253                              (&session->security_parameters.
01254                               current_cipher_suite));
01255 
01256 
01257   /* check if the credentials (username, public key etc.) are ok.
01258    * Actually checks if they exist.
01259    */
01260   if (MHD_gtls_get_kx_cred
01261       (session,
01262        MHD_gtls_cipher_suite_get_kx_algo
01263        (&session->security_parameters.current_cipher_suite), &err) == NULL
01264       && err != 0)
01265     {
01266       MHD_gnutls_assert ();
01267       return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
01268     }
01269 
01270 
01271   /* set the MHD_gtls_mod_auth_st to the appropriate struct
01272    * according to the KX algorithm. This is needed since all the
01273    * handshake functions are read from there;
01274    */
01275   session->internals.auth_struct =
01276     MHD_gtls_kx_auth_struct (MHD_gtls_cipher_suite_get_kx_algo
01277                              (&session->security_parameters.
01278                               current_cipher_suite));
01279 
01280   if (session->internals.auth_struct == NULL)
01281     {
01282 
01283       MHD__gnutls_handshake_log
01284         ("HSK[%x]: Cannot find the appropriate handler for the KX algorithm\n",
01285          session);
01286       MHD_gnutls_assert ();
01287       return GNUTLS_E_INTERNAL_ERROR;
01288     }
01289 
01290 
01291   return 0;
01292 }
01293 
01294 
01295 /* This function sets the given comp method to the session.
01296  */
01297 static int
01298 MHD__gnutls_client_set_comp_method (MHD_gtls_session_t session,
01299                                     opaque comp_method)
01300 {
01301   int comp_methods_num;
01302   uint8_t *compression_methods;
01303   int i;
01304 
01305   comp_methods_num = MHD_gtls_supported_compression_methods (session,
01306                                                              &compression_methods);
01307   if (comp_methods_num < 0)
01308     {
01309       MHD_gnutls_assert ();
01310       return comp_methods_num;
01311     }
01312 
01313   for (i = 0; i < comp_methods_num; i++)
01314     {
01315       if (compression_methods[i] == comp_method)
01316         {
01317           comp_methods_num = 0;
01318           break;
01319         }
01320     }
01321 
01322   MHD_gnutls_free (compression_methods);
01323 
01324   if (comp_methods_num != 0)
01325     {
01326       MHD_gnutls_assert ();
01327       return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM;
01328     }
01329 
01330   session->internals.compression_method =
01331     MHD_gtls_compression_get_id_from_int (comp_method);
01332 
01333 
01334   return 0;
01335 }
01336 
01337 /* This function returns 0 if we are resuming a session or -1 otherwise.
01338  * This also sets the variables in the session. Used only while reading a server
01339  * hello.
01340  */
01341 static int
01342 MHD__gnutls_client_check_if_resuming (MHD_gtls_session_t session,
01343                                       opaque * session_id, int session_id_len)
01344 {
01345   opaque buf[2 * TLS_MAX_SESSION_ID_SIZE + 1];
01346 
01347   MHD__gnutls_handshake_log ("HSK[%x]: SessionID length: %d\n", session,
01348                              session_id_len);
01349   MHD__gnutls_handshake_log ("HSK[%x]: SessionID: %s\n", session,
01350                              MHD_gtls_bin2hex (session_id, session_id_len,
01351                                                (char *) buf, sizeof (buf)));
01352 
01353   if (session_id_len > 0 &&
01354       session->internals.resumed_security_parameters.session_id_size ==
01355       session_id_len
01356       && memcmp (session_id,
01357                  session->internals.resumed_security_parameters.session_id,
01358                  session_id_len) == 0)
01359     {
01360       /* resume session */
01361       memcpy (session->internals.resumed_security_parameters.server_random,
01362               session->security_parameters.server_random, TLS_RANDOM_SIZE);
01363       memcpy (session->internals.resumed_security_parameters.client_random,
01364               session->security_parameters.client_random, TLS_RANDOM_SIZE);
01365       session->internals.resumed = RESUME_TRUE; /* we are resuming */
01366 
01367       return 0;
01368     }
01369   else
01370     {
01371       /* keep the new session id */
01372       session->internals.resumed = RESUME_FALSE;        /* we are not resuming */
01373       session->security_parameters.session_id_size = session_id_len;
01374       memcpy (session->security_parameters.session_id,
01375               session_id, session_id_len);
01376 
01377       return -1;
01378     }
01379 }
01380 
01381 /* This function reads and parses the server hello handshake message.
01382  * This function also restores resumed parameters if we are resuming a
01383  * session.
01384  */
01385 static int
01386 MHD__gnutls_read_server_hello (MHD_gtls_session_t session,
01387                                opaque * data, int datalen)
01388 {
01389   uint8_t session_id_len = 0;
01390   int pos = 0;
01391   int ret = 0;
01392   enum MHD_GNUTLS_Protocol version;
01393   int len = datalen;
01394 
01395   if (datalen < 38)
01396     {
01397       MHD_gnutls_assert ();
01398       return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
01399     }
01400 
01401   MHD__gnutls_handshake_log ("HSK[%x]: Server's version: %d.%d\n",
01402                              session, data[pos], data[pos + 1]);
01403 
01404   DECR_LEN (len, 2);
01405   version = MHD_gtls_version_get (data[pos], data[pos + 1]);
01406   if (MHD_gtls_version_is_supported (session, version) == 0)
01407     {
01408       MHD_gnutls_assert ();
01409       return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
01410     }
01411   else
01412     {
01413       MHD_gtls_set_current_version (session, version);
01414     }
01415 
01416   pos += 2;
01417 
01418   DECR_LEN (len, TLS_RANDOM_SIZE);
01419   MHD_gtls_set_server_random (session, &data[pos]);
01420   pos += TLS_RANDOM_SIZE;
01421 
01422 
01423   /* Read session ID
01424    */
01425   DECR_LEN (len, 1);
01426   session_id_len = data[pos++];
01427 
01428   if (len < session_id_len)
01429     {
01430       MHD_gnutls_assert ();
01431       return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
01432     }
01433   DECR_LEN (len, session_id_len);
01434 
01435 
01436   /* check if we are resuming and set the appropriate
01437    * values;
01438    */
01439   if (MHD__gnutls_client_check_if_resuming
01440       (session, &data[pos], session_id_len) == 0)
01441     return 0;
01442   pos += session_id_len;
01443 
01444 
01445   /* Check if the given cipher suite is supported and copy
01446    * it to the session.
01447    */
01448 
01449   DECR_LEN (len, 2);
01450   ret = MHD__gnutls_client_set_ciphersuite (session, &data[pos]);
01451   if (ret < 0)
01452     {
01453       MHD_gnutls_assert ();
01454       return ret;
01455     }
01456   pos += 2;
01457 
01458 
01459 
01460   /* move to compression   */
01461   DECR_LEN (len, 1);
01462 
01463   ret = MHD__gnutls_client_set_comp_method (session, data[pos++]);
01464   if (ret < 0)
01465     {
01466       MHD_gnutls_assert ();
01467       return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM;
01468     }
01469 
01470   /* Parse extensions.
01471    */
01472   if (version >= MHD_GNUTLS_PROTOCOL_TLS1_0)
01473     {
01474       ret = MHD_gtls_parse_extensions (session, EXTENSION_ANY, &data[pos], len);        /* len is the rest of the parsed length */
01475       if (ret < 0)
01476         {
01477           MHD_gnutls_assert ();
01478           return ret;
01479         }
01480     }
01481   return ret;
01482 }
01483 
01484 
01485 /* This function copies the appropriate ciphersuites to a locally allocated buffer
01486  * Needed in client hello messages. Returns the new data length.
01487  */
01488 int
01489 MHD__gnutls_copy_ciphersuites (MHD_gtls_session_t session,
01490                                opaque * ret_data, size_t ret_data_size)
01491 {
01492   int ret, i;
01493   cipher_suite_st *cipher_suites;
01494   uint16_t cipher_num;
01495   int datalen, pos;
01496 
01497   ret = MHD_gtls_supported_ciphersuites_sorted (session, &cipher_suites);
01498   if (ret < 0)
01499     {
01500       MHD_gnutls_assert ();
01501       return ret;
01502     }
01503 
01504   /* Here we remove any ciphersuite that does not conform
01505    * the certificate requested, or to the
01506    * authentication requested (eg SRP).
01507    */
01508   ret =
01509     MHD_gtls_remove_unwanted_ciphersuites (session, &cipher_suites, ret, -1);
01510   if (ret < 0)
01511     {
01512       MHD_gnutls_assert ();
01513       MHD_gnutls_free (cipher_suites);
01514       return ret;
01515     }
01516 
01517   /* If no cipher suites were enabled.
01518    */
01519   if (ret == 0)
01520     {
01521       MHD_gnutls_assert ();
01522       MHD_gnutls_free (cipher_suites);
01523       return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
01524     }
01525 
01526   cipher_num = ret;
01527 
01528   cipher_num *= sizeof (uint16_t);      /* in order to get bytes */
01529 
01530   datalen = pos = 0;
01531 
01532   datalen += sizeof (uint16_t) + cipher_num;
01533 
01534   if ((size_t) datalen > ret_data_size)
01535     {
01536       MHD_gnutls_assert ();
01537       return GNUTLS_E_INTERNAL_ERROR;
01538     }
01539 
01540   MHD_gtls_write_uint16 (cipher_num, ret_data);
01541   pos += 2;
01542 
01543   for (i = 0; i < (cipher_num / 2); i++)
01544     {
01545       memcpy (&ret_data[pos], cipher_suites[i].suite, 2);
01546       pos += 2;
01547     }
01548   MHD_gnutls_free (cipher_suites);
01549 
01550   return datalen;
01551 }
01552 
01553 /* This function copies the appropriate compression methods, to a locally allocated buffer
01554  * Needed in hello messages. Returns the new data length.
01555  */
01556 static int
01557 MHD__gnutls_copy_comp_methods (MHD_gtls_session_t session,
01558                                opaque * ret_data, size_t ret_data_size)
01559 {
01560   int ret, i;
01561   uint8_t *compression_methods, comp_num;
01562   int datalen, pos;
01563 
01564   ret =
01565     MHD_gtls_supported_compression_methods (session, &compression_methods);
01566   if (ret < 0)
01567     {
01568       MHD_gnutls_assert ();
01569       return ret;
01570     }
01571 
01572   comp_num = ret;
01573 
01574   datalen = pos = 0;
01575   datalen += comp_num + 1;
01576 
01577   if ((size_t) datalen > ret_data_size)
01578     {
01579       MHD_gnutls_assert ();
01580       return GNUTLS_E_INTERNAL_ERROR;
01581     }
01582 
01583   ret_data[pos++] = comp_num;   /* put the number of compression methods */
01584 
01585   for (i = 0; i < comp_num; i++)
01586     {
01587       ret_data[pos++] = compression_methods[i];
01588     }
01589 
01590   MHD_gnutls_free (compression_methods);
01591 
01592   return datalen;
01593 }
01594 
01595 static void
01596 MHD_gtls_set_adv_version (MHD_gtls_session_t session,
01597                           enum MHD_GNUTLS_Protocol ver)
01598 {
01599   set_adv_version (session, MHD_gtls_version_get_major (ver),
01600                    MHD_gtls_version_get_minor (ver));
01601 }
01602 
01603 /* This function sends the client hello handshake message.
01604  */
01605 static int
01606 MHD__gnutls_send_client_hello (MHD_gtls_session_t session, int again)
01607 {
01608   opaque *data = NULL;
01609   int extdatalen;
01610   int pos = 0;
01611   int datalen = 0, ret = 0;
01612   opaque rnd[TLS_RANDOM_SIZE];
01613   enum MHD_GNUTLS_Protocol hver;
01614   opaque extdata[MAX_EXT_DATA_LENGTH];
01615 
01616   opaque *SessionID =
01617     session->internals.resumed_security_parameters.session_id;
01618   uint8_t session_id_len =
01619     session->internals.resumed_security_parameters.session_id_size;
01620 
01621   if (SessionID == NULL)
01622     session_id_len = 0;
01623   else if (session_id_len == 0)
01624     SessionID = NULL;
01625 
01626   if (again == 0)
01627     {
01628 
01629       datalen = 2 + (session_id_len + 1) + TLS_RANDOM_SIZE;
01630       /* 2 for version, (4 for unix time + 28 for random bytes==TLS_RANDOM_SIZE)
01631        */
01632 
01633       data = MHD_gnutls_malloc (datalen);
01634       if (data == NULL)
01635         {
01636           MHD_gnutls_assert ();
01637           return GNUTLS_E_MEMORY_ERROR;
01638         }
01639 
01640       /* if we are resuming a session then we set the
01641        * version number to the previously established.
01642        */
01643       if (SessionID == NULL)
01644         hver = MHD_gtls_version_max (session);
01645       else
01646         {                       /* we are resuming a session */
01647           hver = session->internals.resumed_security_parameters.version;
01648         }
01649 
01650       if (hver == MHD_GNUTLS_PROTOCOL_VERSION_UNKNOWN || hver == 0)
01651         {
01652           MHD_gnutls_assert ();
01653           MHD_gnutls_free (data);
01654           return GNUTLS_E_INTERNAL_ERROR;
01655         }
01656 
01657       data[pos++] = MHD_gtls_version_get_major (hver);
01658       data[pos++] = MHD_gtls_version_get_minor (hver);
01659 
01660       /* Set the version we advertized as maximum
01661        * (RSA uses it).
01662        */
01663       MHD_gtls_set_adv_version (session, hver);
01664 
01665       /* Some old implementations do not interoperate if we send a
01666        * different version in the record layer.
01667        * It seems they prefer to read the record's version
01668        * as the one we actually requested.
01669        * The proper behaviour is to use the one in the client hello
01670        * handshake packet and ignore the one in the packet's record
01671        * header.
01672        */
01673       MHD_gtls_set_current_version (session, hver);
01674 
01675       /* In order to know when this session was initiated.
01676        */
01677       session->security_parameters.timestamp = time (NULL);
01678 
01679       /* Generate random data
01680        */
01681       MHD_gtls_tls_create_random (rnd);
01682       MHD_gtls_set_client_random (session, rnd);
01683 
01684       memcpy (&data[pos], rnd, TLS_RANDOM_SIZE);
01685       pos += TLS_RANDOM_SIZE;
01686 
01687       /* Copy the Session ID       */
01688       data[pos++] = session_id_len;
01689 
01690       if (session_id_len > 0)
01691         {
01692           memcpy (&data[pos], SessionID, session_id_len);
01693           pos += session_id_len;
01694         }
01695 
01696 
01697       /* Copy the ciphersuites.
01698        */
01699       extdatalen =
01700         MHD__gnutls_copy_ciphersuites (session, extdata, sizeof (extdata));
01701       if (extdatalen > 0)
01702         {
01703           datalen += extdatalen;
01704           data = MHD_gtls_realloc_fast (data, datalen);
01705           if (data == NULL)
01706             {
01707               MHD_gnutls_assert ();
01708               return GNUTLS_E_MEMORY_ERROR;
01709             }
01710 
01711           memcpy (&data[pos], extdata, extdatalen);
01712           pos += extdatalen;
01713 
01714         }
01715       else
01716         {
01717           if (extdatalen == 0)
01718             extdatalen = GNUTLS_E_INTERNAL_ERROR;
01719           MHD_gnutls_free (data);
01720           MHD_gnutls_assert ();
01721           return extdatalen;
01722         }
01723 
01724 
01725       /* Copy the compression methods.
01726        */
01727       extdatalen =
01728         MHD__gnutls_copy_comp_methods (session, extdata, sizeof (extdata));
01729       if (extdatalen > 0)
01730         {
01731           datalen += extdatalen;
01732           data = MHD_gtls_realloc_fast (data, datalen);
01733           if (data == NULL)
01734             {
01735               MHD_gnutls_assert ();
01736               return GNUTLS_E_MEMORY_ERROR;
01737             }
01738 
01739           memcpy (&data[pos], extdata, extdatalen);
01740           pos += extdatalen;
01741 
01742         }
01743       else
01744         {
01745           if (extdatalen == 0)
01746             extdatalen = GNUTLS_E_INTERNAL_ERROR;
01747           MHD_gnutls_free (data);
01748           MHD_gnutls_assert ();
01749           return extdatalen;
01750         }
01751 
01752       /* Generate and copy TLS extensions.
01753        */
01754       if (hver >= MHD_GNUTLS_PROTOCOL_TLS1_0)
01755         {
01756           extdatalen =
01757             MHD_gtls_gen_extensions (session, extdata, sizeof (extdata));
01758 
01759           if (extdatalen > 0)
01760             {
01761               datalen += extdatalen;
01762               data = MHD_gtls_realloc_fast (data, datalen);
01763               if (data == NULL)
01764                 {
01765                   MHD_gnutls_assert ();
01766                   return GNUTLS_E_MEMORY_ERROR;
01767                 }
01768 
01769               memcpy (&data[pos], extdata, extdatalen);
01770             }
01771           else if (extdatalen < 0)
01772             {
01773               MHD_gnutls_assert ();
01774               MHD_gnutls_free (data);
01775               return extdatalen;
01776             }
01777         }
01778     }
01779 
01780   ret =
01781     MHD_gtls_send_handshake (session, data, datalen,
01782                              GNUTLS_HANDSHAKE_CLIENT_HELLO);
01783   MHD_gnutls_free (data);
01784 
01785   return ret;
01786 }
01787 #endif
01788 
01789 static int
01790 MHD__gnutls_send_server_hello (MHD_gtls_session_t session, int again)
01791 {
01792   opaque *data = NULL;
01793   opaque extdata[MAX_EXT_DATA_LENGTH];
01794   int extdatalen;
01795   int pos = 0;
01796   int datalen, ret = 0;
01797   uint8_t comp;
01798   opaque *SessionID = session->security_parameters.session_id;
01799   uint8_t session_id_len = session->security_parameters.session_id_size;
01800   opaque buf[2 * TLS_MAX_SESSION_ID_SIZE + 1];
01801 
01802   if (SessionID == NULL)
01803     session_id_len = 0;
01804 
01805   datalen = 0;
01806 
01807   if (again == 0)
01808     {
01809       datalen = 2 + session_id_len + 1 + TLS_RANDOM_SIZE + 3;
01810       extdatalen =
01811         MHD_gtls_gen_extensions (session, extdata, sizeof (extdata));
01812 
01813       if (extdatalen < 0)
01814         {
01815           MHD_gnutls_assert ();
01816           return extdatalen;
01817         }
01818 
01819       data = MHD_gnutls_alloca (datalen + extdatalen);
01820       if (data == NULL)
01821         {
01822           MHD_gnutls_assert ();
01823           return GNUTLS_E_MEMORY_ERROR;
01824         }
01825 
01826       data[pos++] =
01827         MHD_gtls_version_get_major (session->security_parameters.version);
01828       data[pos++] =
01829         MHD_gtls_version_get_minor (session->security_parameters.version);
01830 
01831       memcpy (&data[pos],
01832               session->security_parameters.server_random, TLS_RANDOM_SIZE);
01833       pos += TLS_RANDOM_SIZE;
01834 
01835       data[pos++] = session_id_len;
01836       if (session_id_len > 0)
01837         {
01838           memcpy (&data[pos], SessionID, session_id_len);
01839         }
01840       pos += session_id_len;
01841 
01842       MHD__gnutls_handshake_log ("HSK[%x]: SessionID: %s\n", session,
01843                                  MHD_gtls_bin2hex (SessionID, session_id_len,
01844                                                    (char *) buf,
01845                                                    sizeof (buf)));
01846 
01847       memcpy (&data[pos],
01848               session->security_parameters.current_cipher_suite.suite, 2);
01849       pos += 2;
01850 
01851       comp =
01852         (uint8_t) MHD_gtls_compression_get_num (session->
01853                                                 internals.compression_method);
01854       data[pos++] = comp;
01855 
01856 
01857       if (extdatalen > 0)
01858         {
01859           datalen += extdatalen;
01860 
01861           memcpy (&data[pos], extdata, extdatalen);
01862         }
01863     }
01864 
01865   ret =
01866     MHD_gtls_send_handshake (session, data, datalen,
01867                              GNUTLS_HANDSHAKE_SERVER_HELLO);
01868   MHD_gnutls_afree (data);
01869 
01870   return ret;
01871 }
01872 
01873 int
01874 MHD_gtls_send_hello (MHD_gtls_session_t session, int again)
01875 {
01876   int ret;
01877 #if MHD_DEBUG_TLS
01878   if (session->security_parameters.entity == GNUTLS_CLIENT)
01879     {
01880       ret = MHD__gnutls_send_client_hello (session, again);
01881 
01882     }
01883   else
01884 #endif
01885     {                           /* SERVER */
01886       ret = MHD__gnutls_send_server_hello (session, again);
01887     }
01888 
01889   return ret;
01890 }
01891 
01892 /* RECEIVE A HELLO MESSAGE. This should be called from MHD_gnutls_recv_handshake_int only if a
01893  * hello message is expected. It uses the security_parameters.current_cipher_suite
01894  * and internals.compression_method.
01895  */
01896 int
01897 MHD_gtls_recv_hello (MHD_gtls_session_t session, opaque * data, int datalen)
01898 {
01899   int ret;
01900 #if MHD_DEBUG_TLS
01901   if (session->security_parameters.entity == GNUTLS_CLIENT)
01902     {
01903       ret = MHD__gnutls_read_server_hello (session, data, datalen);
01904       if (ret < 0)
01905         {
01906           MHD_gnutls_assert ();
01907           return ret;
01908         }
01909     }
01910   else
01911 #endif
01912     {                           /* Server side reading a client hello */
01913 
01914       ret = MHD__gnutls_read_client_hello (session, data, datalen);
01915       if (ret < 0)
01916         {
01917           MHD_gnutls_assert ();
01918           return ret;
01919         }
01920     }
01921 
01922   return ret;
01923 }
01924 
01925 /* The packets in MHD__gnutls_handshake (it's more broad than original TLS handshake)
01926  *
01927  *     Client                                               Server
01928  *
01929  *     ClientHello                  -------->
01930  *                                  <--------         ServerHello
01931  *
01932  *                                                    Certificate*
01933  *                                              ServerKeyExchange*
01934  *                                  <--------   CertificateRequest*
01935  *
01936  *                                  <--------      ServerHelloDone
01937  *     Certificate*
01938  *     ClientKeyExchange
01939  *     CertificateVerify*
01940  *     [ChangeCipherSpec]
01941  *     Finished                     -------->
01942  *                                              [ChangeCipherSpec]
01943  *                                  <--------             Finished
01944  *
01945  * (*): means optional packet.
01946  */
01947 
01971 int
01972 MHD__gnutls_rehandshake (MHD_gtls_session_t session)
01973 {
01974   int ret;
01975 
01976   ret =
01977     MHD__gnutls_send_empty_handshake (session, GNUTLS_HANDSHAKE_HELLO_REQUEST,
01978                                       AGAIN (STATE50));
01979   STATE = STATE50;
01980 
01981   if (ret < 0)
01982     {
01983       MHD_gnutls_assert ();
01984       return ret;
01985     }
01986   STATE = STATE0;
01987 
01988   return 0;
01989 }
01990 
01991 inline static int
01992 MHD__gnutls_abort_handshake (MHD_gtls_session_t session, int ret)
01993 {
01994   if (((ret == GNUTLS_E_WARNING_ALERT_RECEIVED) &&
01995        (MHD_gnutls_alert_get (session) == GNUTLS_A_NO_RENEGOTIATION))
01996       || ret == GNUTLS_E_GOT_APPLICATION_DATA)
01997     return 0;
01998 
01999   /* this doesn't matter */
02000   return GNUTLS_E_INTERNAL_ERROR;
02001 }
02002 
02003 /* This function initialized the handshake hash session.
02004  * required for finished messages.
02005  */
02006 inline static int
02007 MHD__gnutls_handshake_hash_init (MHD_gtls_session_t session)
02008 {
02009 
02010   if (session->internals.handshake_mac_handle_md5 == NULL)
02011     {
02012       session->internals.handshake_mac_handle_md5 =
02013         MHD_gtls_hash_init (MHD_GNUTLS_MAC_MD5);
02014 
02015       if (session->internals.handshake_mac_handle_md5 == GNUTLS_HASH_FAILED)
02016         {
02017           MHD_gnutls_assert ();
02018           return GNUTLS_E_MEMORY_ERROR;
02019         }
02020     }
02021 
02022   if (session->internals.handshake_mac_handle_sha == NULL)
02023     {
02024       session->internals.handshake_mac_handle_sha =
02025         MHD_gtls_hash_init (MHD_GNUTLS_MAC_SHA1);
02026       if (session->internals.handshake_mac_handle_sha == GNUTLS_HASH_FAILED)
02027         {
02028           MHD_gnutls_assert ();
02029           return GNUTLS_E_MEMORY_ERROR;
02030         }
02031     }
02032 
02033   return 0;
02034 }
02035 
02036 static int
02037 MHD__gnutls_send_supplemental (MHD_gtls_session_t session, int again)
02038 {
02039   int ret = 0;
02040 
02041   MHD__gnutls_debug_log ("EXT[%x]: Sending supplemental data\n", session);
02042 
02043   if (again)
02044     ret = MHD_gtls_send_handshake (session, NULL, 0,
02045                                    GNUTLS_HANDSHAKE_SUPPLEMENTAL);
02046   else
02047     {
02048       MHD_gtls_buffer buf;
02049       MHD_gtls_buffer_init (&buf);
02050 
02051       ret = MHD__gnutls_gen_supplemental (session, &buf);
02052       if (ret < 0)
02053         {
02054           MHD_gnutls_assert ();
02055           return ret;
02056         }
02057 
02058       ret = MHD_gtls_send_handshake (session, buf.data, buf.length,
02059                                      GNUTLS_HANDSHAKE_SUPPLEMENTAL);
02060       MHD_gtls_buffer_clear (&buf);
02061     }
02062 
02063   return ret;
02064 }
02065 
02066 static int
02067 MHD__gnutls_recv_supplemental (MHD_gtls_session_t session)
02068 {
02069   uint8_t *data = NULL;
02070   int datalen = 0;
02071   int ret;
02072 
02073   MHD__gnutls_debug_log ("EXT[%x]: Expecting supplemental data\n", session);
02074 
02075   ret = MHD_gtls_recv_handshake (session, &data, &datalen,
02076                                  GNUTLS_HANDSHAKE_SUPPLEMENTAL,
02077                                  OPTIONAL_PACKET);
02078   if (ret < 0)
02079     {
02080       MHD_gnutls_assert ();
02081       return ret;
02082     }
02083 
02084   ret = MHD__gnutls_parse_supplemental (session, data, datalen);
02085   if (ret < 0)
02086     {
02087       MHD_gnutls_assert ();
02088       return ret;
02089     }
02090 
02091   MHD_gnutls_free (data);
02092 
02093   return ret;
02094 }
02095 
02123 int
02124 MHD__gnutls_handshake (MHD_gtls_session_t session)
02125 {
02126   int ret;
02127 
02128   if ((ret = MHD__gnutls_handshake_hash_init (session)) < 0)
02129     {
02130       MHD_gnutls_assert ();
02131       return ret;
02132     }
02133 #if MHD_DEBUG_TLS
02134   if (session->security_parameters.entity == GNUTLS_CLIENT)
02135     {
02136       ret = MHD_gtls_handshake_client (session);
02137     }
02138   else
02139 #endif
02140     {
02141       ret = MHD_gtls_handshake_server (session);
02142     }
02143 
02144   if (ret < 0)
02145     {
02146       /* In the case of a rehandshake abort
02147        * we should reset the handshake's internal state.
02148        */
02149       if (MHD__gnutls_abort_handshake (session, ret) == 0)
02150         STATE = STATE0;
02151 
02152       return ret;
02153     }
02154 
02155   ret = MHD_gtls_handshake_common (session);
02156 
02157   if (ret < 0)
02158     {
02159       if (MHD__gnutls_abort_handshake (session, ret) == 0)
02160         STATE = STATE0;
02161 
02162       return ret;
02163     }
02164 
02165   STATE = STATE0;
02166 
02167   MHD__gnutls_handshake_io_buffer_clear (session);
02168   MHD_gtls_handshake_internal_state_clear (session);
02169 
02170   return 0;
02171 }
02172 
02173 #define IMED_RET( str, ret) do { \
02174         if (ret < 0) { \
02175                 if (MHD_gtls_error_is_fatal(ret)==0) return ret; \
02176                 MHD_gnutls_assert(); \
02177                 ERR( str, ret); \
02178                 MHD__gnutls_handshake_hash_buffers_clear(session); \
02179                 return ret; \
02180         } } while (0)
02181 
02182 
02183 #if MHD_DEBUG_TLS
02184 /*
02185  * MHD_gtls_handshake_client
02186  * This function performs the client side of the handshake of the TLS/SSL protocol.
02187  */
02188 static int
02189 MHD_gtls_handshake_client (MHD_gtls_session_t session)
02190 {
02191   int ret = 0;
02192 
02193   switch (STATE)
02194     {
02195     case STATE0:
02196     case STATE1:
02197       ret = MHD_gtls_send_hello (session, AGAIN (STATE1));
02198       STATE = STATE1;
02199       IMED_RET ("send hello", ret);
02200 
02201     case STATE2:
02202       /* receive the server hello */
02203       ret =
02204         MHD_gtls_recv_handshake (session, NULL, NULL,
02205                                  GNUTLS_HANDSHAKE_SERVER_HELLO,
02206                                  MANDATORY_PACKET);
02207       STATE = STATE2;
02208       IMED_RET ("recv hello", ret);
02209 
02210     case STATE70:
02211       if (session->security_parameters.extensions.do_recv_supplemental)
02212         {
02213           ret = MHD__gnutls_recv_supplemental (session);
02214           STATE = STATE70;
02215           IMED_RET ("recv supplemental", ret);
02216         }
02217 
02218     case STATE3:
02219       /* RECV CERTIFICATE */
02220       if (session->internals.resumed == RESUME_FALSE)   /* if we are not resuming */
02221         ret = MHD_gtls_recv_server_certificate (session);
02222       STATE = STATE3;
02223       IMED_RET ("recv server certificate", ret);
02224 
02225     case STATE4:
02226       /* receive the server key exchange */
02227       if (session->internals.resumed == RESUME_FALSE)   /* if we are not resuming */
02228         ret = MHD_gtls_recv_server_kx_message (session);
02229       STATE = STATE4;
02230       IMED_RET ("recv server kx message", ret);
02231 
02232     case STATE5:
02233       /* receive the server certificate request - if any
02234        */
02235 
02236       if (session->internals.resumed == RESUME_FALSE)   /* if we are not resuming */
02237         ret = MHD_gtls_recv_server_certificate_request (session);
02238       STATE = STATE5;
02239       IMED_RET ("recv server certificate request message", ret);
02240 
02241     case STATE6:
02242       /* receive the server hello done */
02243       if (session->internals.resumed == RESUME_FALSE)   /* if we are not resuming */
02244         ret =
02245           MHD_gtls_recv_handshake (session, NULL, NULL,
02246                                    GNUTLS_HANDSHAKE_SERVER_HELLO_DONE,
02247                                    MANDATORY_PACKET);
02248       STATE = STATE6;
02249       IMED_RET ("recv server hello done", ret);
02250 
02251     case STATE71:
02252       if (session->security_parameters.extensions.do_send_supplemental)
02253         {
02254           ret = MHD__gnutls_send_supplemental (session, AGAIN (STATE71));
02255           STATE = STATE71;
02256           IMED_RET ("send supplemental", ret);
02257         }
02258 
02259     case STATE7:
02260       /* send our certificate - if any and if requested
02261        */
02262       if (session->internals.resumed == RESUME_FALSE)   /* if we are not resuming */
02263         ret = MHD_gtls_send_client_certificate (session, AGAIN (STATE7));
02264       STATE = STATE7;
02265       IMED_RET ("send client certificate", ret);
02266 
02267     case STATE8:
02268       if (session->internals.resumed == RESUME_FALSE)   /* if we are not resuming */
02269         ret = MHD_gtls_send_client_kx_message (session, AGAIN (STATE8));
02270       STATE = STATE8;
02271       IMED_RET ("send client kx", ret);
02272 
02273     case STATE9:
02274       /* send client certificate verify */
02275       if (session->internals.resumed == RESUME_FALSE)   /* if we are not resuming */
02276         ret =
02277           MHD_gtls_send_client_certificate_verify (session, AGAIN (STATE9));
02278       STATE = STATE9;
02279       IMED_RET ("send client certificate verify", ret);
02280 
02281       STATE = STATE0;
02282     default:
02283       break;
02284     }
02285 
02286 
02287   return 0;
02288 }
02289 #endif
02290 
02291 /* This function sends the final handshake packets and initializes connection
02292  */
02293 static int
02294 MHD__gnutls_send_handshake_final (MHD_gtls_session_t session, int init)
02295 {
02296   int ret = 0;
02297 
02298   /* Send the CHANGE CIPHER SPEC PACKET */
02299 
02300   switch (STATE)
02301     {
02302     case STATE0:
02303     case STATE20:
02304       ret = MHD_gtls_send_change_cipher_spec (session, AGAIN (STATE20));
02305       STATE = STATE20;
02306       if (ret < 0)
02307         {
02308           ERR ("send ChangeCipherSpec", ret);
02309           MHD_gnutls_assert ();
02310           return ret;
02311         }
02312 
02313       /* Initialize the connection session (start encryption) - in case of client
02314        */
02315       if (init == TRUE)
02316         {
02317           ret = MHD_gtls_connection_state_init (session);
02318           if (ret < 0)
02319             {
02320               MHD_gnutls_assert ();
02321               return ret;
02322             }
02323         }
02324 
02325       ret = MHD_gtls_write_connection_state_init (session);
02326       if (ret < 0)
02327         {
02328           MHD_gnutls_assert ();
02329           return ret;
02330         }
02331 
02332     case STATE21:
02333       /* send the finished message */
02334       ret = MHD__gnutls_send_finished (session, AGAIN (STATE21));
02335       STATE = STATE21;
02336       if (ret < 0)
02337         {
02338           ERR ("send Finished", ret);
02339           MHD_gnutls_assert ();
02340           return ret;
02341         }
02342 
02343       STATE = STATE0;
02344     default:
02345       break;
02346     }
02347 
02348   return 0;
02349 }
02350 
02351 /* This function receives the final handshake packets
02352  * And executes the appropriate function to initialize the
02353  * read session.
02354  */
02355 static int
02356 MHD__gnutls_recv_handshake_final (MHD_gtls_session_t session, int init)
02357 {
02358   int ret = 0;
02359   uint8_t ch;
02360 
02361   switch (STATE)
02362     {
02363     case STATE0:
02364     case STATE30:
02365       ret =
02366         MHD_gtls_recv_int (session, GNUTLS_CHANGE_CIPHER_SPEC, -1, &ch, 1);
02367       STATE = STATE30;
02368       if (ret <= 0)
02369         {
02370           ERR ("recv ChangeCipherSpec", ret);
02371           MHD_gnutls_assert ();
02372           return (ret < 0) ? ret : GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
02373         }
02374 
02375       /* Initialize the connection session (start encryption) - in case of server */
02376       if (init == TRUE)
02377         {
02378           ret = MHD_gtls_connection_state_init (session);
02379           if (ret < 0)
02380             {
02381               MHD_gnutls_assert ();
02382               return ret;
02383             }
02384         }
02385 
02386       ret = MHD_gtls_read_connection_state_init (session);
02387       if (ret < 0)
02388         {
02389           MHD_gnutls_assert ();
02390           return ret;
02391         }
02392 
02393     case STATE31:
02394       ret = MHD__gnutls_recv_finished (session);
02395       STATE = STATE31;
02396       if (ret < 0)
02397         {
02398           ERR ("recv finished", ret);
02399           MHD_gnutls_assert ();
02400           return ret;
02401         }
02402       STATE = STATE0;
02403     default:
02404       break;
02405     }
02406 
02407 
02408   return 0;
02409 }
02410 
02411  /*
02412   * MHD_gtls_handshake_server
02413   * This function does the server stuff of the handshake protocol.
02414   */
02415 
02416 static int
02417 MHD_gtls_handshake_server (MHD_gtls_session_t session)
02418 {
02419   int ret = 0;
02420 
02421   switch (STATE)
02422     {
02423     case STATE0:
02424     case STATE1:
02425       ret =
02426         MHD_gtls_recv_handshake (session, NULL, NULL,
02427                                  GNUTLS_HANDSHAKE_CLIENT_HELLO,
02428                                  MANDATORY_PACKET);
02429       STATE = STATE1;
02430       IMED_RET ("recv hello", ret);
02431 
02432     case STATE2:
02433       ret = MHD_gtls_send_hello (session, AGAIN (STATE2));
02434       STATE = STATE2;
02435       IMED_RET ("send hello", ret);
02436 
02437     case STATE70:
02438       if (session->security_parameters.extensions.do_send_supplemental)
02439         {
02440           ret = MHD__gnutls_send_supplemental (session, AGAIN (STATE70));
02441           STATE = STATE70;
02442           IMED_RET ("send supplemental data", ret);
02443         }
02444 
02445       /* SEND CERTIFICATE + KEYEXCHANGE + CERTIFICATE_REQUEST */
02446     case STATE3:
02447       /* NOTE: these should not be send if we are resuming */
02448 
02449       if (session->internals.resumed == RESUME_FALSE)
02450         ret = MHD_gtls_send_server_certificate (session, AGAIN (STATE3));
02451       STATE = STATE3;
02452       IMED_RET ("send server certificate", ret);
02453 
02454     case STATE4:
02455       /* send server key exchange (A) */
02456       if (session->internals.resumed == RESUME_FALSE)
02457         ret = MHD_gtls_send_server_kx_message (session, AGAIN (STATE4));
02458       STATE = STATE4;
02459       IMED_RET ("send server kx", ret);
02460 
02461     case STATE5:
02462       /* Send certificate request - if requested to */
02463       if (session->internals.resumed == RESUME_FALSE)
02464         ret =
02465           MHD_gtls_send_server_certificate_request (session, AGAIN (STATE5));
02466       STATE = STATE5;
02467       IMED_RET ("send server cert request", ret);
02468 
02469     case STATE6:
02470       /* send the server hello done */
02471       if (session->internals.resumed == RESUME_FALSE)   /* if we are not resuming */
02472         ret =
02473           MHD__gnutls_send_empty_handshake (session,
02474                                             GNUTLS_HANDSHAKE_SERVER_HELLO_DONE,
02475                                             AGAIN (STATE6));
02476       STATE = STATE6;
02477       IMED_RET ("send server hello done", ret);
02478 
02479     case STATE71:
02480       if (session->security_parameters.extensions.do_recv_supplemental)
02481         {
02482           ret = MHD__gnutls_recv_supplemental (session);
02483           STATE = STATE71;
02484           IMED_RET ("recv client supplemental", ret);
02485         }
02486 
02487       /* RECV CERTIFICATE + KEYEXCHANGE + CERTIFICATE_VERIFY */
02488     case STATE7:
02489       /* receive the client certificate message */
02490       if (session->internals.resumed == RESUME_FALSE)   /* if we are not resuming */
02491         ret = MHD_gtls_recv_client_certificate (session);
02492       STATE = STATE7;
02493       IMED_RET ("recv client certificate", ret);
02494 
02495     case STATE8:
02496       /* receive the client key exchange message */
02497       if (session->internals.resumed == RESUME_FALSE)   /* if we are not resuming */
02498         ret = MHD_gtls_recv_client_kx_message (session);
02499       STATE = STATE8;
02500       IMED_RET ("recv client kx", ret);
02501 
02502     case STATE9:
02503       /* receive the client certificate verify message */
02504       if (session->internals.resumed == RESUME_FALSE)   /* if we are not resuming */
02505         ret = MHD_gtls_recv_client_certificate_verify_message (session);
02506       STATE = STATE9;
02507       IMED_RET ("recv client certificate verify", ret);
02508 
02509       STATE = STATE0;           /* finished thus clear session */
02510     default:
02511       break;
02512     }
02513 
02514   return 0;
02515 }
02516 
02517 static int
02518 MHD_gtls_handshake_common (MHD_gtls_session_t session)
02519 {
02520   int ret = 0;
02521 
02522   /* send and recv the change cipher spec and finished messages */
02523   if ((session->internals.resumed == RESUME_TRUE
02524        && session->security_parameters.entity == GNUTLS_CLIENT)
02525       || (session->internals.resumed == RESUME_FALSE
02526           && session->security_parameters.entity == GNUTLS_SERVER))
02527     {
02528       /* if we are a client resuming - or we are a server not resuming */
02529 
02530       ret = MHD__gnutls_recv_handshake_final (session, TRUE);
02531       IMED_RET ("recv handshake final", ret);
02532 
02533       ret = MHD__gnutls_send_handshake_final (session, FALSE);
02534       IMED_RET ("send handshake final", ret);
02535     }
02536   else
02537     {                           /* if we are a client not resuming - or we are a server resuming */
02538 
02539       ret = MHD__gnutls_send_handshake_final (session, TRUE);
02540       IMED_RET ("send handshake final 2", ret);
02541 
02542       ret = MHD__gnutls_recv_handshake_final (session, FALSE);
02543       IMED_RET ("recv handshake final 2", ret);
02544     }
02545 
02546   /* clear handshake buffer */
02547   MHD__gnutls_handshake_hash_buffers_clear (session);
02548   return ret;
02549 
02550 }
02551 
02552 static int
02553 MHD_gtls_generate_session_id (opaque * session_id, uint8_t * len)
02554 {
02555   *len = TLS_MAX_SESSION_ID_SIZE;
02556 
02557   if (MHD_gc_nonce ((char *) session_id, *len) != GC_OK)
02558     {
02559       MHD_gnutls_assert ();
02560       return GNUTLS_E_RANDOM_FAILED;
02561     }
02562 
02563   return 0;
02564 }
02565 
02566 int
02567 MHD_gtls_recv_hello_request (MHD_gtls_session_t session, void *data,
02568                              uint32_t data_size)
02569 {
02570   uint8_t type;
02571 
02572   if (session->security_parameters.entity == GNUTLS_SERVER)
02573     {
02574       MHD_gnutls_assert ();
02575       return GNUTLS_E_UNEXPECTED_PACKET;
02576     }
02577   if (data_size < 1)
02578     {
02579       MHD_gnutls_assert ();
02580       return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
02581     }
02582   type = ((uint8_t *) data)[0];
02583   if (type == GNUTLS_HANDSHAKE_HELLO_REQUEST)
02584     return GNUTLS_E_REHANDSHAKE;
02585   else
02586     {
02587       MHD_gnutls_assert ();
02588       return GNUTLS_E_UNEXPECTED_PACKET;
02589     }
02590 }
02591 
02592 /* Returns 1 if the given KX has not the corresponding parameters
02593  * (DH or RSA) set up. Otherwise returns 0.
02594  */
02595 inline static int
02596 check_server_params (MHD_gtls_session_t session,
02597                      enum MHD_GNUTLS_KeyExchangeAlgorithm kx,
02598                      enum MHD_GNUTLS_KeyExchangeAlgorithm *alg, int alg_size)
02599 {
02600   int cred_type;
02601   MHD_gtls_dh_params_t dh_params = NULL;
02602   MHD_gtls_rsa_params_t rsa_params = NULL;
02603   int j;
02604 
02605   cred_type = MHD_gtls_map_kx_get_cred (kx, 1);
02606 
02607   /* Read the Diffie Hellman parameters, if any.
02608    */
02609   if (cred_type == MHD_GNUTLS_CRD_CERTIFICATE)
02610     {
02611       int delete;
02612       MHD_gtls_cert_credentials_t x509_cred =
02613         (MHD_gtls_cert_credentials_t) MHD_gtls_get_cred (session->key,
02614                                                          cred_type, NULL);
02615 
02616       if (x509_cred != NULL)
02617         {
02618           dh_params =
02619             MHD_gtls_get_dh_params (x509_cred->dh_params,
02620                                     x509_cred->params_func, session);
02621           rsa_params =
02622             MHD_gtls_certificate_get_rsa_params (x509_cred->rsa_params,
02623                                                  x509_cred->params_func,
02624                                                  session);
02625         }
02626 
02627       /* Check also if the certificate supports the
02628        * KX method.
02629        */
02630       delete = 1;
02631       for (j = 0; j < alg_size; j++)
02632         {
02633           if (alg[j] == kx)
02634             {
02635               delete = 0;
02636               break;
02637             }
02638         }
02639 
02640       if (delete == 1)
02641         return 1;
02642 
02643     }
02644   else
02645     return 0;                   /* no need for params */
02646 
02647 
02648   /* If the key exchange method needs RSA or DH params,
02649    * but they are not set then remove it.
02650    */
02651   if (MHD_gtls_kx_needs_rsa_params (kx) != 0)
02652     {
02653       /* needs rsa params. */
02654       if (MHD__gnutls_rsa_params_to_mpi (rsa_params) == NULL)
02655         {
02656           MHD_gnutls_assert ();
02657           return 1;
02658         }
02659     }
02660 
02661   if (MHD_gtls_kx_needs_dh_params (kx) != 0)
02662     {
02663       /* needs DH params. */
02664       if (MHD_gtls_dh_params_to_mpi (dh_params) == NULL)
02665         {
02666           MHD_gnutls_assert ();
02667           return 1;
02668         }
02669     }
02670 
02671   return 0;
02672 }
02673 
02674 /* This function will remove algorithms that are not supported by
02675  * the requested authentication method. We remove an algorithm if
02676  * we have a certificate with keyUsage bits set.
02677  *
02678  * This does a more high level check than  MHD_gnutls_supported_ciphersuites(),
02679  * by checking certificates etc.
02680  */
02681 static int
02682 MHD_gtls_remove_unwanted_ciphersuites (MHD_gtls_session_t session,
02683                                        cipher_suite_st ** cipherSuites,
02684                                        int numCipherSuites,
02685                                        enum MHD_GNUTLS_PublicKeyAlgorithm
02686                                        requested_pk_algo)
02687 {
02688 
02689   int ret = 0;
02690   cipher_suite_st *newSuite, cs;
02691   int newSuiteSize = 0, i;
02692   MHD_gtls_cert_credentials_t cert_cred;
02693   enum MHD_GNUTLS_KeyExchangeAlgorithm kx;
02694   int server = session->security_parameters.entity == GNUTLS_SERVER ? 1 : 0;
02695   enum MHD_GNUTLS_KeyExchangeAlgorithm *alg = NULL;
02696   int alg_size = 0;
02697 
02698   /* if we should use a specific certificate,
02699    * we should remove all algorithms that are not supported
02700    * by that certificate and are on the same authentication
02701    * method (CERTIFICATE).
02702    */
02703 
02704   cert_cred =
02705     (MHD_gtls_cert_credentials_t) MHD_gtls_get_cred (session->key,
02706                                                      MHD_GNUTLS_CRD_CERTIFICATE,
02707                                                      NULL);
02708 
02709   /* If there are certificate credentials, find an appropriate certificate
02710    * or disable them;
02711    */
02712   if (session->security_parameters.entity == GNUTLS_SERVER
02713       && cert_cred != NULL)
02714     {
02715       ret = MHD_gtls_server_select_cert (session, requested_pk_algo);
02716       if (ret < 0)
02717         {
02718           MHD_gnutls_assert ();
02719           MHD__gnutls_x509_log
02720             ("Could not find an appropriate certificate: %s\n",
02721              MHD_gtls_strerror (ret));
02722           cert_cred = NULL;
02723         }
02724     }
02725 
02726   /* get all the key exchange algorithms that are
02727    * supported by the X509 certificate parameters.
02728    */
02729   if ((ret =
02730        MHD_gtls_selected_cert_supported_kx (session, &alg, &alg_size)) < 0)
02731     {
02732       MHD_gnutls_assert ();
02733       return ret;
02734     }
02735 
02736   newSuite = MHD_gnutls_malloc (numCipherSuites * sizeof (cipher_suite_st));
02737   if (newSuite == NULL)
02738     {
02739       MHD_gnutls_assert ();
02740       MHD_gnutls_free (alg);
02741       return GNUTLS_E_MEMORY_ERROR;
02742     }
02743 
02744   /* now removes ciphersuites based on the KX algorithm
02745    */
02746   for (i = 0; i < numCipherSuites; i++)
02747     {
02748       int delete = 0;
02749 
02750       /* finds the key exchange algorithm in
02751        * the ciphersuite
02752        */
02753       kx = MHD_gtls_cipher_suite_get_kx_algo (&(*cipherSuites)[i]);
02754 
02755       /* if it is defined but had no credentials
02756        */
02757       if (MHD_gtls_get_kx_cred (session, kx, NULL) == NULL)
02758         {
02759           delete = 1;
02760         }
02761       else
02762         {
02763           delete = 0;
02764 
02765           if (server)
02766             delete = check_server_params (session, kx, alg, alg_size);
02767         }
02768       memcpy (&cs.suite, &(*cipherSuites)[i].suite, 2);
02769 
02770       if (delete == 0)
02771         {
02772 
02773           MHD__gnutls_handshake_log ("HSK[%x]: Keeping ciphersuite: %s\n",
02774                                      session,
02775                                      MHD_gtls_cipher_suite_get_name (&cs));
02776 
02777           memcpy (newSuite[newSuiteSize].suite, (*cipherSuites)[i].suite, 2);
02778           newSuiteSize++;
02779         }
02780       else
02781         {
02782           MHD__gnutls_handshake_log ("HSK[%x]: Removing ciphersuite: %s\n",
02783                                      session,
02784                                      MHD_gtls_cipher_suite_get_name (&cs));
02785 
02786         }
02787     }
02788 
02789   MHD_gnutls_free (alg);
02790   MHD_gnutls_free (*cipherSuites);
02791   *cipherSuites = newSuite;
02792 
02793   ret = newSuiteSize;
02794 
02795   return ret;
02796 
02797 }
02798 
02799 enum MHD_GNUTLS_Protocol
02800 MHD_gtls_get_adv_version (MHD_gtls_session_t session)
02801 {
02802   return MHD_gtls_version_get (MHD__gnutls_get_adv_version_major (session),
02803                                MHD__gnutls_get_adv_version_minor (session));
02804 }

Generated on Tue May 19 23:21:08 2009 for GNU libmicrohttpd by  doxygen 1.5.8