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