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

DelegateResponseVerifier.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: DelegateResponseVerifier.cc,v 1.4 2004/05/19 15:56:52 mmarsh Exp $
00008 //
00009 // $Log: DelegateResponseVerifier.cc,v $
00010 // Revision 1.4  2004/05/19 15:56:52  mmarsh
00011 // *** empty log message ***
00012 //
00013 // Revision 1.3  2003/11/04 22:31:49  mmarsh
00014 // *** empty log message ***
00015 //
00016 //
00017 
00018 #include "DelegateResponseVerifier.h"
00019 #include "CODEX_Server/ServerResponseEvent.h"
00020 #include "CODEX_Server/ServerState.h"
00021 #include "StateInfo.h"
00022 #include "ClientDelegation.h"
00023 #include "VerifiableBlindKeyMsg.h"
00024 
00025 #include "CODEX_Server/ServerExceptions.h"
00026 #include "Exceptions.h"
00027 
00028 #include "timing.h"
00029 
00030 using namespace CODEX_KeyService;
00031 
00032 DelegateResponseVerifier::DelegateResponseVerifier(
00033    CODEX_Events::DeadPileType& deadPile,
00034    CODEX_Events::QType& eventQueue,
00035    SupportedClientResponseHandler* destination ):
00036    CODEX_Events::Activity( deadPile, eventQueue ),
00037    m_destination( destination )
00038 {
00039 }
00040 
00041 DelegateResponseVerifier::~DelegateResponseVerifier()
00042 {
00043 }
00044 
00045 bool
00046 DelegateResponseVerifier::handler(
00047    SupportedClientResponseEvent< BoundNameMsg, SignedCreateKeyMsg >& event )
00048 {
00049 #ifdef TIMING
00050    ActiveTimer.start();
00051 #endif
00052    const BoundNameMsg& response = event.message().response();
00053    const CreateKeyMsg& request = response.request().message();
00054 
00055    // "sRequest" will be digested and checked against the signatures
00056    // provided as evidence.  Consequently, we don't need to test it,
00057    // since correct servers would not have signed a malformed request.
00058    const SignedCreateKeyMsg& sRequest = event.message().request();
00059 
00060    if ( response.name().value() != request.name().value() )
00061    {
00062 #ifdef TIMING
00063       ActiveTimer.stop();
00064 #endif
00065       return true;
00066    }
00067    if ( request.name().value() != sRequest.message().name().value() )
00068    {
00069 #ifdef TIMING
00070       ActiveTimer.stop();
00071 #endif
00072       return true;
00073    }
00074 
00075    // The signatures must match, or the response is not valid.
00076    if ( 0 != BN_cmp( response.request().signature().value(),
00077                      sRequest.signature().value() ) )
00078    {
00079 #ifdef TIMING
00080       ActiveTimer.stop();
00081 #endif
00082       return true;
00083    }
00084 
00085    // Get the server state info.
00086    CODEX_Server::ServerState* serverState =
00087       CODEX_Server::ServerState::instance();
00088    if ( 0 == serverState )
00089    {
00090 #ifdef TIMING
00091       ActiveTimer.stop();
00092 #endif
00093       return true;
00094    }
00095 
00096    StateInfo* stateInfo = StateInfo::instance();
00097    if ( 0 == stateInfo )
00098    {
00099 #ifdef TIMING
00100       ActiveTimer.stop();
00101 #endif
00102       return true;
00103    }
00104 
00105    // The signature on the request that is contained within the response
00106    // must be correct.  This ensures that the binding contains valid
00107    // information.
00108    CODEX_Ciphers::RSAPublicKey ownerKey( request.owner().value() );
00109    BIGNUM * digest = 0;
00110    try
00111    {
00112       digest = request.digest( serverState->hashFunc() );
00113       bool sigOK = ownerKey.verifySignature( response.request().signature(),
00114                                              digest );
00115       BN_free(digest);
00116       digest = 0;
00117       if ( ! sigOK )
00118       {
00119 #ifdef TIMING
00120          ActiveTimer.stop();
00121 #endif
00122          return true;
00123       }
00124    }
00125    catch ( ... )
00126    {
00127       if ( 0 != digest ) BN_free(digest);
00128 #ifdef TIMING
00129       ActiveTimer.stop();
00130 #endif
00131       throw;
00132    }
00133 
00134    // Get the quorum system.
00135    CODEX_Quorum::QuorumSystem* qs = serverState->quorumSystem();
00136    if ( 0 == qs )
00137    {
00138 #ifdef TIMING
00139       ActiveTimer.stop();
00140 #endif
00141       return true;
00142    }
00143 
00144    // Get a digest of the request.
00145    try
00146    {
00147       digest = sRequest.digest( serverState->hashFunc() );
00148    }
00149    catch ( ... )
00150    {
00151       if ( 0 != digest ) BN_free(digest);
00152 #ifdef TIMING
00153       ActiveTimer.stop();
00154 #endif
00155       return true;
00156    }
00157    if ( 0 == digest )
00158    {
00159 #ifdef TIMING
00160       ActiveTimer.stop();
00161 #endif
00162       return true;
00163    }
00164 
00165    bool retVal =
00166       process( digest, event.message().evidence(), qs->quorumSize() );
00167 
00168    BN_free(digest);
00169 
00170    if ( retVal )
00171    {
00172       // The key name should be bound here if it isn't already.  If another
00173       // request bound the name, we should replace it, since the previous
00174       // binding was not accepted by the quorum system.
00175       const KeyInfo* keyInfo =
00176          stateInfo->getKeyInfo( response.name().value() );
00177       if ( 0 == keyInfo )
00178       {
00179          if ( ! stateInfo->addKeyName( response.name().value(), response ) )
00180          {
00181 #ifdef TIMING
00182             ActiveTimer.stop();
00183 #endif
00184             throw KeyExistsException( __FILE__ , __LINE__ );
00185          }
00186       }
00187       else
00188       {
00189          // The simplest thing to do is just replace, whether the bindings
00190          // are different or not.
00191          if ( ! stateInfo->replaceKeyBinding(
00192             response.name().value(),
00193             CODEX_Client::SignedBoundNameMsg(
00194                response,
00195                CODEX_Ciphers::RSASignature() ) ) )
00196          {
00197 #ifdef TIMING
00198             ActiveTimer.stop();
00199 #endif
00200             throw KeyNotFoundException( __FILE__ , __LINE__ );
00201          }
00202       }
00203 
00204       event.reRoute( m_destination );
00205    }
00206    else
00207    {
00208       sendEvent( 0, event.source(), true ); // NACK
00209    }
00210 #ifdef TIMING
00211    ActiveTimer.stop();
00212 #endif
00213    return (!retVal);
00214 }
00215 
00216 bool
00217 DelegateResponseVerifier::handler(
00218    SupportedClientResponseEvent< KeyStoredMsg, SignedWriteKeyMsg >& event )
00219 {
00220 #ifdef TIMING
00221    ActiveTimer.start();
00222 #endif
00223    const KeyStoredMsg& response = event.message().response();
00224 
00225    // We do not need to check the details of the write request, since
00226    // correct servers will have done that already before signing it.
00227    const SignedWriteKeyMsg& request = event.message().request();
00228    if ( response.name().value() != request.message().name().value() )
00229    {
00230 #ifdef TIMING
00231       ActiveTimer.stop();
00232 #endif
00233       return true;
00234    }
00235    // The response must contain the signature on the request, or it's
00236    // not valid.
00237    if ( 0 != BN_cmp( response.requestSignature().value(),
00238                      request.signature().value() ) )
00239    {
00240 #ifdef TIMING
00241       ActiveTimer.stop();
00242 #endif
00243       return true;
00244    }
00245 
00246    // Get the server state info.
00247    CODEX_Server::ServerState* serverState =
00248       CODEX_Server::ServerState::instance();
00249    if ( 0 == serverState )
00250    {
00251 #ifdef TIMING
00252       ActiveTimer.stop();
00253 #endif
00254       return true;
00255    }
00256 
00257    StateInfo* stateInfo = StateInfo::instance();
00258    if ( 0 == stateInfo )
00259    {
00260 #ifdef TIMING
00261       ActiveTimer.stop();
00262 #endif
00263       return true;
00264    }
00265 
00266    // Get the quorum system.
00267    CODEX_Quorum::QuorumSystem* qs = serverState->quorumSystem();
00268    if ( 0 == qs )
00269    {
00270 #ifdef TIMING
00271       ActiveTimer.stop();
00272 #endif
00273       return true;
00274    }
00275 
00276    // Get a digest of the request.
00277    BIGNUM * digest = 0;
00278    try
00279    {
00280       digest = request.digest( serverState->hashFunc() );
00281    }
00282    catch ( ... )
00283    {
00284       if ( 0 != digest ) BN_free(digest);
00285 #ifdef TIMING
00286       ActiveTimer.stop();
00287 #endif
00288       return true;
00289    }
00290    if ( 0 == digest )
00291    {
00292 #ifdef TIMING
00293       ActiveTimer.stop();
00294 #endif
00295       return true;
00296    }
00297 
00298    bool retVal =
00299       process( digest, event.message().evidence(), qs->quorumSize() );
00300 
00301    BN_free( digest );
00302 
00303    if ( retVal )
00304    {
00305       // The request is valid, so the value should be stored regardless
00306       // of whether a value exists at this server already.  In addition,
00307       // the verified bit should be set.
00308       const KeyInfo* keyInfo =
00309          stateInfo->getKeyInfo( request.message().name().value() );
00310       if ( 0 == keyInfo )
00311       {
00312          if ( ! stateInfo->addKeyName( response.name().value(),
00313                                        request.message().binding() ) )
00314          {
00315 #ifdef TIMING
00316             ActiveTimer.stop();
00317 #endif
00318             throw KeyExistsException( __FILE__ , __LINE__ );
00319          }
00320          if ( ! stateInfo->addKeyValue( response.name().value(),
00321                                         request.message().encryption() ) )
00322          {
00323 #ifdef TIMING
00324             ActiveTimer.stop();
00325 #endif
00326             throw KeyNotFoundException( __FILE__ , __LINE__ );
00327          }
00328       }
00329       else
00330       {
00331          // If the key value is not yet set, or the values differ, set the
00332          // key value according to the request.
00333          if ( ! ( keyInfo->keyValue().initialized() &&
00334                   ( keyInfo->keyValue() == request.message().encryption() ) ) )
00335          {
00336             if ( ! stateInfo->addKeyValue( response.name().value(),
00337                                            request.message().encryption() ) )
00338             {
00339 #ifdef TIMING
00340                ActiveTimer.stop();
00341 #endif
00342                throw KeyNotFoundException( __FILE__ , __LINE__ );
00343             }
00344          }
00345       }
00346 
00347       if ( ! stateInfo->verifyKeyValue( response.name().value() ) )
00348       {
00349 #ifdef TIMING
00350          ActiveTimer.stop();
00351 #endif
00352          throw KeyNotFoundException( __FILE__ , __LINE__ );
00353       }
00354 
00355       event.reRoute( m_destination );
00356    }
00357    else
00358    {
00359       sendEvent( 0, event.source(), true ); // NACK
00360    }
00361 #ifdef TIMING
00362    ActiveTimer.stop();
00363 #endif
00364    return (!retVal);
00365 }
00366 
00367 bool
00368 DelegateResponseVerifier::handler( SupportedKeyStoredEvent& event )
00369 {
00370 #ifdef TIMING
00371    ActiveTimer.start();
00372 #endif
00373    const KeyStoredMsg& response = event.message().response();
00374 
00375    // Get the server state info.
00376    CODEX_Server::ServerState* serverState =
00377       CODEX_Server::ServerState::instance();
00378    if ( 0 == serverState )
00379    {
00380 #ifdef TIMING
00381       ActiveTimer.stop();
00382 #endif
00383       return true;
00384    }
00385 
00386    StateInfo* stateInfo = StateInfo::instance();
00387    if ( 0 == stateInfo )
00388    {
00389 #ifdef TIMING
00390       ActiveTimer.stop();
00391 #endif
00392       return true;
00393    }
00394 
00395    // Get the quorum system.
00396    CODEX_Quorum::QuorumSystem* qs = serverState->quorumSystem();
00397    if ( 0 == qs )
00398    {
00399 #ifdef TIMING
00400       ActiveTimer.stop();
00401 #endif
00402       return true;
00403    }
00404 
00405    // Get a digest of the response.
00406    BIGNUM * digest = 0;
00407    try
00408    {
00409       digest = response.digest( serverState->hashFunc() );
00410    }
00411    catch ( ... )
00412    {
00413       if ( 0 != digest ) BN_free(digest);
00414 #ifdef TIMING
00415       ActiveTimer.stop();
00416 #endif
00417       return true;
00418    }
00419    if ( 0 == digest )
00420    {
00421 #ifdef TIMING
00422       ActiveTimer.stop();
00423 #endif
00424       return true;
00425    }
00426 
00427    bool retVal =
00428       process( digest, event.message().evidence(), qs->quorumSize() );
00429 
00430    BN_free( digest );
00431 
00432    if ( retVal )
00433    {
00434       event.reRoute( m_destination );
00435    }
00436    else
00437    {
00438       sendEvent( 0, event.source(), true ); // NACK
00439    }
00440 #ifdef TIMING
00441    ActiveTimer.stop();
00442 #endif
00443    return (!retVal);
00444 }
00445 
00446 bool
00447 DelegateResponseVerifier::handler(
00448    SupportedClientResponseEvent< VerifiableBlindKeyMsg, SignedReadKeyMsg >&
00449    event )
00450 {
00451 #ifdef TIMING
00452    ActiveTimer.start();
00453 #endif
00454    const BlindKeyMsg& response = event.message().response();
00455    const VerifiableBlindKeyMsg& vResponse = event.message().response();
00456 
00457    // We do not need to check the details of the read request, since
00458    // a correct server will have done that already before signing it.
00459    const SignedReadKeyMsg& request = event.message().request();
00460 
00461    if ( response.name().value() != request.message().name().value() )
00462    {
00463 #ifdef TIMING
00464       ActiveTimer.stop();
00465 #endif
00466       return true;
00467    }
00468 
00469    // The response must contain the signature on the request, or it's
00470    // not valid.
00471    if ( 0 != BN_cmp( response.requestSignature().value(),
00472                      request.signature().value() ) )
00473    {
00474 #ifdef TIMING
00475       ActiveTimer.stop();
00476 #endif
00477       return true;
00478    }
00479 
00480    // Get the server state info.
00481    CODEX_Server::ServerState* serverState =
00482       CODEX_Server::ServerState::instance();
00483    if ( 0 == serverState )
00484    {
00485 #ifdef TIMING
00486       ActiveTimer.stop();
00487 #endif
00488       return true;
00489    }
00490 
00491    // Get the quorum system.
00492    CODEX_Quorum::QuorumSystem* qs = serverState->quorumSystem();
00493    if ( 0 == qs )
00494    {
00495 #ifdef TIMING
00496       ActiveTimer.stop();
00497 #endif
00498       return true;
00499    }
00500 
00501    // Get a digest of the request.
00502    BIGNUM * digest = 0;
00503    unsigned char* buff = 0;
00504    CODEX_ASN1::ustring* str = 0;
00505    try
00506    {
00507       int length = request.marshal(0);
00508       length += vResponse.blindCipher().marshal(0);
00509       buff = new unsigned char[ length ];
00510       unsigned char* pBuff = buff;
00511       request.marshal(&pBuff);
00512       vResponse.blindCipher().marshal(&pBuff);
00513 
00514       str = serverState->hashFunc()( CODEX_ASN1::ustring( buff, length ) );
00515 
00516       delete [] buff;
00517       buff = 0;
00518 
00519       digest = BN_new();
00520       if ( 0 == digest )
00521       {
00522          throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00523       }
00524       if ( 0 == BN_bin2bn( str->data(), str->length(), digest ) )
00525       {
00526          throw CODEX_Exceptions::BignumBin2BNException( __FILE__ , __LINE__ );
00527       }
00528 
00529       delete str;
00530    }
00531    catch ( ... )
00532    {
00533       if ( 0 != digest ) BN_free(digest);
00534       if ( 0 != buff ) delete [] buff;
00535       if ( 0 != str ) delete str;
00536 #ifdef TIMING
00537       ActiveTimer.stop();
00538 #endif
00539       return true;
00540    }
00541    if ( 0 == digest )
00542    {
00543 #ifdef TIMING
00544       ActiveTimer.stop();
00545 #endif
00546       return true;
00547    }
00548 
00549 #ifndef ELGAMAL
00550    // RSA test
00551    CODEX_Ciphers::RSACipherText* blindEncryption = 0;
00552    try
00553    {
00554       blindEncryption = serverState->serviceKey().encrypt(
00555          response.blindedKey().b1().value() );
00556       bool cipherTest1 = ( *blindEncryption == vResponse.blindCipher().c1() );
00557       delete blindEncryption;
00558       blindEncryption = 0;
00559       bool cipherTest2 =
00560          ( response.blindedKey().b2() == vResponse.blindCipher().c2() );
00561       if ( ! ( cipherTest1 && cipherTest2 ) )
00562       {
00563 #ifdef TIMING
00564          ActiveTimer.stop();
00565 #endif
00566          return true;
00567       }
00568    }
00569    catch ( ... )
00570    {
00571       if ( 0 != blindEncryption ) delete blindEncryption;
00572 #ifdef TIMING
00573       ActiveTimer.stop();
00574 #endif
00575       return true;
00576    }
00577 #else /* ELGAMAL */
00578    // ElGamal test
00579    typedef CODEX_Server::ServerState::ShareSetType  ShareSetType;
00580    typedef CODEX_Server::ServerState::ShareType     ShareType;
00581    const CODEX_Ciphers::ElGamalPublicKey& serviceEGKey =
00582       serverState->publicEGKey();
00583    ShareSetType tempSS;
00584    for ( unsigned int i = 0 ; i < ShareType::NumShares ; ++i )
00585    {
00586       if ( vResponse.proof(i).verify( vResponse.blindCipher().c1().value(),
00587                                       serviceEGKey.g().value(),
00588                                       vResponse.partial(i).value(),
00589                                       vResponse.label().vc(i).value(),
00590                                       serviceEGKey.p().value(),
00591                                       serverState->hashFunc() ) )
00592       {
00593          tempSS.setShare(i,vResponse.partial(i));
00594       }
00595       else
00596       {
00597 #ifdef TIMING
00598          ActiveTimer.stop();
00599 #endif
00600          return true;
00601       }
00602    }
00603    // We now know that combining the partial results gives us c1^x
00604    // Now we must recover the plaintext from this using c2, and compare
00605    // with the alleged plaintext.
00606    BIGNUM * bk = serverState->thresholdEG().thresholdDecrypt(
00607       tempSS,
00608       vResponse.blindCipher() );
00609    if ( 0 == bk )
00610    {
00611 #ifdef TIMING
00612       ActiveTimer.stop();
00613 #endif
00614       return true;
00615    }
00616    bool bkMismatch = ( 0 != BN_cmp( bk, response.blindedKey().value() ) );
00617    BN_clear_free( bk );
00618    if ( bkMismatch )
00619    {
00620 #ifdef TIMING
00621       ActiveTimer.stop();
00622 #endif
00623       return true;
00624    }
00625 #endif /* ELGAMAL */
00626 
00627    bool retVal = process(
00628       digest, event.message().evidence(), qs->faultsTolerated()+1 );
00629 
00630    BN_free( digest );
00631 
00632    if ( retVal )
00633    {
00634       event.reRoute( m_destination );
00635    }
00636    else
00637    {
00638       sendEvent( 0, event.source(), true ); // NACK
00639    }
00640 #ifdef TIMING
00641    ActiveTimer.stop();
00642 #endif
00643    return (!retVal);
00644 }
00645 
00646 bool
00647 DelegateResponseVerifier::process(
00648    const BIGNUM* digest,
00649    const CODEX_ASN1::Array< CODEX_Server::ServerSignature >& evidence,
00650    unsigned int evidenceSize )
00651 {
00652    typedef CODEX_ASN1::Array< CODEX_Server::ServerSignature > ArrayType;
00653 
00654    // Make sure the digest isn't 0.
00655    if ( 0 == digest )
00656    {
00657       return false;
00658    }
00659 
00660    // We don't want to double-count evidence.
00661    bool serverResponses[ CODEX_Server::ServerState::nServers ];
00662    for ( unsigned int i = 0 ; i < CODEX_Server::ServerState::nServers ; ++i )
00663    {
00664       serverResponses[i] = false;
00665    }
00666 
00667    // Get the server state info.
00668    CODEX_Server::ServerState* serverState =
00669       CODEX_Server::ServerState::instance();
00670    if ( 0 == serverState )
00671    {
00672       return false;
00673    }
00674 
00675    // Make sure there is enough evidence.
00676    if ( evidence.size() < evidenceSize )
00677    {
00678       return false;
00679    }
00680 
00681    // Loop over the evidence.  Any bad signatures result in a verification
00682    // failure.  Duplications aren't counted and don't result in a rejection.
00683    // The good-signature counter must accumulate enough for a positive
00684    // verification.
00685    unsigned int goodSigs = 0;
00686    ArrayType::ArrayItr itr = evidence.begin();
00687    ArrayType::ArrayItr end = evidence.end();
00688    for ( ; itr != end ; ++itr )
00689    {
00690       int serverNum = (*itr)->serverID().value();
00691       if ( serverResponses[ serverNum ] )
00692       {
00693          // We've already seen a purported signature from this server.
00694          continue;
00695       }
00696       serverResponses[ serverNum ] = true;
00697 
00698       // Get the server's public key.
00699       const CODEX_Ciphers::RSAPublicKey& pubKey =
00700          serverState->publicKey( serverNum );
00701       if ( ! pubKey.initialized() )
00702       {
00703          break;
00704       }
00705 
00706       // Now check the signature.
00707       if ( ! pubKey.verifySignature( (*itr)->signature(), digest ) )
00708       {
00709          break;
00710       }
00711 
00712       // Everything's OK.
00713       ++goodSigs;
00714    }
00715 
00716    // Did we get enough?
00717    if ( goodSigs < evidenceSize )
00718    {
00719       return false;
00720    }
00721    return true;
00722 }

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