Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

MessageVerifier.cc

00001 /*
00002  * Copyright 2003 Michael A. Marsh, Cornell University. All rights reserved.
00003  * This software is released under the modified BSD license.
00004  * See the file LICENSE in the top-level directory for details.
00005  */
00006 //
00007 // $Id: MessageVerifier.cc,v 1.3 2004/05/19 15:56:24 mmarsh Exp $
00008 //
00009 // $Log: MessageVerifier.cc,v $
00010 // Revision 1.3  2004/05/19 15:56:24  mmarsh
00011 // Added copyright and license statements.
00012 //
00013 // Revision 1.2  2003/11/04 22:31:45  mmarsh
00014 // *** empty log message ***
00015 //
00016 //
00017 
00018 #include "MessageVerifier.h"
00019 #include "StateInfo.h"
00020 #include "CODEX_Server/ServerResponseEvent.h"
00021 #include "FailureEvent.h"
00022 
00023 #include "timing.h"
00024 
00025 using namespace CODEX_APSS;
00026 
00027 MessageVerifier::MessageVerifier(
00028    CODEX_Events::DeadPileType& deadPile,
00029    CODEX_Events::QType& eventQueue,
00030    RoutedMessageHandler* destination,
00031    CODEX_Server::ServerResponseHandler* responder ) :
00032    CODEX_Events::Activity( deadPile, eventQueue ),
00033    m_destination( destination ),
00034    m_responder( responder )
00035 {
00036 }
00037 
00038 MessageVerifier::~MessageVerifier()
00039 {
00040 }
00041 
00045 bool
00046 MessageVerifier::handler( RoutedMessageEvent< SignedInitMsg >& event )
00047 {
00048 #ifdef TIMING
00049    ActiveTimer.start();
00050 #endif
00051    StateInfo* stateInfo = StateInfo::instance();
00052    CODEX_Server::ServerState* serverState =
00053       CODEX_Server::ServerState::instance();
00054    const SignedInitMsg& signedMessage = event.message();
00055    const InitMsg& message = signedMessage.message();
00056    unsigned int coordinator = message.coordinator().value();
00057 
00058    BIGNUM * digest = 0;
00059    try
00060    {
00061       const CODEX_Ciphers::RSAPublicKey& serverKey =
00062          serverState->publicKey( coordinator );
00063 
00064       // Check the signature on the message.
00065       digest = message.digest( serverState->hashFunc() );
00066       if ( ! serverKey.verifySignature( signedMessage.signature(), digest ) )
00067       {
00068          throw CODEX_Server::SignatureVerificationFailedException( __FILE__ ,
00069                                                                    __LINE__ );
00070       }
00071       BN_free( digest );  digest = 0;
00072 
00073       // Check the version.  Send a finished message if out-of-date.
00074       unsigned int num = message.label().num().value();
00075       unsigned int version = message.version().value();
00076       if ( version < stateInfo->version(num) )
00077       {
00078          stateInfo->sendFinished( num, coordinator );
00079          sendEvent( new FailureEvent( this, m_responder, event ),
00080                     event.source(), true ); // send a NACK
00081 #ifdef TIMING
00082          ActiveTimer.stop();
00083 #endif
00084          return true;
00085       }
00086 
00087       // Check for a previous init message from this coordinator:
00088       const InitRecord& priorInit = stateInfo->initRecord( num, coordinator );
00089       if ( priorInit.request().initialized() )
00090       {
00091          unsigned int pVersion = priorInit.request().version().value();
00092          if ( pVersion == version )
00093          {
00094             if ( priorInit.request().label() != message.label() )
00095             {
00096                // Inconsistent -- ignore
00097                //add logging here?
00098                sendEvent( 0, event.source(), true ); // send a NACK
00099 #ifdef TIMING
00100                ActiveTimer.stop();
00101 #endif
00102                return true;
00103             }
00104             // otherwise, look for cached response
00105             if ( priorInit.response().initialized() )
00106             {
00107                // send the cached response
00108                CODEX_Quorum::Message m;
00109                unsigned char server[CODEX_Server::ServerState::nSID];
00110                memcpy( server,
00111                        event.server(),
00112                        CODEX_Server::ServerState::nSID );
00113                // Make sure the "outgoing" mask isn't set.
00114                server[0] &= ~(CODEX_Server::ServerState::OutgoingMask);
00115                int serverNum = server[0];
00116 
00117                // Fill message headers.
00118                m.fill( server, CODEX_Server::ServerState::nSID );
00119                m.fill( event.seqNum(), CODEX_Server::ServerState::nMID );
00120                m.fill( stateInfo->domain() );
00121                m.fill( kContributeMsg | SignatureMask );
00122                const SignedContributeMsg& cm = priorInit.response();
00123                int length = cm.marshal(0);
00124                unsigned char* buffer = new unsigned char[length];
00125                unsigned char* pBuffer = buffer;
00126                cm.marshal(&pBuffer);
00127                m.fill( buffer, length );
00128                delete [] buffer;
00129 
00130                sendEvent(
00131                   new CODEX_Server::ServerResponseEvent( this,
00132                                                          m_responder,
00133                                                          m,
00134                                                          serverNum ),
00135                   event.source() );
00136 #ifdef TIMING
00137                ActiveTimer.stop();
00138 #endif
00139                return true;
00140             }
00141             else
00142             {
00143                // We're still processing the request
00144                sendEvent( 0, event.source() ); // ACK
00145 #ifdef TIMING
00146                ActiveTimer.stop();
00147 #endif
00148                return true;
00149             }
00150          }
00151       }
00152 
00153       // Make sure the new version is consistent with the label
00154       if ( ( message.version().value() -
00155              message.label().version().value() ) != 1 )
00156       {
00157          sendEvent( 0, event.source(), true ); // send a NACK
00158 #ifdef TIMING
00159          ActiveTimer.stop();
00160 #endif
00161          return true;
00162       }
00163 
00164       // The message is good -- store and re-route it to our successor.
00165       stateInfo->addInitMsg( signedMessage );
00166       event.reRoute( m_destination );
00167 #ifdef TIMING
00168       InitActTimer[num].start();
00169       ActiveTimer.stop();
00170 #endif
00171       return false;
00172    }
00173    catch ( ... )
00174    {
00175       if ( 0 != digest ) BN_free( digest );
00176       sendEvent( 0, event.source(), true ); // send a NACK
00177 #ifdef TIMING
00178       ActiveTimer.stop();
00179 #endif
00180       return true;
00181    }
00182 }
00183 
00187 bool
00188 MessageVerifier::handler( RoutedMessageEvent< SignedEstablishMsg >& event )
00189 {
00190 #ifdef TIMING
00191    ActiveTimer.start();
00192 #endif
00193    StateInfo* stateInfo = StateInfo::instance();
00194    CODEX_Server::ServerState* serverState =
00195       CODEX_Server::ServerState::instance();
00196    const SignedEstablishMsg& signedMessage = event.message();
00197    const EstablishMsg& message = signedMessage.message();
00198    unsigned int establisher = message.establisher().value();
00199 
00200    BIGNUM * digest = 0;
00201    try
00202    {
00203       const CODEX_Ciphers::RSAPublicKey& serverKey =
00204          serverState->publicKey( establisher );
00205 
00206       const CODEX_Ciphers::HashFunction& hashFunc = serverState->hashFunc();
00207 
00208       // Check the signature on the message.
00209       digest = message.digest( hashFunc );
00210       if ( ! serverKey.verifySignature( signedMessage.signature(), digest ) )
00211       {
00212          throw CODEX_Server::SignatureVerificationFailedException( __FILE__ ,
00213                                                                    __LINE__ );
00214       }
00215       BN_free( digest );  digest = 0;
00216 
00217       // Check the version.  Send a finished message if out-of-date.
00218       unsigned int num = message.sublabel().label().num().value();
00219       unsigned int version = message.version().value();
00220       if ( version < stateInfo->version(num) )
00221       {
00222          stateInfo->sendFinished( num, establisher );
00223          sendEvent( new FailureEvent( this, m_responder, event ),
00224                     event.source(), true ); // send a NACK
00225 #ifdef TIMING
00226          ActiveTimer.stop();
00227 #endif
00228          return true;
00229       }
00230 
00231       // Check for a previous establish message from this server:
00232       const EstablishRecord& priorEst =
00233          stateInfo->establishRecord( num,
00234                                      establisher,
00235                                      message.sublabel().id().value(),
00236                                      message.sublabel().label() );
00237       if ( priorEst.request().initialized() )
00238       {
00239          unsigned int pVersion = priorEst.request().version().value();
00240          if ( pVersion == version )
00241          {
00242             if ( priorEst.request().sublabel() != message.sublabel() )
00243             {
00244                // Inconsistent -- ignore
00245                //add logging here?
00246                sendEvent( 0, event.source(), true ); // send a NACK
00247 #ifdef TIMING
00248                ActiveTimer.stop();
00249 #endif
00250                return true;
00251             }
00252             // otherwise, look for cached response
00253             if ( priorEst.response().initialized() )
00254             {
00255                // send the cached response
00256                CODEX_Quorum::Message m;
00257                unsigned char server[CODEX_Server::ServerState::nSID];
00258                memcpy( server,
00259                        event.server(),
00260                        CODEX_Server::ServerState::nSID );
00261                // Make sure the "outgoing" mask isn't set.
00262                server[0] &= ~(CODEX_Server::ServerState::OutgoingMask);
00263                int serverNum = server[0];
00264 
00265                // Fill message headers.
00266                m.fill( server, CODEX_Server::ServerState::nSID );
00267                m.fill( event.seqNum(), CODEX_Server::ServerState::nMID );
00268                m.fill( stateInfo->domain() );
00269                m.fill( kEstablishedMsg | SignatureMask );
00270                const SignedEstablishedMsg& em = priorEst.response();
00271                int length = em.marshal(0);
00272                unsigned char* buffer = new unsigned char[length];
00273                unsigned char* pBuffer = buffer;
00274                em.marshal(&pBuffer);
00275                m.fill( buffer, length );
00276                delete [] buffer;
00277 
00278                sendEvent(
00279                   new CODEX_Server::ServerResponseEvent( this,
00280                                                          m_responder,
00281                                                          m,
00282                                                          serverNum ),
00283                   event.source() );
00284 #ifdef TIMING
00285                ActiveTimer.stop();
00286 #endif
00287                return true;
00288             }
00289             else
00290             {
00291                // We're still processing the request
00292                sendEvent( 0, event.source() ); // ACK
00293 #ifdef TIMING
00294                ActiveTimer.stop();
00295 #endif
00296                return true;
00297             }
00298          }
00299       }
00300 
00301       OneWay oneWay( stateInfo->witness(num).args() );
00302 
00303       // Check the validity of the label
00304       if ( ! message.sublabel().label().verify(
00305          stateInfo->witness(num).witness(), oneWay ) )
00306       {
00307          sendEvent( 0, event.source(), true ); // send a NACK
00308 #ifdef TIMING
00309          ActiveTimer.stop();
00310 #endif
00311          return true;
00312       }
00313 
00314       // Check the validity of the sublabel
00315       if ( ! message.sublabel().verify( oneWay ) )
00316       {
00317          sendEvent( 0, event.source(), true ); // send a NACK
00318 #ifdef TIMING
00319          ActiveTimer.stop();
00320 #endif
00321          return true;
00322       }
00323 
00324       // Check the validity of the subshares
00325       if ( ! message.sublabel().check(message.shares(),oneWay) )
00326       {
00327          sendEvent( 0, event.source(), true ); // send a NACK
00328 #ifdef TIMING
00329          ActiveTimer.stop();
00330 #endif
00331          return true;
00332       }
00333 
00334       // The message is good -- store and re-route it to our successor.
00335       stateInfo->addEstablishMsg( signedMessage );
00336       event.reRoute( m_destination );
00337 #ifdef TIMING
00338       ActiveTimer.stop();
00339 #endif
00340       return false;
00341    }
00342    catch ( ... )
00343    {
00344       if ( 0 != digest ) BN_free( digest );
00345       sendEvent( 0, event.source(), true ); // send a NACK
00346 #ifdef TIMING
00347       ActiveTimer.stop();
00348 #endif
00349       return true;
00350    }
00351 }
00352 
00356 bool
00357 MessageVerifier::handler( RoutedMessageEvent< SignedComputeMsg >& event )
00358 {
00359 #ifdef TIMING
00360    ActiveTimer.start();
00361 #endif
00362    StateInfo* stateInfo = StateInfo::instance();
00363    CODEX_Server::ServerState* serverState =
00364       CODEX_Server::ServerState::instance();
00365    const SignedComputeMsg& signedMessage = event.message();
00366    const ComputeMsg& message = signedMessage.message();
00367    unsigned int coordinator = message.coordinator().value();
00368 
00369    BIGNUM * digest = 0;
00370    try
00371    {
00372       const CODEX_Ciphers::RSAPublicKey& serverKey =
00373          serverState->publicKey( coordinator );
00374 
00375       // Check the signature on the message.
00376       digest = message.digest( serverState->hashFunc() );
00377       if ( ! serverKey.verifySignature( signedMessage.signature(), digest ) )
00378       {
00379          throw CODEX_Server::SignatureVerificationFailedException( __FILE__ ,
00380                                                                    __LINE__ );
00381       }
00382       BN_free( digest );  digest = 0;
00383 
00384       // Check the version.  Send a finished message if out-of-date.
00385       unsigned int num = message.subshareLabel(0).label().num().value();
00386       unsigned int version =
00387          message.subshareLabel(0).label().version().value();
00388       if ( version < stateInfo->version(num) )
00389       {
00390          stateInfo->sendFinished( num, coordinator );
00391          sendEvent( new FailureEvent( this, m_responder, event ),
00392                     event.source(), true ); // send a NACK
00393 #ifdef TIMING
00394          ActiveTimer.stop();
00395 #endif
00396          return true;
00397       }
00398 
00399       // Check for a previous compute message from this coordinator:
00400       const ComputeRecord& priorComp = stateInfo->computeRecord( num,
00401                                                                  coordinator );
00402       if ( priorComp.request().initialized() )
00403       {
00404          unsigned int pVersion =
00405             priorComp.request().subshareLabel(0).label().version().value();
00406          if ( pVersion == version )
00407          {
00408             for ( unsigned int i = 0 ; i < ComputeMsg::NumShares ; ++i )
00409             {
00410                if ( priorComp.request().subshareLabel(i) !=
00411                     message.subshareLabel(i) )
00412                {
00413                   // Inconsistent -- ignore
00414                   //add logging here?
00415                   sendEvent( 0, event.source(), true ); // send a NACK
00416 #ifdef TIMING
00417                   ActiveTimer.stop();
00418 #endif
00419                   return true;
00420                }
00421             }
00422             // If consistent, look for cached response
00423             if ( priorComp.response().initialized() )
00424             {
00425                // send the cached response
00426                CODEX_Quorum::Message m;
00427                unsigned char server[CODEX_Server::ServerState::nSID];
00428                memcpy( server,
00429                        event.server(),
00430                        CODEX_Server::ServerState::nSID );
00431                // Make sure the "outgoing" mask isn't set.
00432                server[0] &= ~(CODEX_Server::ServerState::OutgoingMask);
00433                int serverNum = server[0];
00434 
00435                // Fill message headers.
00436                m.fill( server, CODEX_Server::ServerState::nSID );
00437                m.fill( event.seqNum(), CODEX_Server::ServerState::nMID );
00438                m.fill( stateInfo->domain() );
00439                m.fill( kComputedMsg | SignatureMask );
00440                const SignedComputedMsg& cm = priorComp.response();
00441                int length = cm.marshal(0);
00442                unsigned char* buffer = new unsigned char[length];
00443                unsigned char* pBuffer = buffer;
00444                cm.marshal(&pBuffer);
00445                m.fill( buffer, length );
00446                delete [] buffer;
00447 
00448                sendEvent(
00449                   new CODEX_Server::ServerResponseEvent( this,
00450                                                          m_responder,
00451                                                          m,
00452                                                          serverNum ),
00453                   event.source() );
00454 #ifdef TIMING
00455                ActiveTimer.stop();
00456 #endif
00457                return true;
00458             }
00459             else
00460             {
00461                // We're still processing the request
00462                sendEvent( 0, event.source() ); // ACK
00463 #ifdef TIMING
00464                ActiveTimer.stop();
00465 #endif
00466                return true;
00467             }
00468          }
00469       }
00470 
00471       // Verify that the form of the message is valid.
00472       for ( unsigned int i = 0 ; i < ShareType::NumShares ; ++i )
00473       {
00474          unsigned int id = message.subshareLabel(i).id().value();
00475          if ( id != i )
00476          {
00477             sendEvent( 0, event.source(), true ); // send a NACK
00478 #ifdef TIMING
00479             ActiveTimer.stop();
00480 #endif
00481             return true;
00482          }
00483       }
00484 
00485       // The message is good -- store and re-route it to our successor.
00486       stateInfo->addComputeMsg( signedMessage );
00487       event.reRoute( m_destination );
00488 #ifdef TIMING
00489       ActiveTimer.stop();
00490 #endif
00491       return false;
00492    }
00493    catch ( ... )
00494    {
00495       if ( 0 != digest ) BN_free( digest );
00496       sendEvent( 0, event.source(), true ); // send a NACK
00497 #ifdef TIMING
00498       ActiveTimer.stop();
00499 #endif
00500       return true;
00501    }
00502 }
00503 
00504 bool
00505 MessageVerifier::handler( RoutedMessageEvent< SignedRecoverMsg >& event )
00506 {
00507 #ifdef TIMING
00508    ActiveTimer.start();
00509 #endif
00510    StateInfo* stateInfo = StateInfo::instance();
00511    CODEX_Server::ServerState* serverState =
00512       CODEX_Server::ServerState::instance();
00513    const SignedRecoverMsg& signedMessage = event.message();
00514    const RecoverMsg& message = signedMessage.message();
00515    unsigned int requester = message.requester().value();
00516 
00517    BIGNUM * digest = 0;
00518    try
00519    {
00520       const CODEX_Ciphers::RSAPublicKey& serverKey =
00521          serverState->publicKey( requester );
00522 
00523       // Check the signature on the message.
00524       digest = message.digest( serverState->hashFunc() );
00525       if ( ! serverKey.verifySignature( signedMessage.signature(), digest ) )
00526       {
00527          throw CODEX_Server::SignatureVerificationFailedException( __FILE__ ,
00528                                                                    __LINE__ );
00529       }
00530       BN_free( digest );  digest = 0;
00531 
00532       // Check the version.  Send a finished message if out-of-date.
00533       unsigned int num = message.sublabel().label().num().value();
00534       unsigned int version = message.version().value();
00535       if ( version < stateInfo->version(num) )
00536       {
00537          stateInfo->sendFinished( num, requester );
00538          sendEvent( new FailureEvent( this, m_responder, event ),
00539                     event.source(), true ); // send a NACK
00540 #ifdef TIMING
00541          ActiveTimer.stop();
00542 #endif
00543          return true;
00544       }
00545 
00546       // The message is good -- re-route it to our successor.
00547       event.reRoute( m_destination );
00548 #ifdef TIMING
00549       ActiveTimer.stop();
00550 #endif
00551       return false;
00552    }
00553    catch ( ... )
00554    {
00555       if ( 0 != digest ) BN_free( digest );
00556       sendEvent( 0, event.source(), true ); // send a NACK
00557 #ifdef TIMING
00558       ActiveTimer.stop();
00559 #endif
00560       return true;
00561    }
00562 }
00563 
00564 bool
00565 MessageVerifier::handler( RoutedMessageEvent< SignedFinishedMsg >& event )
00566 {
00567 #ifdef TIMING
00568    ActiveTimer.start();
00569 #endif
00570    StateInfo* stateInfo = StateInfo::instance();
00571    CODEX_Server::ServerState* serverState =
00572       CODEX_Server::ServerState::instance();
00573    const SignedFinishedMsg& signedMessage = event.message();
00574    const FinishedMsg& message = signedMessage.message();
00575    unsigned int coordinator = message.coordinator().value();
00576 
00577    BIGNUM * digest = 0;
00578    try
00579    {
00580       const CODEX_Ciphers::RSAPublicKey& serverKey =
00581          serverState->publicKey( coordinator );
00582 
00583       // Check the signature on the message.
00584       digest = message.digest( serverState->hashFunc() );
00585       if ( ! serverKey.verifySignature( signedMessage.signature(), digest ) )
00586       {
00587          throw CODEX_Server::SignatureVerificationFailedException( __FILE__ ,
00588                                                                    __LINE__ );
00589       }
00590       BN_free( digest );  digest = 0;
00591 
00592       // Make sure there is sufficient evidence attached.
00593       CODEX_Quorum::QuorumSystem* qs = serverState->quorumSystem();
00594       if ( 0 == qs )
00595       {
00596          throw CODEX_Server::NoQuorumSystemException( __FILE__ , __LINE__ );
00597       }
00598       unsigned int quorumSize = qs->quorumSize();
00599       if ( message.evidence().size() < quorumSize )
00600       {
00601          sendEvent( 0, event.source(), true ); // send a NACK
00602 #ifdef TIMING
00603          ActiveTimer.stop();
00604 #endif
00605          return true;
00606       }
00607 
00608       // Check the version.  Store the finished message if it's in the current
00609       // or new epoch, unless it's a duplicate.
00610       unsigned int num =
00611          message.evidence().element(0)->message().shareLabel().num().value();
00612       unsigned int version = message.version().value();
00613       if ( version < stateInfo->version(num) )
00614       {
00615          sendEvent( new FailureEvent( this, m_responder, event ),
00616                     event.source(), true ); // send a NACK
00617 #ifdef TIMING
00618          ActiveTimer.stop();
00619 #endif
00620          return true;
00621       }
00622       unsigned int coord = message.coordinator().value();
00623       const SignedFinishedMsg& fm = stateInfo->finishedMsg( num, coord );
00624       if ( fm.message().initialized() )
00625       {
00626          unsigned int pVers = fm.message().version().value();
00627          if ( version <= pVers )
00628          {
00629             // ignore
00630             sendEvent( 0, event.source() );
00631 #ifdef TIMING
00632             ActiveTimer.stop();
00633 #endif
00634             return true;
00635          }
00636       }
00637 
00638       // Verify that the evidence supports the message.
00639       ComputedArray::ArrayItr itr = message.evidence().begin();
00640       ComputedArray::ArrayItr end = message.evidence().end();
00641       for ( ; itr != end ; ++itr )
00642       {
00643          const ComputedMsg& cm = (*itr)->message();
00644          // Check that the coordinator matches the coordinator for the
00645          // computed message.
00646          unsigned int eCoord = cm.shareLabel().id().value();
00647          if ( eCoord != coordinator )
00648          {
00649             sendEvent( 0, event.source(), true ); // send a NACK
00650 #ifdef TIMING
00651             ActiveTimer.stop();
00652 #endif
00653             return true;
00654          }
00655 
00656          // Check that the version matches the version for the computed
00657          // messages.
00658          unsigned int eVers = cm.shareLabel().version().value();
00659          if ( eVers != version )
00660          {
00661             sendEvent( 0, event.source(), true ); // send a NACK
00662 #ifdef TIMING
00663             ActiveTimer.stop();
00664 #endif
00665             return true;
00666          }
00667 
00668          // Check the signature on the computed message.
00669          unsigned int s = cm.computor().value();
00670          digest = cm.digest( serverState->hashFunc() );
00671          if ( ! serverState->publicKey(s).verifySignature( (*itr)->signature(),
00672                                                            digest ) )
00673          {
00674             throw
00675                CODEX_Server::SignatureVerificationFailedException( __FILE__ ,
00676                                                                    __LINE__ );
00677          }
00678          BN_free( digest );  digest = 0;
00679       }
00680 
00681 #ifdef TIMING
00682       // We have to stop the timer slightly early, since addFinishedMsg()
00683       // might move us into the next epoch and print the timing statistics.
00684       ActiveTimer.stop();
00685 #endif
00686       // The message is good -- store it.
00687       stateInfo->addFinishedMsg( signedMessage );
00688       return false;
00689    }
00690    catch ( ... )
00691    {
00692       if ( 0 != digest ) BN_free( digest );
00693       sendEvent( 0, event.source(), true ); // send a NACK
00694 #ifdef TIMING
00695       ActiveTimer.stop();
00696 #endif
00697       return true;
00698    }
00699 }

Generated on Fri May 6 17:40:51 2005 for COrnell Data EXchange (CODEX) by  doxygen 1.4.1