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

CODEX_KeyService/StateInfo.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: StateInfo.cc,v 1.3 2004/05/19 15:56:53 mmarsh Exp $
00008 //
00009 // $Log: StateInfo.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: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 <fstream>
00023 #include <sstream>
00024 #include <openssl/conf.h>
00025 
00026 #include "StateInfo.h"
00027 #include "ClientActivity.h"
00028 #include "CODEX_ASN1/Integer.h"
00029 #include "CODEX_Exceptions/FileExceptions.h"
00030 #include "CODEX_Server/ServerExceptions.h"
00031 #include "CODEX_Server/ConfigurationExceptions.h"
00032 #include "Exceptions.h"
00033 
00034 #include "timing.h"
00035 
00036 using namespace CODEX_KeyService;
00037 
00038 StateInfo* StateInfo::m_instance = 0;
00039 
00040 
00041 //=============================================================
00042 // Constructors and destructors
00043 //=============================================================
00044 
00045 StateInfo*
00046 StateInfo::instance()
00047 {
00048    if ( 0 == m_instance )
00049    {
00050       m_instance = new StateInfo;
00051    }
00052    return m_instance;
00053 }
00054 
00055 void
00056 StateInfo::destroy()
00057 {
00058    if ( 0 != m_instance )
00059    {
00060       delete m_instance;
00061    }
00062    m_instance = 0;
00063 }
00064 
00067 StateInfo::SynchronyState
00068 StateInfo::synchronize(const char* fname, bool force_read)
00069 {
00070    try
00071    {
00072       if ( m_keyMap.empty() || force_read )
00073       {
00074          // We need to read.
00075 
00076          // First purge the key map.
00077          KeyMap::iterator kmItr = m_keyMap.begin();
00078          KeyMap::iterator kmEnd = m_keyMap.end();
00079          for ( ; kmItr != kmEnd ; ++kmItr )
00080          {
00081             delete kmItr->second;
00082          }
00083          m_keyMap.clear();
00084 
00085          // Now read the keys in from the file "fname".
00086          ifstream is(fname);
00087          if ( ! is.is_open() )
00088          {
00089             throw CODEX_Exceptions::FileCannotOpenException( __FILE__ ,
00090                                                              __LINE__ ,
00091                                                              fname );
00092          }
00093          string s;
00094          char ch;
00095          while ( is.get(ch) )
00096          {
00097             s.push_back(ch);
00098          }
00099          //CODEX_ASN1::ustring s;
00100          //is >> s;
00101          is.close();
00102          unsigned int length = s.length();
00103          unsigned char* p = new unsigned char[length];
00104          unsigned char* pOrig = p;
00105          for ( unsigned int i = 0 ; i < length ; ++i )
00106          {
00107             p[i] = s.data()[i];
00108          }
00109          //unsigned char* p = (unsigned char*)s.data();
00110          unsigned char* oldP = p;
00111          CODEX_ASN1::Integer nKeys;
00112          if ( 0 == nKeys.unmarshal(0,&p,length) )
00113          {
00114             // Not a great exception to throw here, but it's not worth
00115             // creating a new class for this case.
00116             throw KeyNotFoundException( __FILE__ , __LINE__ );
00117          }
00118          length -= ( p - oldP );
00119          oldP = p;
00120          KeyInfo* pKey = 0;
00121          try
00122          {
00123             for ( int i = 0 ; i < nKeys.value() ; ++i )
00124             {
00125                CODEX_ASN1::OctetString name;
00126                pKey = new KeyInfo;
00127                if ( length < 1 )
00128                {
00129                   // not the _ideal_ exception, but it's an OK match, since
00130                   // we're expecting a key that isn't there.
00131                   throw KeyNotFoundException( __FILE__ , __LINE__ );
00132                }
00133                if ( 0 == name.unmarshal(0,&p,length) )
00134                {
00135                   throw KeyNotFoundException( __FILE__ , __LINE__ );
00136                }
00137                length -= ( p - oldP );
00138                oldP = p;
00139                if ( length < 1 )
00140                {
00141                   throw KeyNotFoundException( __FILE__ , __LINE__ );
00142                }
00143                if ( 0 == pKey->unmarshal(0,&p,length) )
00144                {
00145                   throw KeyNotFoundException( __FILE__ , __LINE__ );
00146                }
00147                length -= ( p - oldP );
00148                oldP = p;
00149                m_keyMap.insert( KeyMap::value_type( name.value(), pKey ) );
00150                pKey = 0;
00151             }
00152             delete [] pOrig;
00153             return kRead;
00154          }
00155          catch ( ... )
00156          {
00157             delete [] pOrig;
00158             if ( 0 != pKey ) delete pKey;
00159             throw;
00160          }
00161       }
00162       else
00163       {
00164          // We need to write.
00165          unsigned char* buff = 0;
00166          try
00167          {
00168             // First marshal the data.
00169             CODEX_ASN1::Integer nKeys( m_keyMap.size() );
00170             unsigned int length = nKeys.marshal(0);
00171             KeyMap::const_iterator kmItr = m_keyMap.begin();
00172             KeyMap::const_iterator kmEnd = m_keyMap.end();
00173             for ( ; kmItr != kmEnd ; ++kmItr )
00174             {
00175                CODEX_ASN1::OctetString name( kmItr->first );
00176                length += name.marshal(0);
00177                length += kmItr->second->marshal(0);
00178             }
00179             buff = new unsigned char[length];
00180             unsigned char* pBuff = buff;
00181             nKeys.marshal(&pBuff);
00182             kmItr = m_keyMap.begin();
00183             for ( ; kmItr != kmEnd ; ++kmItr )
00184             {
00185                CODEX_ASN1::OctetString name( kmItr->first );
00186                name.marshal(&pBuff);
00187                kmItr->second->marshal(&pBuff);
00188             }
00189 
00190             // Now write the buffer to the file "fname".
00191             ofstream os(fname);
00192             if ( ! os.is_open() )
00193             {
00194                throw CODEX_Exceptions::FileCannotCreateException( __FILE__ ,
00195                                                                   __LINE__ ,
00196                                                                   fname );
00197             }
00198             for ( unsigned int i = 0 ; i < length ; ++i )
00199             {
00200                os << buff[i];
00201             }
00202             os.close();
00203             delete [] buff;
00204             return kWrote;
00205          }
00206          catch ( ... )
00207          {
00208             if ( 0 != buff ) delete [] buff;
00209             throw;
00210          }
00211       }
00212    }
00213    catch ( CODEX_Exceptions::ExceptionBase& e )
00214    {
00215       // Synchrony exceptions are important -- always report them.
00216       e.report();
00217       return kFailed;
00218    }
00219    catch ( ... )
00220    {
00221       // unknown exception, just return the failure.
00222       return kFailed;
00223    }
00224 }
00225 
00226 StateInfo::StateInfo() :
00227    m_messageDomain( 0 ),
00228    m_delegationDomain( 0 )
00229 {
00230 }
00231 
00232 StateInfo::~StateInfo()
00233 {
00234    RequestMap::iterator rmItr = m_requestMap.begin();
00235    RequestMap::iterator rmEnd = m_requestMap.end();
00236    for ( ; rmItr != rmEnd ; ++rmItr )
00237    {
00238       delete [] rmItr->first;
00239    }
00240    KeyMap::iterator kmItr = m_keyMap.begin();
00241    KeyMap::iterator kmEnd = m_keyMap.end();
00242    for ( ; kmItr != kmEnd ; ++kmItr )
00243    {
00244       delete kmItr->second;
00245    }
00246 }
00247 
00248 
00249 //=============================================================
00250 // Configuration
00251 //=============================================================
00252 
00253 void
00254 StateInfo::configure( const CONF* conf, const char* sec, const string& fname )
00255 {
00256    long dummy;
00257 
00258    // Security parameter for proofs of plaintext knowledge
00259    if ( ! NCONF_get_number_e(conf,
00260                              sec,
00261                              "ppk_security_param",
00262                              &dummy) )
00263    {
00264       throw CODEX_Server::BCParameterNotDefinedException(
00265          __FILE__ , __LINE__ , fname, "ppk_security_param" );
00266    }
00267    if ( dummy <= 0 )
00268    {
00269       throw CODEX_Server::BCBadValueException(
00270          __FILE__ , __LINE__ , fname, "ppk_security_param" );
00271    }
00272    m_ppkSecurityParam = dummy;
00273 
00274    // Port on which to listen for clients.
00275    if ( ! NCONF_get_number_e(conf,sec,"client_port",&m_clientPort) )
00276    {
00277       throw CODEX_Server::BCParameterNotDefinedException(
00278          __FILE__ , __LINE__ , fname, "client_port" );
00279    }
00280    if ( 0 >= m_clientPort )
00281    {
00282       throw CODEX_Server::BCBadValueException(
00283          __FILE__ , __LINE__ , fname, "client_port" );
00284    }
00285 }
00286 
00287 
00288 //=============================================================
00289 // Client management
00290 //=============================================================
00291 
00292 bool
00293 StateInfo::addClient( ClientActivity* clientAct )
00294 {
00295    return ( m_clientMap.insert( ClientMap::value_type( clientAct,
00296                                                        clientAct ) ) ).second;
00297 }
00298 
00299 ClientActivity*
00300 StateInfo::getClient( CODEX_Events::Activity* clientAct ) const
00301 {
00302    ClientMap::const_iterator mapItr = m_clientMap.find( clientAct );
00303    if ( m_clientMap.end() == mapItr )
00304    {
00305       return 0;
00306    }
00307    return mapItr->second;
00308 }
00309 
00310 bool
00311 StateInfo::removeClient( CODEX_Events::Activity* clientAct )
00312 {
00313    ClientMap::iterator mapItr = m_clientMap.find( clientAct );
00314    if ( m_clientMap.end() == mapItr )
00315    {
00316       return false;
00317    }
00318    // remove all sequence numbers associated with this activity
00319    RequestMap::iterator rItr = m_requestMap.begin();
00320    // We want the call to end() to be made at each step, since the map
00321    // is potentially changing underneath us.
00322    for ( ; rItr != m_requestMap.end() ; )
00323    {
00324       if ( clientAct == rItr->second )
00325       {
00326          removeSequenceNumber( rItr->first );
00327          // re-start the loop
00328          rItr = m_requestMap.begin();
00329       }
00330       else
00331       {
00332          ++rItr;
00333       }
00334    }
00335    m_clientMap.erase( mapItr );
00336    return true;
00337 }
00338 
00339 bool
00340 StateInfo::registerSequenceNumber( const unsigned char* seqNum,
00341                                    CODEX_Events::Activity* clientAct )
00342 {
00343    unsigned char* s = new unsigned char[ CODEX_Server::ServerState::nMID ];
00344    memcpy( s, seqNum, CODEX_Server::ServerState::nMID );
00345    return ( m_requestMap.insert(
00346       RequestMap::value_type( s, clientAct ) ) ).second;
00347 }
00348 
00349 bool
00350 StateInfo::removeSequenceNumber( const unsigned char* seqNum )
00351 {
00352    RequestMap::iterator mapItr = m_requestMap.find( seqNum );
00353    if ( m_requestMap.end() == mapItr )
00354    {
00355       return false;
00356    }
00357    const unsigned char* s = mapItr->first;
00358    m_requestMap.erase( mapItr );
00359    delete [] s;
00360    return true;
00361 }
00362 
00363 CODEX_Events::Activity*
00364 StateInfo::getActFromSeqNum( const unsigned char* seqNum ) const
00365 {
00366    RequestMap::const_iterator mapItr = m_requestMap.find( seqNum );
00367    if ( m_requestMap.end() == mapItr )
00368    {
00369       return 0;
00370    }
00371    return mapItr->second;
00372 }
00373 
00374 
00375 //=============================================================
00376 // Key management
00377 //=============================================================
00378 
00379 bool
00380 StateInfo::addKeyName( const CODEX_ASN1::ustring& name,
00381                          const CODEX_Client::SignedBoundNameMsg& binding )
00382 {
00383    return (
00384       m_keyMap.insert( KeyMap::value_type(
00385          name,
00386          new KeyInfo(binding.message(), binding.signature()) )
00387          ) ).second;
00388 }
00389 
00390 bool
00391 StateInfo::addKeyName( const CODEX_ASN1::ustring& name,
00392                          const CODEX_Client::BoundNameMsg& binding )
00393 {
00394    return (
00395       m_keyMap.insert( KeyMap::value_type( name, new KeyInfo(binding) ) )
00396       ).second;
00397 }
00398 
00399 const KeyInfo*
00400 StateInfo::getKeyInfo( const CODEX_ASN1::ustring& name ) const
00401 {
00402 #ifdef TIMING
00403    LookupTimer.start();
00404 #endif
00405    KeyMap::const_iterator mapItr = m_keyMap.find( name );
00406 #ifdef TIMING
00407    LookupTimer.stop();
00408 #endif
00409    if ( m_keyMap.end() == mapItr )
00410    {
00411       return 0;
00412    }
00413    return mapItr->second;
00414 }
00415 
00416 bool
00417 StateInfo::addKeySignature( const CODEX_ASN1::ustring& name,
00418                               const CODEX_Ciphers::RSASignature& signature )
00419 {
00420 #ifdef TIMING
00421    LookupTimer.start();
00422 #endif
00423    KeyMap::iterator mapItr = m_keyMap.find( name );
00424 #ifdef TIMING
00425    LookupTimer.stop();
00426 #endif
00427    if ( m_keyMap.end() == mapItr )
00428    {
00429       return false;
00430    }
00431    mapItr->second->setSignature( signature );
00432    return true;
00433 }
00434 
00435 bool
00436 StateInfo::replaceKeyBinding(
00437    const CODEX_ASN1::ustring& name,
00438    const CODEX_Client::SignedBoundNameMsg& binding )
00439 {
00440 #ifdef TIMING
00441    LookupTimer.start();
00442 #endif
00443    KeyMap::iterator mapItr = m_keyMap.find( name );
00444 #ifdef TIMING
00445    LookupTimer.stop();
00446 #endif
00447    if ( m_keyMap.end() == mapItr )
00448    {
00449       return false;
00450    }
00451    mapItr->second->setBinding( binding.message() );
00452    mapItr->second->setSignature( binding.signature() );
00453    return true;
00454 }
00455 
00456 bool
00457 StateInfo::addKeyValue( const CODEX_ASN1::ustring& name,
00458                         const CODEX_Client::RequestCipherTextType& keyValue )
00459 {
00460 #ifdef TIMING
00461    LookupTimer.start();
00462 #endif
00463    KeyMap::iterator mapItr = m_keyMap.find( name );
00464 #ifdef TIMING
00465    LookupTimer.stop();
00466 #endif
00467    if ( m_keyMap.end() == mapItr )
00468    {
00469       return false;
00470    }
00471    mapItr->second->setKeyValue( keyValue );
00472    return true;
00473 }
00474 
00475 bool
00476 StateInfo::verifyKeyValue( const CODEX_ASN1::ustring& name )
00477 {
00478 #ifdef TIMING
00479    LookupTimer.start();
00480 #endif
00481    KeyMap::iterator mapItr = m_keyMap.find( name );
00482 #ifdef TIMING
00483    LookupTimer.stop();
00484 #endif
00485    if ( m_keyMap.end() == mapItr )
00486    {
00487       return false;
00488    }
00489    mapItr->second->setVerified();
00490    return true;
00491 }
00492 
00493 //=============================================================
00494 // Decryption template methods
00495 //=============================================================
00496 
00497 const StateInfo::LSType&
00498 StateInfo::decryptionShares( const LSType::LabelType& label,
00499                              unsigned int server ) const
00500 {
00501    return shareTemplate< CODEX_Client::CipherTextType >(
00502       label, server );
00503 }
00504 
00505 const StateInfo::LSType::LabelType&
00506 StateInfo::defaultDecryptionLabel() const
00507 {
00508    return labelTemplate< CODEX_Client::CipherTextType >();
00509 }
00510 
00511 const StateInfo::ThresholdDecryptionType&
00512 StateInfo::thresholdDecryption() const
00513 {
00514    return thresholdTemplate< ThresholdDecryptionType >();
00515 }
00516 
00517 
00518 //=============================================================
00519 // KeyInfo methods
00520 //=============================================================
00521 
00522 KeyInfo::KeyInfo() :
00523    CODEX_ASN1::Base( false ),
00524    m_verified( false )
00525 {
00526 }
00527 
00528 KeyInfo::KeyInfo( const CODEX_Client::BoundNameMsg& binding ) :
00529    CODEX_ASN1::Base( true ),
00530    m_binding( binding ),
00531    m_verified( false )
00532 {
00533 }
00534 
00535 KeyInfo::KeyInfo( const CODEX_Client::BoundNameMsg& binding,
00536                   const CODEX_Ciphers::RSASignature& signature ) :
00537    CODEX_ASN1::Base( true ),
00538    m_binding( binding ),
00539    m_signature( signature ),
00540    m_verified( false )
00541 {
00542 }
00543 
00544 KeyInfo::KeyInfo( const CODEX_Client::SignedBoundNameMsg& binding ) :
00545    CODEX_ASN1::Base( true ),
00546    m_binding( binding.message() ),
00547    m_signature( binding.signature() ),
00548    m_verified( false )
00549 {
00550 }
00551 
00552 KeyInfo::KeyInfo( const CODEX_Client::BoundNameMsg& binding,
00553                   const CODEX_Ciphers::RSASignature& signature,
00554                   const CODEX_Client::RequestCipherTextType& keyValue ) :
00555    CODEX_ASN1::Base( true ),
00556    m_binding( binding ),
00557    m_signature( signature ),
00558    m_keyValue( keyValue ),
00559    m_verified( false )
00560 {
00561 }
00562 
00563 KeyInfo::KeyInfo( const CODEX_Client::SignedBoundNameMsg& binding,
00564                   const CODEX_Client::RequestCipherTextType& keyValue ) :
00565    CODEX_ASN1::Base( true ),
00566    m_binding( binding.message() ),
00567    m_signature( binding.signature() ),
00568    m_keyValue( keyValue ),
00569    m_verified( false )
00570 {
00571 }
00572 
00573 KeyInfo::KeyInfo( const KeyInfo& aKI ) :
00574    CODEX_ASN1::Base( aKI.m_initialized ),
00575    m_binding( aKI.m_binding ),
00576    m_keyValue( aKI.m_keyValue ),
00577    m_verified( false )
00578 {
00579 }
00580 
00581 KeyInfo::~KeyInfo()
00582 {
00583 }
00584 
00585 void
00586 KeyInfo::operator=( const KeyInfo& aKI )
00587 {
00588    m_initialized = aKI.m_initialized;
00589    m_binding     = aKI.m_binding;
00590    m_keyValue    = aKI.m_keyValue;
00591    m_verified    = aKI.m_verified;
00592 }
00593 
00594 void
00595 KeyInfo::setKeyValue( const CODEX_Client::RequestCipherTextType& keyValue )
00596 {
00597    m_keyValue = keyValue;
00598 }
00599 
00600 void
00601 KeyInfo::setBinding( const CODEX_Client::BoundNameMsg& binding )
00602 {
00603    m_binding = binding;
00604 }
00605 
00606 void
00607 KeyInfo::setSignature( const CODEX_Ciphers::RSASignature& signature )
00608 {
00609    m_signature = signature;
00610 }
00611 
00612 int
00613 KeyInfo::marshal( unsigned char ** pp ) const
00614 {
00615    int r=0;
00616    int ret=0;
00617    unsigned char * p;
00618 
00619    CODEX_ASN1::Integer haveSignature( m_signature.initialized() ? 1 : 0 );
00620    CODEX_ASN1::Integer haveKeyValue( m_keyValue.initialized() ? 1 : 0 );
00621    CODEX_ASN1::Integer isVerified( m_verified ? 1 : 0 );
00622 
00623    ret += m_binding.marshal(0);
00624    ret += haveSignature.marshal(0);
00625    if ( haveSignature.value() )
00626    {
00627       ret += m_signature.marshal(0);
00628    }
00629    ret += haveKeyValue.marshal(0);
00630    if ( haveKeyValue.value() )
00631    {
00632       ret += m_keyValue.marshal(0);
00633    }
00634    ret += isVerified.marshal(0);
00635    M_ASN1_I2D_seq_total();
00636    m_binding.marshal(&p);
00637    haveSignature.marshal(&p);
00638    if ( haveSignature.value() )
00639    {
00640       m_signature.marshal(&p);
00641    }
00642    haveKeyValue.marshal(&p);
00643    if ( haveKeyValue.value() )
00644    {
00645       m_keyValue.marshal(&p);
00646    }
00647    isVerified.marshal(&p);
00648    M_ASN1_I2D_finish();
00649 }
00650 
00651 void*
00652 KeyInfo::unmarshal( void* bogus, unsigned char ** pp, long length )
00653 {
00654    if ( m_initialized )
00655    {
00656       return 0;
00657    }
00658    if ( (0 == pp) || (0 == *pp) )
00659    {
00660       return 0;
00661    }
00662    ASN1_CTX c;
00663    c.pp = pp;
00664    c.q = *pp;
00665    c.error = ERR_R_NESTED_ASN1_ERROR;
00666    int i;
00667    CODEX_ASN1::Integer haveSignature;
00668    CODEX_ASN1::Integer haveKeyValue;
00669    CODEX_ASN1::Integer isVerified;
00670 
00671    M_ASN1_D2I_Init();
00672    M_ASN1_D2I_start_sequence();
00673    M_ASN1_D2I_get(i, m_binding.unmarshal);
00674    M_ASN1_D2I_get(i, haveSignature.unmarshal);
00675    if ( haveSignature.value() )
00676    {
00677       M_ASN1_D2I_get(i, m_signature.unmarshal);
00678    }
00679    M_ASN1_D2I_get(i, haveKeyValue.unmarshal);
00680    if ( haveKeyValue.value() )
00681    {
00682       M_ASN1_D2I_get(i, m_keyValue.unmarshal);
00683    }
00684    M_ASN1_D2I_get(i, isVerified.unmarshal);
00685    m_verified = isVerified.value();
00686    if ( !asn1_Finish(&c) )
00687    {
00688       return 0;
00689    }
00690    *pp=c.p;
00691    m_initialized = true;
00692    return this;
00693   err: // needed by ASN.1 macros
00694    return 0;
00695 }

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