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

ClientMessageVerifier.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: ClientMessageVerifier.cc,v 1.4 2004/05/19 15:56:51 mmarsh Exp $
00008 //
00009 // $Log: ClientMessageVerifier.cc,v $
00010 // Revision 1.4  2004/05/19 15:56:51  mmarsh
00011 // *** empty log message ***
00012 //
00013 // Revision 1.3  2003/11/04 22:15:00  mmarsh
00014 // General code cleanup and reorganization.  The signed ElGamal public key
00015 // was moved to CODEX_Server, decoupling that package from CODEX_Client.
00016 // Since CODEX_Server no longer knows about the cryptosystem used by
00017 // the client, switching between cryptosystems is handled locally by
00018 // CODEX_KeyService.
00019 //
00020 //
00021 
00022 #include <assert.h>
00023 
00024 #include "ClientMessageVerifier.h"
00025 #include "ClientResponseEvent.h"
00026 #include "ClientActivity.h"
00027 #include "CODEX_Server/ServerState.h"
00028 #include "StateInfo.h"
00029 #include "CODEX_Server/ServerExceptions.h"
00030 #include "Exceptions.h"
00031 
00032 #include "timing.h"
00033 
00034 using namespace CODEX_KeyService;
00035 
00036 ClientMessageVerifier::ClientMessageVerifier(
00037    CODEX_Events::DeadPileType& deadPile,
00038    CODEX_Events::QType& eventQueue,
00039    ClientMessageHandler* destination ) :
00040    CODEX_Events::Activity(deadPile,eventQueue),
00041    m_destination( destination )
00042 {
00043    assert( 0 != m_destination );
00044 }
00045 
00046 ClientMessageVerifier::~ClientMessageVerifier()
00047 {
00048 }
00049 
00050 bool
00051 ClientMessageVerifier::handler( CODEX_Events::CloseEvent& event )
00052 {
00053    // We only consume close events.
00054    sendEvent( 0, event.source() );
00055    // The message handler doesn't terminate.  All of its predecessors
00056    // are ephemeral.
00057    return true;
00058 }
00059 
00060 bool
00061 ClientMessageVerifier::handler( ClientMessageEvent< RequestKeyMsg >& event )
00062 {
00063    // We should be able to handle this message here, and avoid any
00064    // further processing.
00065    const CODEX_Server::SignedAugmentedEGPublicKey& pkMsg =
00066       CODEX_Server::ServerState::instance()->signedEGKey();
00067    if ( pkMsg.initialized() )
00068    {
00069       ClientActivity* ca =
00070          StateInfo::instance()->getClient( event.source() );
00071       if ( 0 != ca )
00072       {
00073          typedef
00074             ClientResponseEvent< CODEX_Server::SignedAugmentedEGPublicKey >
00075             EvtType;
00076          EvtType* outEvt = new EvtType(this,ca,pkMsg);
00077          sendEvent( outEvt, event.source() );
00078          return true;
00079       }
00080    }
00081    sendEvent( 0, event.source() ); // just acknowledge
00082    return true;
00083 }
00084 
00086 bool
00087 ClientMessageVerifier::handler(
00088    ClientMessageEvent< SignedCreateKeyMsg >& event )
00089 {
00090 #ifdef TIMING
00091    ActiveTimer.start();
00092 #endif
00093    const CODEX_Ciphers::RSASignature& signature = event.message().signature();
00094    const CreateKeyMsg& request = event.message().message();
00095 
00096    BIGNUM * digest = 0;
00097    try
00098    {
00099       CODEX_Server::ServerState* serverState =
00100          CODEX_Server::ServerState::instance();
00101       const CODEX_Ciphers::HashFunction& hashFunc = serverState->hashFunc();
00102 
00103       StateInfo* stateInfo = StateInfo::instance();
00104 
00105       // Check if the name is already bound at this server.
00106       const KeyInfo* keyInfo =
00107          stateInfo->getKeyInfo( request.name().value() );
00108       if ( 0 != keyInfo )
00109       {
00110          // Is it the same binding?  Compare signatures on the requests.
00111          if ( signature != keyInfo->binding().request().signature() )
00112          {
00113             throw KeyExistsException( __FILE__ , __LINE__ );
00114          }
00115          // Has this request been serviced?  If so, just return the cached
00116          // response.
00117          if ( keyInfo->signature().initialized() )
00118          {
00119             ClientActivity* ca =
00120                stateInfo->getClient( event.source() );
00121             if ( 0 != ca )
00122             {
00123                typedef ClientResponseEvent< CODEX_Client::SignedBoundNameMsg >
00124                   EvtType;
00125                EvtType* outEvt =
00126                   new EvtType( this, ca, CODEX_Client::SignedBoundNameMsg(
00127                      keyInfo->binding(), keyInfo->signature() ) );
00128                sendEvent( outEvt, event.source() );
00129                // Don't sign another response.
00130 #ifdef TIMING
00131                ActiveTimer.stop();
00132 #endif
00133                return true;
00134             }
00135             // This is a duplicate, but we must allow it.
00136 #ifdef TIMING
00137             ActiveTimer.stop();
00138 #endif
00139             return false;
00140          }
00141       }
00142 
00143       // Check signature on client's certificate.
00144       EVP_PKEY* caKey = (EVP_PKEY*) serverState->caKey();
00145       if ( 0 == caKey )
00146       {
00147          throw CODEX_Server::PublicKeyNotFoundException( __FILE__ , __LINE__ );
00148       }
00149       X509 * ownerCert = (X509*) request.owner().value();
00150       if ( ! X509_verify( ownerCert, caKey ) )
00151       {
00152          throw CODEX_Server::CertificateNotFoundException( __FILE__ ,
00153                                                            __LINE__ );
00154       }
00155 
00156       // Check signature on message.
00157       CODEX_Ciphers::RSAPublicKey ownerKey( request.owner().value() );
00158       digest = request.digest( hashFunc );
00159       bool sigOK = ownerKey.verifySignature( signature, digest );
00160       BN_free( digest );
00161       digest = 0;
00162       if ( ! sigOK )
00163       {
00164          throw CODEX_Server::SignatureVerificationFailedException( __FILE__ ,
00165                                                                    __LINE__ );
00166       }
00167 
00168       // Check the signatures on the policies.
00169       // NOTE: Policies no longer need to be verified
00170 //      if ( ! request.readP().verify( ownerKey, hashFunc ) )
00171 //      {
00172 //         throw CODEX_Server::SignatureVerificationFailedException( __FILE__ ,
00173 //                                                                   __LINE__ );
00174 //      }
00175 //      if ( ! request.writeP().verify( ownerKey, hashFunc ) )
00176 //      {
00177 //         throw CODEX_Server::SignatureVerificationFailedException( __FILE__ ,
00178 //                                                                   __LINE__ );
00179 //      }
00180 
00181       // We have now seen a valid create_key request, and should _not_
00182       // respond to another.
00183       if ( 0 == keyInfo )
00184       {
00185          if ( ! stateInfo->addKeyName( request.name().value(),
00186                                        CODEX_Client::BoundNameMsg(
00187                                           request.name(),
00188                                           event.message() ) ) )
00189          {
00190             throw KeyExistsException( __FILE__ , __LINE__ );
00191          }
00192       }
00193 
00194       // Now we're done. Re-route the event to our successor.
00195       event.reRoute( m_destination );
00196 #ifdef TIMING
00197       ActiveTimer.stop();
00198 #endif
00199       return false; // Event hasn't been fully handled yet.
00200    }
00201    catch ( CODEX_Exceptions::ExceptionBase& e )
00202    {
00203       e.report();
00204       if ( 0 != digest ) BN_free( digest );
00205       // send a NACK
00206       sendEvent( 0, event.source(), true );
00207 #ifdef TIMING
00208       ActiveTimer.stop();
00209 #endif
00210       return true;
00211    }
00212    catch ( ... )
00213    {
00214       if ( 0 != digest ) BN_free( digest );
00215       // send a NACK
00216       sendEvent( 0, event.source(), true );
00217 #ifdef TIMING
00218       ActiveTimer.stop();
00219 #endif
00220       return true;
00221    }
00222 }
00223 
00224 bool
00225 ClientMessageVerifier::handler(
00226    ClientMessageEvent< SignedWriteKeyMsg >& event )
00227 {
00228 #ifdef TIMING
00229    ActiveTimer.start();
00230 #endif
00231    const CODEX_Ciphers::RSASignature& signature = event.message().signature();
00232    const WriteKeyMsg& request = event.message().message();
00233 
00234    BIGNUM * digest = 0;
00235    try
00236    {
00237       CODEX_Server::ServerState* serverState =
00238          CODEX_Server::ServerState::instance();
00239       StateInfo* stateInfo = StateInfo::instance();
00240       const CODEX_Ciphers::HashFunction& hashFunc = serverState->hashFunc();
00241 
00242       // Check if the name is already bound at this server.
00243       const KeyInfo* keyInfo = stateInfo->getKeyInfo( request.name().value() );
00244       if ( 0 == keyInfo )
00245       {
00247          // Check the binding that was passed in.
00248 
00249          // Do the names match?
00250          if ( request.name().value() !=
00251               request.binding().message().name().value() )
00252          {
00253             throw NameMismatchException( __FILE__ , __LINE__ );
00254          }
00255 
00256          // Is the signature valid?
00257          const CODEX_Ciphers::RSAPublicKey& servKey =
00258             serverState->serviceKey();
00259          if ( ! servKey.initialized() )
00260          {
00261             throw CODEX_Server::PublicKeyNotFoundException( __FILE__ ,
00262                                                             __LINE__ );
00263          }
00264          const CODEX_Ciphers::RSASignature& bSig =
00265             request.binding().signature();
00266          digest = request.binding().message().digest( hashFunc );
00267          if ( ! servKey.verifySignature( bSig, digest ) )
00268          {
00269             throw
00270                CODEX_Server::SignatureVerificationFailedException( __FILE__ ,
00271                                                                    __LINE__ );
00272          }
00273          BN_free( digest );
00274          digest = 0;
00275 
00276          // Add the binding as if this server had participated in the
00277          // original transaction.
00278          if ( ! stateInfo->addKeyName( request.name().value(),
00279                                        request.binding() ) )
00280          {
00281             throw KeyExistsException( __FILE__ , __LINE__ );
00282          }
00283          // Now get the KeyInfo object.
00284          keyInfo = stateInfo->getKeyInfo( request.name().value() );
00285          if ( 0 == keyInfo )
00286          {
00287             throw KeyNotFoundException( __FILE__ , __LINE__ );
00288          }
00289       }
00290       else
00291       {
00292          // Check if the bindings match
00293          if ( ! keyInfo->signature().initialized() )
00294          {
00295             const CODEX_Ciphers::RSAPublicKey& servKey =
00296                serverState->serviceKey();
00297             if ( ! servKey.initialized() )
00298             {
00299                throw CODEX_Server::PublicKeyNotFoundException( __FILE__ ,
00300                                                                __LINE__ );
00301             }
00302             const CODEX_Ciphers::RSASignature& bSig =
00303                request.binding().signature();
00304             digest = request.binding().message().digest( hashFunc );
00305             if ( ! servKey.verifySignature( bSig, digest ) )
00306             {
00307                throw CODEX_Server::SignatureVerificationFailedException(
00308                   __FILE__ , __LINE__ );
00309             }
00310             BN_free( digest );
00311             digest = 0;
00312             digest = keyInfo->binding().digest( hashFunc );
00313             if ( servKey.verifySignature( bSig, digest ) )
00314             {
00315                // Add the signature for the binding
00316                if ( ! stateInfo->addKeySignature( request.name().value(),
00317                                                   bSig ) )
00318                {
00319                   throw KeyNotFoundException( __FILE__ , __LINE__ );
00320                }
00321             }
00322             else
00323             {
00324                // Replace the binding -- the old one was not approved
00325                if ( ! stateInfo->replaceKeyBinding( request.name().value(),
00326                                                     request.binding() ) )
00327                {
00328                   throw KeyNotFoundException( __FILE__ , __LINE__ );
00329                }
00330             }
00331             BN_free( digest );
00332             digest = 0;
00333          }
00334          else
00335          {
00336             // If the key already exists at this server and has a value set,
00337             // then fail.  This enforces write-once semantics in the absence
00338             // of an explicit clear operation.  It also results in failures
00339             // for multiple clients attempting to write values simultaneously,
00340             // rather than each thinking it has successfully written a value
00341             // for the key.
00342             if ( keyInfo->keyValue().initialized() )
00343             {
00344                if ( keyInfo->keyValue() != request.encryption() )
00345                {
00346                   throw KeyExistsException( __FILE__ , __LINE__ );
00347                }
00348             }
00349          }
00350       }
00351 
00352       // Check the client's credentials (which are signed).
00353       const CODEX_Ciphers::Policy& writeP =
00354          keyInfo->binding().request().message().writeP();
00355       if ( ! writeP.verify( request.credentials() ) )
00356       {
00357          throw CODEX_Server::SignatureVerificationFailedException( __FILE__ ,
00358                                                                    __LINE__ );
00359       }
00360 
00361       // Check signature on message.
00362       const CODEX_Ciphers::RSAPublicKey& clientKey =
00363          request.credentials().publicKey();
00364       digest = request.digest( hashFunc );
00365       if ( ! clientKey.verifySignature( signature, digest ) )
00366       {
00367          throw CODEX_Server::SignatureVerificationFailedException( __FILE__ ,
00368                                                                    __LINE__ );
00369       }
00370       BN_free( digest );
00371       digest = 0;
00372 
00373 #ifndef ELGAMAL
00374       // Check the plaintext proof of knowledge certificate.
00375       const CODEX_Ciphers::RSAPublicKey& pubKey = serverState->serviceKey();
00376       if ( ! pubKey.initialized() )
00377       {
00378          throw CODEX_Server::PublicKeyNotFoundException( __FILE__ , __LINE__ );
00379       }
00380       if ( ! request.proof().verify( request.encryption().c1(),
00381                                      pubKey,
00382                                      request.credentials(),
00383                                      hashFunc ) )
00384       {
00385          throw CODEX_Server::SignatureVerificationFailedException( __FILE__ ,
00386                                                                    __LINE__ );
00387       }
00388 #else
00389       // Check the validity of the signed encryption.
00390       //
00391       // The client's credentials provide its identity, which must have
00392       // been used to generate the Schnorr signature.  This provides a
00393       // plaintext-client binding.
00394       const CODEX_Ciphers::ElGamalPublicKey& pubEGKey =
00395          serverState->publicEGKey();
00396       if ( ! pubEGKey.initialized() )
00397       {
00398          throw CODEX_Server::PublicKeyNotFoundException( __FILE__ , __LINE__ );
00399       }
00400       if ( ! request.encryption().verify( pubEGKey.g(),
00401                                           pubEGKey.p(),
00402                                           request.credentials(),
00403                                           hashFunc ) )
00404       {
00405          throw CODEX_Server::SignatureVerificationFailedException( __FILE__ ,
00406                                                                    __LINE__ );
00407       }
00408 #endif      
00409 
00410       // Everything is good.  Write the value now so that write-once
00411       // semantics can be enforced (in the absence of an explicit clearing
00412       // operation).
00413       if ( ! keyInfo->keyValue().initialized() )
00414       {
00415          if ( ! stateInfo->addKeyValue( request.name().value(),
00416                                         request.encryption() ) )
00417          {
00418             throw KeyNotFoundException( __FILE__ , __LINE__ );
00419          }
00420          // Now we're done. Re-route the event to our successor.
00421          event.reRoute( m_destination );
00422 #ifdef TIMING
00423          ActiveTimer.stop();
00424 #endif
00425          return false; // Event hasn't been fully handled yet.
00426       }
00427       else
00428       {
00429          if ( keyInfo->keyValue() != request.encryption() )
00430          {
00431             // Only write once.
00432 #ifdef TIMING
00433             ActiveTimer.stop();
00434 #endif
00435             return true;
00436          }
00437          // This is a duplicate request, but should still be approved.
00438          event.reRoute( m_destination );
00439 #ifdef TIMING
00440          ActiveTimer.stop();
00441 #endif
00442          return false; // Event hasn't been fully handled yet.
00443       }
00444    }
00445    catch ( ... )
00446    {
00447       if ( 0 != digest ) BN_free( digest );
00448       // send a NACK
00449       sendEvent( 0, event.source(), true );
00450 #ifdef TIMING
00451       ActiveTimer.stop();
00452 #endif
00453       return true;
00454    }
00455 }
00456 
00457 bool
00458 ClientMessageVerifier::handler( ClientMessageEvent< SignedReadKeyMsg >& event )
00459 {
00460 #ifdef TIMING
00461    ActiveTimer.start();
00462 #endif
00463    const CODEX_Ciphers::RSASignature& signature = event.message().signature();
00464    const ReadKeyMsg& request = event.message().message();
00465 
00466    BIGNUM * digest = 0;
00467    try
00468    {
00469       CODEX_Server::ServerState* serverState =
00470          CODEX_Server::ServerState::instance();
00471       const CODEX_Ciphers::HashFunction& hashFunc = serverState->hashFunc();
00472 
00473       StateInfo* stateInfo = StateInfo::instance();
00474 
00475       // Check if the name is bound at this server.
00476       const KeyInfo* keyInfo =
00477          stateInfo->getKeyInfo( request.name().value() );
00478       if ( 0 != keyInfo )
00479       {
00480          // Check the client's credentials (which are signed).
00481          const CODEX_Ciphers::Policy& readP =
00482             keyInfo->binding().request().message().readP();
00483          if ( ! readP.verify( request.credentials() ) )
00484          {
00485             throw
00486                CODEX_Server::SignatureVerificationFailedException( __FILE__ ,
00487                                                                    __LINE__ );
00488          }
00489       }
00490 
00491       // Check signature on message, assuming the credentials are valid.
00492       const CODEX_Ciphers::RSAPublicKey& clientKey =
00493          request.credentials().publicKey();
00494       digest = request.digest( hashFunc );
00495       if ( ! clientKey.verifySignature( signature, digest ) )
00496       {
00497          throw CODEX_Server::SignatureVerificationFailedException( __FILE__ ,
00498                                                                    __LINE__ );
00499       }
00500       BN_free( digest );
00501       digest = 0;
00502 
00503 #ifndef ELGAMAL
00504       // Check the plaintext proof of knowledge certificate.
00505       const CODEX_Ciphers::RSAPublicKey& pubKey = serverState->serviceKey();
00506       if ( ! pubKey.initialized() )
00507       {
00508          throw CODEX_Server::PublicKeyNotFoundException( __FILE__ , __LINE__ );
00509       }
00510       if ( ! request.proof().verify( request.blinding(),
00511                                      pubKey,
00512                                      request.credentials(),
00513                                      hashFunc ) )
00514       {
00515          throw CODEX_Server::SignatureVerificationFailedException( __FILE__ ,
00516                                                                    __LINE__ );
00517       }
00518 #else
00519       // Check the validity of the signed encryption.
00520       //
00521       // The client's credentials provide its identity, which must have
00522       // been used to generate the Schnorr signature.  This provides a
00523       // plaintext-client binding.
00524       const CODEX_Ciphers::ElGamalPublicKey& pubEGKey =
00525          serverState->publicEGKey();
00526       if ( ! pubEGKey.initialized() )
00527       {
00528          throw CODEX_Server::PublicKeyNotFoundException( __FILE__ , __LINE__ );
00529       }
00530       if ( ! request.blinding().verify( pubEGKey.g(),
00531                                         pubEGKey.p(),
00532                                         request.credentials(),
00533                                         hashFunc ) )
00534       {
00535          throw CODEX_Server::SignatureVerificationFailedException( __FILE__ ,
00536                                                                    __LINE__ );
00537       }
00538 #endif      
00539 
00540       // Now we're done. Re-route the event to our successor.
00541       event.reRoute( m_destination );
00542 #ifdef TIMING
00543       ActiveTimer.stop();
00544 #endif
00545       return false; // Event hasn't been fully handled yet.
00546    }
00547    catch ( ... )
00548    {
00549       if ( 0 != digest ) BN_free( digest );
00550       // send a NACK
00551       sendEvent( 0, event.source(), true );
00552 #ifdef TIMING
00553       ActiveTimer.stop();
00554 #endif
00555       return true;
00556    }
00557 }

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