00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef __CODEX_VSS_COMBINATORIC_H__
00019 #define __CODEX_VSS_COMBINATORIC_H__
00020
00021 #include <fstream>
00022
00023 #include "CODEX_ASN1/SecureBigNumber.h"
00024 #include "CODEX_ASN1/Integer.h"
00025 #include "CODEX_Exceptions/BignumExceptions.h"
00026 #include "CODEX_Exceptions/FileExceptions.h"
00027 #include "ShareFunctional.h"
00028 #include "ShareSet.h"
00029 #include "CombinatoricScenario.h"
00030 #include "Range.h"
00031
00032 namespace CODEX_VSS
00033 {
00037 template< int N , int T >
00038 struct choose
00039 {
00045 static const unsigned int value = N*choose<N-1,T-1>::value/T;
00046 };
00047
00049 template< int N >
00050 struct choose<N,0>
00051 {
00053 static const unsigned int value = 1;
00054 };
00055
00057 template< int N >
00058 struct choose<N,1>
00059 {
00061 static const unsigned int value = N;
00062 };
00063
00068 template< unsigned int NumT , unsigned int ThreshT >
00069 class Combinatoric : public CODEX_ASN1::Base
00070 {
00071 public :
00073 typedef CODEX_ASN1::SecureBigNumber ValueType;
00074
00079 static const unsigned int NumShares = choose<NumT,ThreshT-1>::value+1;
00080
00082 Combinatoric();
00083
00085 Combinatoric( const Combinatoric<NumT,ThreshT>& aOther );
00086
00088 Combinatoric( const ShareSet< Combinatoric<NumT,ThreshT> >& shareSet,
00089 unsigned int partNum );
00090
00092 virtual ~Combinatoric();
00093
00095 void operator=( const Combinatoric<NumT,ThreshT>& aOther );
00096
00104 void operator+=( const Combinatoric<NumT,ThreshT>& aOther );
00105
00111 void setShare( unsigned int i,
00112 const CODEX_ASN1::SecureBigNumber& share );
00113
00118 const CODEX_ASN1::SecureBigNumber& share( unsigned int i ) const;
00119
00121 unsigned int count() const;
00122
00129 void apply( const ShareFunctional& func,
00130 Combinatoric<NumT,ThreshT>& result ) const;
00131
00137 void recover( CODEX_ASN1::SecureBigNumber& result ) const;
00138
00139 int marshal( unsigned char ** pp ) const;
00140
00141 void* unmarshal( void* bogus, unsigned char ** pp, long length );
00142
00144 void toFile( const char* fname ) const;
00145
00147 void* fromFile( const char* fname );
00148
00149 private :
00150 CODEX_ASN1::SecureBigNumber m_shares[ NumShares ];
00151 };
00152
00153 template< unsigned int NumT , unsigned int ThreshT >
00154 Combinatoric<NumT,ThreshT>::Combinatoric() :
00155 CODEX_ASN1::Base( false )
00156 {
00157 }
00158
00159 template< unsigned int NumT , unsigned int ThreshT >
00160 Combinatoric<NumT,ThreshT>::Combinatoric(
00161 const Combinatoric<NumT,ThreshT>& aOther ) :
00162 CODEX_ASN1::Base( aOther.m_initialized )
00163 {
00164 for ( unsigned int i = 0 ; i < NumShares ; ++i )
00165 {
00166 m_shares[i] = aOther.m_shares[i];
00167 }
00168 }
00169
00170 template< unsigned int NumT , unsigned int ThreshT >
00171 Combinatoric<NumT,ThreshT>::Combinatoric(
00172 const ShareSet< Combinatoric<NumT,ThreshT> >& shareSet,
00173 unsigned int partNum ) :
00174 CODEX_ASN1::Base( true )
00175 {
00176 typedef CombinatoricScenario<NumT,ThreshT-1> CSType;
00177 CSType* cs = CSType::instance();
00178 for ( unsigned int i = 0 ; i < NumShares ; ++i )
00179 {
00180
00181 if ( ( NumShares == (i+1) ) ||
00182 ( ! cs->inScenario( partNum, i ) ) )
00183 {
00184 m_shares[i] = shareSet(i);
00185 }
00186 }
00187 }
00188
00189 template< unsigned int NumT , unsigned int ThreshT >
00190 Combinatoric<NumT,ThreshT>::~Combinatoric()
00191 {
00192 }
00193
00194 template< unsigned int NumT , unsigned int ThreshT >
00195 void
00196 Combinatoric<NumT,ThreshT>::operator=(
00197 const Combinatoric<NumT,ThreshT>& aOther )
00198 {
00199 m_initialized = aOther.m_initialized;
00200 for ( unsigned int i = 0 ; i < NumShares ; ++i )
00201 {
00202 m_shares[i] = aOther.m_shares[i];
00203 }
00204 }
00205
00206 template< unsigned int NumT , unsigned int ThreshT >
00207 void
00208 Combinatoric<NumT,ThreshT>::operator+=(
00209 const Combinatoric<NumT,ThreshT>& aOther )
00210 {
00211 if ( ! aOther.m_initialized )
00212 {
00213 return;
00214 }
00215 m_initialized = true;
00216 for ( unsigned int i = 0 ; i < NumShares ; ++i )
00217 {
00218 if ( ! m_shares[i].initialized() )
00219 {
00220 m_shares[i] = aOther.m_shares[i];
00221 }
00222 }
00223 }
00224
00225 template< unsigned int NumT , unsigned int ThreshT >
00226 void
00227 Combinatoric<NumT,ThreshT>::setShare(
00228 unsigned int i,
00229 const CODEX_ASN1::SecureBigNumber& share )
00230 {
00231 if ( i >= NumShares )
00232 {
00233 throw CODEX_Exceptions::IllegalIndexException( __FILE__ , __LINE__ );
00234 }
00235 m_shares[i] = share;
00236 m_initialized = true;
00237 }
00238
00239 template< unsigned int NumT , unsigned int ThreshT >
00240 const CODEX_ASN1::SecureBigNumber&
00241 Combinatoric<NumT,ThreshT>::share( unsigned int i ) const
00242 {
00243 if ( i >= NumShares )
00244 {
00245 throw CODEX_Exceptions::IllegalIndexException( __FILE__ , __LINE__ );
00246 }
00247 return m_shares[i];
00248 }
00249
00250 template< unsigned int NumT , unsigned int ThreshT >
00251 unsigned int
00252 Combinatoric<NumT,ThreshT>::count() const
00253 {
00254 unsigned int retVal = 0;
00255 for ( unsigned int i = 0 ; i < NumShares ; ++i )
00256 {
00257 if ( m_shares[i].initialized() )
00258 {
00259 ++retVal;
00260 }
00261 }
00262 return retVal;
00263 }
00264
00265 template< unsigned int NumT , unsigned int ThreshT >
00266 void
00267 Combinatoric<NumT,ThreshT>::apply( const ShareFunctional& func,
00268 Combinatoric<NumT,ThreshT>& result )
00269 const
00270 {
00271 result.m_initialized = true;
00272 for ( unsigned int i = 0 ; i < NumShares ; ++i )
00273 {
00274 if ( m_shares[i].initialized() )
00275 {
00276 func( m_shares[i] , result.m_shares[i] );
00277 }
00278 }
00279 }
00280
00281 template< unsigned int NumT , unsigned int ThreshT >
00282 void
00283 Combinatoric<NumT,ThreshT>::recover( CODEX_ASN1::SecureBigNumber& result )
00284 const
00285 {
00286 if ( result.initialized() )
00287 {
00288 result = CODEX_ASN1::SecureBigNumber();
00289 }
00290 if ( ! m_initialized )
00291 {
00292 return;
00293 }
00294 for ( unsigned int i = 0 ; i < NumShares ; ++i )
00295 {
00296 if ( ! m_shares[i].initialized() )
00297 {
00298 return;
00299 }
00300 }
00301 BIGNUM * r = 0;
00302 try
00303 {
00304 r = BN_new();
00305 if ( 0 == r )
00306 {
00307 throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00308 }
00309 if ( ! BN_zero(r) )
00310 {
00311 throw CODEX_Exceptions::BignumSetWordException( __FILE__ ,
00312 __LINE__ );
00313 }
00314 for ( unsigned int i = 0 ; i < NumShares ; ++i )
00315 {
00316 if ( ! BN_add( r, r, m_shares[i].value() ) )
00317 {
00318 throw CODEX_Exceptions::BignumAddException( __FILE__ ,
00319 __LINE__ );
00320 }
00321 }
00322 result = CODEX_ASN1::SecureBigNumber( r );
00323 }
00324 catch ( ... )
00325 {
00326 if ( 0 != r ) BN_clear_free(r);
00327 throw;
00328 }
00329 }
00330
00331 template< unsigned int NumT , unsigned int ThreshT >
00332 int
00333 Combinatoric<NumT,ThreshT>::marshal( unsigned char ** pp ) const
00334 {
00335 int r=0;
00336 int ret=0;
00337 unsigned char * p;
00338
00339 CODEX_ASN1::Integer isSet[NumShares];
00340 for ( unsigned int counter = 0 ; counter < NumShares ; ++counter )
00341 {
00342 isSet[counter] =
00343 CODEX_ASN1::Integer( m_shares[counter].initialized() ? 1 : 0 );
00344 }
00345 for ( unsigned int counter = 0 ; counter < NumShares ; ++counter )
00346 {
00347 ret += isSet[counter].marshal(0);
00348 if ( isSet[counter].value() )
00349 {
00350 ret += m_shares[counter].marshal(0);
00351 }
00352 }
00353 M_ASN1_I2D_seq_total();
00354 for ( unsigned int counter = 0 ; counter < NumShares ; ++counter )
00355 {
00356 isSet[counter].marshal(&p);
00357 if ( isSet[counter].value() )
00358 {
00359 m_shares[counter].marshal(&p);
00360 }
00361 }
00362 M_ASN1_I2D_finish();
00363 }
00364
00365 template< unsigned int NumT , unsigned int ThreshT >
00366 void*
00367 Combinatoric<NumT,ThreshT>::unmarshal( void* bogus,
00368 unsigned char ** pp,
00369 long length )
00370 {
00371 if ( m_initialized )
00372 {
00373 return 0;
00374 }
00375 if ( (0 == pp) || (0 == *pp) )
00376 {
00377 return 0;
00378 }
00379 ASN1_CTX c;
00380 c.pp = pp;
00381 c.q = *pp;
00382 c.error = ERR_R_NESTED_ASN1_ERROR;
00383 int i;
00384
00385 M_ASN1_D2I_Init();
00386 M_ASN1_D2I_start_sequence();
00387 for ( unsigned int counter = 0 ; counter < NumShares ; ++counter )
00388 {
00389 CODEX_ASN1::Integer isSet;
00390 M_ASN1_D2I_get(i, isSet.unmarshal);
00391 if ( isSet.value() )
00392 {
00393 M_ASN1_D2I_get(i, m_shares[counter].unmarshal);
00394 }
00395 }
00396 if ( !asn1_Finish(&c) )
00397 {
00398 return 0;
00399 }
00400 *pp=c.p;
00401 m_initialized = true;
00402 return this;
00403 err:
00404 return 0;
00405 }
00406
00407 template< unsigned int NumT , unsigned int ThreshT >
00408 void
00409 Combinatoric<NumT,ThreshT>::toFile( const char* fname ) const
00410 {
00411 int length = marshal(0);
00412 if ( 0 == length ) return;
00413 unsigned char* buff = new unsigned char[length];
00414 unsigned char* p = buff;
00415 marshal(&p);
00416 ofstream os(fname);
00417 if ( ! os.is_open() )
00418 {
00419 delete [] buff;
00420 throw CODEX_Exceptions::FileCannotCreateException( __FILE__ ,
00421 __LINE__ ,
00422 fname );
00423 }
00424 for ( int i = 0 ; i < length ; ++i )
00425 {
00426 os << buff[i];
00427 }
00428 os.close();
00429 delete [] buff;
00430 }
00431
00432 template< unsigned int NumT , unsigned int ThreshT >
00433 void*
00434 Combinatoric<NumT,ThreshT>::fromFile( const char* fname )
00435 {
00436 ifstream is(fname);
00437 if ( ! is.is_open() )
00438 {
00439 throw CODEX_Exceptions::FileCannotOpenException( __FILE__ ,
00440 __LINE__ ,
00441 fname );
00442 }
00443 string s;
00444 char ch;
00445 while ( is.get(ch) )
00446 {
00447 s.push_back(ch);
00448 }
00449
00450
00451 unsigned int length = s.length();
00452 unsigned char* p = new unsigned char[length];
00453 unsigned char* pOrig = p;
00454
00455 for ( unsigned int i = 0 ; i < length ; ++i )
00456 {
00457 p[i] = s.data()[i];
00458 }
00459 return unmarshal(0,&p,length);
00460 delete [] pOrig;
00461 }
00462
00463
00465 template< unsigned int NumT , unsigned int ThreshT >
00466 class ShareSet< Combinatoric<NumT,ThreshT> >
00467 {
00468 public :
00470 typedef Combinatoric<NumT,ThreshT> ShareType;
00471
00473 ShareSet() {}
00474
00476 ShareSet( const ShareSet< ShareType >& aOther ) :
00477 m_shares( aOther.m_shares )
00478 {}
00479
00481 void operator=( const ShareSet< ShareType >& aOther )
00482 {
00483 m_shares = aOther.m_shares;
00484 }
00485
00494 const typename ShareType::ValueType& operator()( unsigned int i )
00495 const
00496 {
00497 return m_shares.share(i);
00498 }
00499
00507 void setShare( unsigned int i,
00508 const typename ShareType::ValueType& share )
00509 {
00510 m_shares.setShare(i,share);
00511 }
00512
00514 void addShare( const ShareType& share )
00515 {
00516 m_shares += share;
00517 }
00518
00524 void recover( CODEX_ASN1::SecureBigNumber& result ) const
00525 {
00526 return m_shares.recover( result );
00527 }
00528
00538 bool shouldHave( unsigned int shareNum, unsigned int partNum ) const
00539 {
00540 typedef CombinatoricScenario<NumT,ThreshT-1> CSType;
00541 CSType* cs = CSType::instance();
00542 if ( shareNum + 1 == ShareType::NumShares )
00543 {
00544 return true;
00545 }
00546 return ( ! cs->inScenario( partNum, shareNum ) );
00547 }
00548
00549 private :
00550 ShareType m_shares;
00551 };
00552
00554 template< unsigned int NumT , unsigned int ThreshT >
00555 class ShareSplitting< Combinatoric<NumT,ThreshT> >
00556 {
00557 public :
00559 typedef Combinatoric<NumT,ThreshT> ShareType;
00560
00562 const static unsigned int NumShares = ShareType::NumShares;
00563
00573 static void split( const BIGNUM* secret,
00574 ShareSet< ShareType >& shareSet,
00575 const Range& range )
00576 {
00577 const BIGNUM * minVal = range.min();
00578 const BIGNUM * maxVal = range.max();
00579 BIGNUM * m = 0;
00580 BIGNUM * temp = 0;
00581 BIGNUM * total = 0;
00582 BIGNUM * remainder = 0;
00583 try
00584 {
00585 m = BN_new();
00586 if ( 0 == m )
00587 {
00588 throw CODEX_Exceptions::BignumNullException( __FILE__ ,
00589 __LINE__ );
00590 }
00591 total = BN_new();
00592 if ( 0 == total )
00593 {
00594 throw CODEX_Exceptions::BignumNullException( __FILE__ ,
00595 __LINE__ );
00596 }
00597 remainder = BN_new();
00598 if ( 0 == remainder )
00599 {
00600 throw CODEX_Exceptions::BignumNullException( __FILE__ ,
00601 __LINE__ );
00602 }
00603
00604 if ( ! BN_sub( m, maxVal, minVal ) )
00605 {
00606 throw CODEX_Exceptions::BignumSubException( __FILE__ ,
00607 __LINE__ );
00608 }
00609 if ( ! BN_add( m, m, BN_value_one() ) )
00610 {
00611 throw CODEX_Exceptions::BignumAddException( __FILE__ ,
00612 __LINE__ );
00613 }
00614
00615 for ( unsigned int i = 0 ; i < NumShares - 1 ; ++i )
00616 {
00617 temp = BN_new();
00618 if ( 0 == temp )
00619 {
00620 throw CODEX_Exceptions::BignumNullException( __FILE__ ,
00621 __LINE__ );
00622 }
00623 if ( ! BN_rand_range( temp, m ) )
00624 {
00625 throw
00626 CODEX_Exceptions::BignumRandRangeException( __FILE__ ,
00627 __LINE__ );
00628 }
00629 if ( ! BN_add( temp, temp, minVal ) )
00630 {
00631 throw CODEX_Exceptions::BignumAddException( __FILE__ ,
00632 __LINE__ );
00633 }
00634
00635 if ( ! BN_add( total, total, temp ) )
00636 {
00637 throw CODEX_Exceptions::BignumAddException( __FILE__ ,
00638 __LINE__ );
00639 }
00640 shareSet.setShare(i,ShareType::ValueType(temp));
00641 temp = 0;
00642 }
00643
00644 if ( ! BN_sub( remainder, secret, total ) )
00645 {
00646 throw CODEX_Exceptions::BignumSubException( __FILE__ ,
00647 __LINE__ );
00648 }
00649 shareSet.setShare(NumShares-1,ShareType::ValueType(remainder));
00650 remainder = 0;
00651 BN_clear_free(total);
00652 BN_free(m);
00653 }
00654 catch ( ... )
00655 {
00656 if ( 0 != m ) BN_free(m);
00657 if ( 0 != temp ) BN_clear_free(temp);
00658 if ( 0 != total ) BN_clear_free(total);
00659 if ( 0 != remainder ) BN_clear_free(remainder);
00660 throw;
00661 }
00662 }
00663 };
00664
00665 }
00666
00667 #endif