00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "ComputeCallback.h"
00019 #include "StateInfo.h"
00020 #include "CODEX_Server/ServerState.h"
00021
00022 #include "CODEX_Exceptions/BignumExceptions.h"
00023 #include "CODEX_Server/ServerExceptions.h"
00024
00025 #include "timing.h"
00026
00027 using namespace CODEX_APSS;
00028
00029 ComputeCallback::ComputeCallback( const LabelType& label ) :
00030 m_label( label ),
00031 m_completed( false )
00032 {
00033 }
00034
00035 ComputeCallback::~ComputeCallback()
00036 {
00037 }
00038
00039 bool
00040 ComputeCallback::operator()( unsigned int server, CODEX_Quorum::Message* msg )
00041 {
00042 if ( m_completed )
00043 {
00044 if ( 0 != msg ) delete msg;
00045 return true;
00046 }
00047
00048 if ( 0 == msg )
00049 {
00050 return false;
00051 }
00052
00053 #ifdef TIMING
00054 ActiveTimer.start();
00055 #endif
00056 CODEX_Server::ServerState* serverState =
00057 CODEX_Server::ServerState::instance();
00058 if ( 0 == serverState )
00059 {
00060 delete msg;
00061 #ifdef TIMING
00062 ActiveTimer.stop();
00063 #endif
00064 return false;
00065 }
00066
00067 StateInfo* stateInfo = StateInfo::instance();
00068 if ( 0 == stateInfo )
00069 {
00070 delete msg;
00071 #ifdef TIMING
00072 ActiveTimer.stop();
00073 #endif
00074 return false;
00075 }
00076
00077
00078 const unsigned long epoch = stateInfo->version( m_label.num().value() );
00079 const unsigned long version = m_label.version().value();
00080 if ( epoch >= version )
00081 {
00082 delete msg;
00083 m_completed = true;
00084 #ifdef TIMING
00085 ActiveTimer.stop();
00086 #endif
00087 return true;
00088 }
00089
00090
00091 unsigned char* data = (unsigned char*)msg->buffer();
00092 int length = msg->length();
00093
00094 if ( length < 2 )
00095 {
00096 delete msg;
00097 #ifdef TIMING
00098 ActiveTimer.stop();
00099 #endif
00100 return false;
00101 }
00102
00103 if ( stateInfo->domain() != data[0] )
00104 {
00105 delete msg;
00106 #ifdef TIMING
00107 ActiveTimer.stop();
00108 #endif
00109 return false;
00110 }
00111 ++data;
00112 --length;
00113
00114 if ( ( kComputedMsg | SignatureMask ) != data[0] )
00115 {
00116 delete msg;
00117 #ifdef TIMING
00118 ActiveTimer.stop();
00119 #endif
00120 return false;
00121 }
00122 ++data;
00123 --length;
00124
00125 SignedComputedMsg* signedResponse = new SignedComputedMsg;
00126 if ( 0 == signedResponse )
00127 {
00128 delete msg;
00129 #ifdef TIMING
00130 ActiveTimer.stop();
00131 #endif
00132 return false;
00133 }
00134 if ( 0 == signedResponse->unmarshal( 0, &data, length ) )
00135 {
00136 delete msg;
00137 #ifdef TIMING
00138 ActiveTimer.stop();
00139 #endif
00140 return false;
00141 }
00142 delete msg;
00143
00144
00145 const ComputedMsg& response = signedResponse->message();
00146
00147 unsigned int computor = response.computor().value();
00148 if ( computor != server )
00149 {
00150 #ifdef TIMING
00151 ActiveTimer.stop();
00152 #endif
00153 return false;
00154 }
00155
00156 if ( response.shareLabel() != m_label )
00157 {
00158 #ifdef TIMING
00159 ActiveTimer.stop();
00160 #endif
00161 return false;
00162 }
00163
00164
00165 BIGNUM * digest = 0;
00166 try
00167 {
00168 digest = response.digest( serverState->hashFunc() );
00169 if ( 0 == digest )
00170 {
00171 throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00172 }
00173 if ( ! serverState->publicKey(server).verifySignature(
00174 signedResponse->signature(),
00175 digest ) )
00176 {
00177 throw CODEX_Server::SignatureVerificationFailedException( __FILE__ ,
00178 __LINE__ );
00179 }
00180 BN_free(digest);
00181 }
00182 catch ( ... )
00183 {
00184 if ( 0 != digest ) BN_free(digest);
00185 #ifdef TIMING
00186 ActiveTimer.stop();
00187 #endif
00188 return false;
00189 }
00190
00191
00192 m_evidence.append( signedResponse );
00193
00194 CODEX_Quorum::QuorumSystem* qs = serverState->quorumSystem();
00195 if ( 0 == qs )
00196 {
00197 #ifdef TIMING
00198 ActiveTimer.stop();
00199 #endif
00200 throw CODEX_Server::NoQuorumSystemException( __FILE__ , __LINE__ );
00201 }
00202
00203 if ( m_evidence.size() >= qs->quorumSize() )
00204 {
00205
00206 FinishedMsg fm( m_label.version(), m_label.id(), m_evidence );
00207
00208
00209 BIGNUM * digest = 0;
00210 CODEX_Ciphers::RSASignature* signature = 0;
00211 try
00212 {
00213 const CODEX_Ciphers::HashFunction& hashFunc = serverState->hashFunc();
00214 digest = fm.digest( hashFunc );
00215 const CODEX_Ciphers::RSAPrivateKey& key = serverState->privateKey();
00216 signature = key.sign( digest );
00217 BN_free(digest);
00218 digest = 0;
00219 if ( 0 == signature )
00220 {
00221 throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00222 }
00223 }
00224 catch ( ... )
00225 {
00226 if ( 0 != digest ) BN_free( digest );
00227 if ( 0 != signature ) delete signature;
00228 #ifdef TIMING
00229 ActiveTimer.stop();
00230 #endif
00231 throw;
00232 }
00233 SignedFinishedMsg signedFM( fm, *signature );
00234 delete signature;
00235
00236
00237 CODEX_Quorum::Message m;
00238 m.fill( serverState->hostNum() |
00239 CODEX_Server::ServerState::OutgoingMask );
00240 const unsigned char* seqNum = serverState->newSequenceNumber();
00241 m.fill( seqNum, CODEX_Server::ServerState::nMID );
00242 m.fill( stateInfo->domain() );
00243 m.fill( kFinishedMsg | SignatureMask );
00244 int length = signedFM.marshal(0);
00245 unsigned char* buffer = new unsigned char[length];
00246 unsigned char* pBuffer = buffer;
00247 signedFM.marshal(&pBuffer);
00248 m.fill( buffer, length );
00249 delete [] buffer;
00250
00251
00252 stateInfo->broadcast( m, 0 );
00253
00254 m_completed = true;
00255
00256 #ifdef TIMING
00257 ComputeTimer[m_label.num().value()].stop();
00258 #endif
00259
00260 }
00261
00262 #ifdef TIMING
00263 ActiveTimer.stop();
00264 #endif
00265 return true;
00266 }