00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "RSAPlaintextPK.h"
00019 #include "CODEX_Exceptions/BignumExceptions.h"
00020
00021 #include "timing.h"
00022
00023 using namespace CODEX_Ciphers;
00024
00025 RSAPlaintextPK::RSAPlaintextPK() :
00026 CODEX_ASN1::Base( false )
00027 {
00028 }
00029
00030 RSAPlaintextPK::RSAPlaintextPK( const CODEX_ASN1::SecureBigNumber& plaintext,
00031 const RSAPublicKey& publicKey,
00032 const CODEX_ASN1::Base& id,
00033 const HashFunction& hashFunc ) :
00034 CODEX_ASN1::Base( true )
00035 {
00036 if ( ! ( plaintext.initialized() &&
00037 publicKey.initialized() &&
00038 id.initialized() ) )
00039 {
00040 throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00041 }
00042 int Ln = BN_num_bytes( publicKey.n().value() );
00043 int ln = BN_num_bits( publicKey.n().value() );
00044 int Le = BN_num_bytes( publicKey.e().value() );
00045 int sublen = Le - 1;
00046 int k = Ln / sublen;
00047
00048 typedef vector< BIGNUM* > VBNType;
00049 VBNType vr;
00050
00051
00052 const BIGNUM * n = publicKey.n().value();
00053 const BIGNUM * s = plaintext.value();
00054 CODEX_ASN1::ustring* str = 0;
00055 unsigned char* buff = 0;
00056 BIGNUM * r = 0;
00057 RSACipherText* p1 = 0;
00058 RSACipherText* es = 0;
00059 BIGNUM * c = 0;
00060 BIGNUM * p2 = 0;
00061 BN_CTX * ctx = 0;
00062 try
00063 {
00064 ctx = BN_CTX_new();
00065 if ( NULL == ctx )
00066 {
00067 throw CODEX_Exceptions::BignumContextException( __FILE__ , __LINE__ );
00068 }
00069
00070 for ( int i = 0 ; i < k ; ++i )
00071 {
00072
00073 r = BN_new();
00074 if ( 0 == r )
00075 {
00076 throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00077 }
00078 do
00079 {
00080 if ( ! BN_rand_range( r, (BIGNUM*)n ) )
00081 {
00082 throw CODEX_Exceptions::BignumRandRangeException( __FILE__ ,
00083 __LINE__ );
00084 }
00085 }
00086 while ( 0 >= BN_cmp( r, BN_value_one() ) );
00087
00088 p1 = publicKey.encrypt( r );
00089 vr.push_back( r );
00090 r = 0;
00091 m_a.append( p1 );
00092 p1 = 0;
00093 }
00094 if ( vr.size() != k )
00095 {
00096 throw CODEX_Exceptions::IllegalIndexException( __FILE__ , __LINE__ );
00097 }
00098 if ( m_a.size() != k )
00099 {
00100 throw CODEX_Exceptions::IllegalIndexException( __FILE__ , __LINE__ );
00101 }
00102
00103 es = publicKey.encrypt( s );
00104
00105 unsigned int length = m_a.marshal(0);
00106 length += es->marshal(0);
00107 length += id.marshal(0);
00108
00109 buff = new unsigned char[length];
00110 unsigned char* pBuff = buff;
00111 m_a.marshal(&pBuff);
00112 es->marshal(&pBuff);
00113 id.marshal(&pBuff);
00114 str = hashFunc( CODEX_ASN1::ustring(buff,length), ln );
00115 delete [] buff;
00116 buff = 0;
00117 delete es;
00118 es = 0;
00119 for ( int i = 0 ; i < k ; ++i )
00120 {
00121 c = BN_new();
00122 if ( 0 == c )
00123 {
00124 throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00125 }
00126 if ( 0 == BN_bin2bn( str->data()+i*sublen, sublen, c ) )
00127 {
00128 throw CODEX_Exceptions::BignumBin2BNException( __FILE__ ,
00129 __LINE__ );
00130 }
00131
00132 p2 = BN_new();
00133 if ( 0 == p2 )
00134 {
00135 throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00136 }
00137 if ( ! BN_mod_exp( p2, s, c, n, ctx ) )
00138 {
00139 throw CODEX_Exceptions::BignumModExpException( __FILE__ ,
00140 __LINE__ );
00141 }
00142 if ( ! BN_mod_mul( p2, p2, vr[i], n, ctx ) )
00143 {
00144 throw CODEX_Exceptions::BignumModMulException( __FILE__ ,
00145 __LINE__ );
00146 }
00147 m_b.append( new CODEX_ASN1::BigNumber( p2 ) );
00148 p2 = 0;
00149 BN_free(c);
00150 c = 0;
00151 BN_clear_free(vr[i]);
00152 vr[i] = 0;
00153 }
00154 delete str;
00155 str = 0;
00156
00157 BN_CTX_free(ctx);
00158 }
00159 catch ( ... )
00160 {
00161 if ( 0 != ctx ) BN_CTX_free( ctx );
00162 if ( 0 != r ) BN_clear_free( r );
00163 if ( 0 != p1 ) delete p1;
00164 if ( 0 != es ) delete es;
00165 if ( 0 != c ) BN_free( c );
00166 if ( 0 != str ) delete str;
00167 if ( 0 != buff ) delete [] buff;
00168 for ( VBNType::iterator itr = vr.begin() ; itr != vr.end() ; ++itr )
00169 {
00170 BN_clear_free( *itr );
00171 }
00172 throw;
00173 }
00174 }
00175
00176 RSAPlaintextPK::RSAPlaintextPK( const RSAPlaintextPK& aPPK ) :
00177 CODEX_ASN1::Base( aPPK.m_initialized ),
00178 m_a( aPPK.m_a ),
00179 m_b( aPPK.m_b )
00180 {
00181 }
00182
00183 RSAPlaintextPK::~RSAPlaintextPK()
00184 {
00185 }
00186
00187 void
00188 RSAPlaintextPK::operator=( const RSAPlaintextPK& aPPK )
00189 {
00190 m_initialized = aPPK.m_initialized;
00191 m_a = aPPK.m_a;
00192 m_b = aPPK.m_b;
00193 }
00194
00195 bool
00196 RSAPlaintextPK::verify( const RSACipherText& ciphertext,
00197 const RSAPublicKey& publicKey,
00198 const CODEX_ASN1::Base& id,
00199 const HashFunction& hashFunc ) const
00200 {
00201 if ( ! ( ciphertext.initialized() &&
00202 publicKey.initialized() &&
00203 id.initialized() ) )
00204 {
00205 throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00206 }
00207
00208 int Ln = BN_num_bytes( publicKey.n().value() );
00209 int ln = BN_num_bits( publicKey.n().value() );
00210 int Le = BN_num_bytes( publicKey.e().value() );
00211 int sublen = Le - 1;
00212 int k = Ln / sublen;
00213
00214 if ( m_a.size() != k )
00215 {
00216 return false;
00217 }
00218 if ( m_b.size() != k )
00219 {
00220 return false;
00221 }
00222
00223 for ( int i = 0 ; i < k ; ++i )
00224 {
00225 if ( BN_is_zero( m_a.element(i)->value() ) )
00226 {
00227 return false;
00228 }
00229 }
00230
00231 #ifdef TIMING
00232 RSAPPKTimer.start();
00233 #endif
00234 const BIGNUM * e = publicKey.e().value();
00235 const BIGNUM * n = publicKey.n().value();
00236 const BIGNUM * ct = ciphertext.value();
00237 CODEX_ASN1::ustring* str = 0;
00238 unsigned char* buff = 0;
00239 BIGNUM * c = 0;
00240 BIGNUM * ep2 = 0;
00241 BIGNUM * ecp1 = 0;
00242 BN_CTX * ctx = 0;
00243 try
00244 {
00245 ctx = BN_CTX_new();
00246 if ( 0 == ctx )
00247 {
00248 throw CODEX_Exceptions::BignumContextException( __FILE__ , __LINE__ );
00249 }
00250
00251 unsigned int length = m_a.marshal(0);
00252 length += ciphertext.marshal(0);
00253 length += id.marshal(0);
00254 buff = new unsigned char[length];
00255 unsigned char* pBuff = buff;
00256 m_a.marshal(&pBuff);
00257 ciphertext.marshal(&pBuff);
00258 id.marshal(&pBuff);
00259 str = hashFunc( CODEX_ASN1::ustring(buff,length), ln );
00260 delete [] buff;
00261 buff = 0;
00262
00263 bool retVal = true;
00264 for ( int i = 0 ;
00265 retVal && ( i < k ) ;
00266 ++i )
00267 {
00268 c = BN_new();
00269 if ( 0 == c )
00270 {
00271 throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00272 }
00273 if ( 0 == BN_bin2bn( str->data()+i*sublen, sublen, c ) )
00274 {
00275 throw CODEX_Exceptions::BignumBin2BNException( __FILE__ ,
00276 __LINE__ );
00277 }
00278
00279 ep2 = BN_new();
00280 if ( 0 == ep2 )
00281 {
00282 throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00283 }
00284 if ( ! BN_mod_exp( ep2, m_b.element(i)->value(), e, n, ctx ) )
00285 {
00286 throw CODEX_Exceptions::BignumModExpException( __FILE__ ,
00287 __LINE__ );
00288 }
00289
00290 ecp1 = BN_new();
00291 if ( 0 == ecp1 )
00292 {
00293 throw CODEX_Exceptions::BignumNullException( __FILE__ , __LINE__ );
00294 }
00295 if ( ! BN_mod_exp( ecp1, ct, c, n, ctx ) )
00296 {
00297 throw CODEX_Exceptions::BignumModExpException( __FILE__ ,
00298 __LINE__ );
00299 }
00300 if ( ! BN_mod_mul( ecp1, ecp1, m_a.element(i)->value(), n, ctx ) )
00301 {
00302 throw CODEX_Exceptions::BignumModMulException( __FILE__ ,
00303 __LINE__ );
00304 }
00305 BN_free( c );
00306 c = 0;
00307
00308 if ( 0 != BN_cmp( ep2, ecp1 ) )
00309 {
00310 retVal = false;
00311 }
00312 BN_free( ep2 ); ep2 = 0;
00313 BN_free( ecp1 ); ecp1 = 0;
00314 }
00315
00316 delete str;
00317 str = 0;
00318 BN_CTX_free( ctx );
00319 #ifdef TIMING
00320 RSAPPKTimer.stop();
00321 #endif
00322 return retVal;
00323 }
00324 catch ( ... )
00325 {
00326 if ( 0 != ctx ) BN_CTX_free( ctx );
00327 if ( 0 != str ) delete str;
00328 if ( 0 != buff ) delete [] buff;
00329 if ( 0 != c ) BN_free( c );
00330 if ( 0 != ep2 ) BN_free( ep2 );
00331 if ( 0 != ecp1 ) BN_free( ecp1 );
00332 #ifdef TIMING
00333 RSAPPKTimer.stop();
00334 #endif
00335 throw;
00336 }
00337 }
00338
00339 int
00340 RSAPlaintextPK::marshal( unsigned char ** pp ) const
00341 {
00342 int r=0;
00343 int ret=0;
00344 unsigned char * p;
00345
00346 ret += m_a.marshal(0);
00347 ret += m_b.marshal(0);
00348 M_ASN1_I2D_seq_total();
00349 m_a.marshal(&p);
00350 m_b.marshal(&p);
00351 M_ASN1_I2D_finish();
00352 }
00353
00354 void*
00355 RSAPlaintextPK::unmarshal( void* bogus, unsigned char ** pp, long length )
00356 {
00357 if ( m_initialized )
00358 {
00359 return NULL;
00360 }
00361 if ( (NULL == pp) || (NULL == *pp) )
00362 {
00363 return NULL;
00364 }
00365
00366 ASN1_CTX c;
00367 c.pp = pp;
00368 c.q = *pp;
00369 c.error = ERR_R_NESTED_ASN1_ERROR;
00370 int i;
00371
00372 M_ASN1_D2I_Init();
00373 M_ASN1_D2I_start_sequence();
00374 M_ASN1_D2I_get(i, m_a.unmarshal);
00375 M_ASN1_D2I_get(i, m_b.unmarshal);
00376 if ( !asn1_Finish(&c) )
00377 {
00378 return NULL;
00379 }
00380 *pp=c.p;
00381 m_initialized = true;
00382 return this;
00383 err:
00384 return NULL;
00385 }