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

SignWriteCallback.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: SignWriteCallback.cc,v 1.3 2004/05/19 15:56:53 mmarsh Exp $
00008 //
00009 // $Log: SignWriteCallback.cc,v $
00010 // Revision 1.3  2004/05/19 15:56:53  mmarsh
00011 // *** empty log message ***
00012 //
00013 // Revision 1.2  2003/11/04 22:31:49  mmarsh
00014 // *** empty log message ***
00015 //
00016 //
00017 
00018 #include "SignWriteCallback.h"
00019 #include "CODEX_Events/Event.h"
00020 #include "CODEX_Server/ServerExceptions.h"
00021 #include "CODEX_Server/ServerState.h"
00022 #include "StateInfo.h"
00023 #include "CODEX_Client/Message.h"
00024 #include "CODEX_Server/SignRequestEvent.h"
00025 #include "ClientDelegation.h"
00026 #include "CODEX_Server/ShareLabelChallenge.h"
00027 
00028 #include "timing.h"
00029 
00030 using namespace CODEX_KeyService;
00031 
00032 SignWriteCallback::SignWriteCallback(
00033    CODEX_Events::DeadPileType& deadPile,
00034    CODEX_Events::QType& eventQueue,
00035    ClientResponseHandler* destination,
00036    const RequestType& request,
00037    const unsigned char* seqNum,
00038    CODEX_Server::SignRequestHandler* reqHandler ) :
00039    ResponseCallback( seqNum ),
00040    CODEX_Events::Activity( deadPile, eventQueue ),
00041    m_destination( destination ),
00042    m_request( request ),
00043    m_complete( false ),
00044    m_reqHandler( reqHandler )
00045 {
00046    m_digest = m_request.response().digest(
00047       CODEX_Server::ServerState::instance()->hashFunc() );
00048 }
00049 
00050 SignWriteCallback::~SignWriteCallback()
00051 {
00052    if ( NULL != m_digest ) BN_free( m_digest );
00053    while ( m_signatures.size() )
00054    {
00055       delete m_signatures.back();
00056       m_signatures.pop_back();
00057    }
00058    ChallengeVector::iterator vItr = m_challenges.begin();
00059    ChallengeVector::iterator vEnd = m_challenges.end();
00060    for ( ; vItr != vEnd ; ++vItr )
00061    {
00062       delete *vItr;
00063    }
00064 }
00065 
00067 bool
00068 SignWriteCallback::operator()( unsigned int server,
00069                                CODEX_Quorum::Message* msg )
00070 {
00071    if ( NULL == msg )
00072    {
00073       return false;
00074    }
00075 
00076    if ( m_complete )
00077    {
00078       delete msg;
00079       return true;
00080    }
00081 
00082 #ifdef TIMING
00083    ActiveTimer.start();
00084 #endif
00085 
00086    CODEX_Server::ServerState* serverState =
00087       CODEX_Server::ServerState::instance();
00088    if ( NULL == serverState )
00089    {
00090       delete msg;
00091 #ifdef TIMING
00092       ActiveTimer.stop();
00093 #endif
00094       return false;
00095    }
00096 
00097    StateInfo* stateInfo = StateInfo::instance();
00098    if ( NULL == stateInfo )
00099    {
00100       delete msg;
00101 #ifdef TIMING
00102       ActiveTimer.stop();
00103 #endif
00104       return false;
00105    }
00106 
00107    // Sanity check -- is our destination still valid?
00108    if ( NULL == stateInfo->getActFromSeqNum( seqNum() ) )
00109    {
00110       delete msg;
00111 #ifdef TIMING
00112       ActiveTimer.stop();
00113 #endif
00114       return false;
00115    }
00116 
00117    CODEX_Quorum::QuorumSystem* qs = serverState->quorumSystem();
00118    if ( NULL == qs )
00119    {
00120       delete msg;
00121 #ifdef TIMING
00122       ActiveTimer.stop();
00123 #endif
00124       throw CODEX_Server::NoQuorumSystemException( __FILE__ , __LINE__ );
00125    }
00126 
00127    unsigned char* data = (unsigned char*)msg->buffer();
00128    int length = msg->length();
00129 
00130    if ( length < 2 )
00131    {
00132       delete msg;
00133 #ifdef TIMING
00134       ActiveTimer.stop();
00135 #endif
00136       return false;
00137    }
00138 
00139    // Check the message type.
00140    if ( stateInfo->delegationDomain() != data[0] )
00141    {
00142       delete msg;
00143 #ifdef TIMING
00144       ActiveTimer.stop();
00145 #endif
00146       return false;
00147    }
00148    ++data;
00149    --length;
00150 
00151    // Test a special condition
00152    if ( ClientDelegation::kBadShareLabel == data[0] )
00153    {
00154       cerr << __FILE__ << ", line " << __LINE__ << ":\n"
00155            << "   kBadShareLabel returned" << endl;
00156       ++data;
00157       --length;
00158       // We need to re-send the request with the new label, but only if
00159       // the label returned is actually valid.
00160       CODEX_Server::ServerState::LSType::LabelType label;
00161       if ( NULL == label.unmarshal( NULL, &data, length ) )
00162       {
00163          // The response is no good.
00164          delete msg;
00165 #ifdef TIMING
00166          ActiveTimer.stop();
00167 #endif
00168          return false;
00169       }
00170       RequestType newReq( m_request.response(),
00171                           m_request.evidence(),
00172                           label );
00173       const unsigned char* newSeqNum = serverState->newSequenceNumber();
00174       stateInfo->registerSequenceNumber( newSeqNum, m_destination );
00175       SignWriteCallback* cb = new SignWriteCallback( m_deadPile,
00176                                                      m_queue,
00177                                                      m_destination,
00178                                                      newReq,
00179                                                      newSeqNum,
00180                                                      m_reqHandler );
00181 
00182       CODEX_Quorum::Message message;
00183       unsigned char self = serverState->hostNum();
00184       message.fill( self | CODEX_Server::ServerState::OutgoingMask );
00185       message.fill( newSeqNum, CODEX_Server::ServerState::nMID );
00186       message.fill( stateInfo->delegationDomain() );
00187       message.fill( ClientDelegation::kRequestSignature );
00188       message.fill( CODEX_Client::kKeyStoredMsg );
00189       int length = newReq.marshal(0);
00190       unsigned char* buffer = new unsigned char[length];
00191       unsigned char* pBuffer = buffer;
00192       newReq.marshal(&pBuffer);
00193       message.fill( buffer, length );
00194       delete [] buffer;
00195 
00196       // Create the outgoing event.
00197       CODEX_Server::SignRequestEvent* outEvent =
00198          new CODEX_Server::SignRequestEvent( this,
00199                                              m_reqHandler,
00200                                              message,
00201                                              cb );
00202       CODEX_Server::ShareLabelChallenge* slc =
00203          new CODEX_Server::ShareLabelChallenge( label, server, cb, outEvent );
00204       m_challenges.push_back( slc );
00205       if ( m_challenges.size() > qs->faultsTolerated() )
00206       {
00207          // register challenges
00208          ChallengeVector::iterator vItr = m_challenges.begin();
00209          ChallengeVector::iterator vEnd = m_challenges.end();
00210          for ( ; vItr != vEnd ; ++vItr )
00211          {
00212             serverState->addChallenge( seqNum() , *vItr );
00213          }
00214          m_challenges.clear();
00215          // No progress will be made on this request.
00216          m_complete = true;
00217       }
00218       delete msg;
00219 #ifdef TIMING
00220       ActiveTimer.stop();
00221 #endif
00222       return true;
00223    }
00224 
00225    if ( ClientDelegation::kAcceptSignatureRequest != data[0] )
00226    {
00227       delete msg;
00228 #ifdef TIMING
00229       ActiveTimer.stop();
00230 #endif
00231       return false;
00232    }
00233    ++data;
00234    --length;
00235 
00236    // Check that it unmarshals.
00237    typedef CODEX_Server::ServerState::ShareType ShareType;
00238    ShareType* signatures = new ShareType;
00239    if ( NULL == signatures->unmarshal( NULL, &data, length ) )
00240    {
00241       delete msg;
00242 #ifdef TIMING
00243       ActiveTimer.stop();
00244 #endif
00245       return false;
00246    }
00247    delete msg;
00248    m_signatures.push_back( signatures );
00249 
00250    // See if we have enough responses to create the threshold signature.
00251    typedef CODEX_Client::SignedKeyStoredMsg MsgType;
00252 
00253    const CODEX_Server::ServerState::ThresholdRSAType& thresholdRSA =
00254       serverState->thresholdRSA();
00255 
00256    // optimistic case
00257    if ( m_signatures.size() > CODEX_Server::ServerState::nFaults )
00258    {
00259       CODEX_Server::ServerState::ShareSetType partials;
00260       SignatureArray::const_iterator itr = m_signatures.begin();
00261       SignatureArray::const_iterator end = m_signatures.end();
00262       for ( ; itr != end ; ++itr )
00263       {
00264          partials.addShare( **itr );
00265       }
00266       // Get the threshold signature, verify it, and if OK respond.
00267       BIGNUM * tsig = thresholdRSA.threshold( partials );
00268       if ( NULL != tsig )
00269       {
00270          try
00271          {
00272             CODEX_Ciphers::RSASignature sig(tsig);
00273             const CODEX_Ciphers::RSAPublicKey& serviceKey =
00274                serverState->serviceKey();
00275             if ( ! serviceKey.initialized() )
00276             {
00277                throw CODEX_Server::PublicKeyNotFoundException( __FILE__ ,
00278                                                                __LINE__ );
00279             }
00280             if ( serviceKey.verifySignature( sig, m_digest ) )
00281             {
00282                ClientResponseEvent< MsgType >* event = new
00283                   ClientResponseEvent< MsgType >(
00284                      this,
00285                      m_destination,
00286                      MsgType(m_request.response(), sig) );
00287                sendEvent( event, 0 ); // no need to acknowledge
00288                serverState->removeChallenge( seqNum() );
00289                m_complete = true;
00290                // We're done.
00291 #ifdef TIMING
00292                ActiveTimer.stop();
00293 #endif
00294                return true;
00295             }
00296          }
00297          catch ( ... )
00298          {
00299          }
00300       }
00301    }
00302 
00303    // Wait for a full quorum and try all possible combinations until one
00304    // works.
00305    if ( m_signatures.size() >= qs->quorumSize() )
00306    {
00307       BIGNUM* tsig = serverState->thresholdOperation( m_signatures, m_digest );
00308       if ( NULL != tsig )
00309       {
00310          CODEX_Ciphers::RSASignature sig(tsig);
00311          ClientResponseEvent< MsgType >* event = new
00312             ClientResponseEvent< MsgType >(
00313                this,
00314                m_destination,
00315                MsgType(m_request.response(), sig) );
00316          sendEvent( event, 0 ); // no need to acknowledge
00317          serverState->removeChallenge( seqNum() );
00318          m_complete = true;
00319       }
00320       else
00321       {
00322          // There was a problem
00323          sendEvent( new CODEX_Events::CloseEvent( this, m_destination ), 0 );
00324       }
00325    }
00326 #ifdef TIMING
00327    ActiveTimer.stop();
00328 #endif
00329    return true;
00330 }

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