#define PRIME_LEN 96
+#define DH_PRIVKEY_LEN_MIN 16
+#define DH_PRIVKEY_LEN 20
+
static const uint8_t dh_P[PRIME_LEN] =
{
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
tr_bool mySecretIsSet;
uint8_t myPublicKey[KEY_LEN];
uint8_t mySecret[KEY_LEN];
+ DH * dh;
};
/**
} \
} while( 0 )
-static DH*
-getSharedDH( void )
+static void
+ensureKeyExists( tr_crypto * crypto)
{
- static DH * dh = NULL;
-
- if( dh == NULL )
+ if( crypto->dh == NULL )
{
- dh = DH_new( );
+ int len, offset;
+ DH * dh = DH_new( );
dh->p = BN_bin2bn( dh_P, sizeof( dh_P ), NULL );
if( dh->p == NULL )
if( dh->g == NULL )
logErrorFromSSL( );
+ /* private DH value: strong random BN of DH_PRIVKEY_LEN*8 bits */
+ dh->priv_key = BN_new( );
+ do {
+ if( BN_rand( dh->priv_key, DH_PRIVKEY_LEN * 8, -1, 0 ) != 1 )
+ logErrorFromSSL( );
+ } while ( BN_num_bits( dh->priv_key ) < DH_PRIVKEY_LEN_MIN * 8 );
+
if( !DH_generate_key( dh ) )
logErrorFromSSL( );
- }
- return dh;
+ /* DH can generate key sizes that are smaller than the size of
+ P with exponentially decreasing probability, in which case
+ the msb's of myPublicKey need to be zeroed appropriately. */
+ len = BN_num_bytes( dh->pub_key );
+ offset = KEY_LEN - len;
+ assert( len <= KEY_LEN );
+ memset( crypto->myPublicKey, 0, offset );
+ BN_bn2bin( dh->pub_key, crypto->myPublicKey + offset );
+
+ crypto->dh = dh;
+ }
}
tr_crypto *
tr_cryptoNew( const uint8_t * torrentHash,
int isIncoming )
{
- int len, offset;
tr_crypto * crypto;
- DH * dh = getSharedDH( );
crypto = tr_new0( tr_crypto, 1 );
crypto->isIncoming = isIncoming ? 1 : 0;
tr_cryptoSetTorrentHash( crypto, torrentHash );
-
- /* DH can generate key sizes that are smaller than the size of
- P with exponentially decreasing probability, in which case
- the msb's of myPublicKey need to be zeroed appropriately. */
- len = DH_size( dh );
- offset = KEY_LEN - len;
- assert( len <= KEY_LEN );
- memset( crypto->myPublicKey, 0, offset );
- BN_bn2bin( dh->pub_key, crypto->myPublicKey + offset );
+ crypto->dh = NULL;
return crypto;
}
void
tr_cryptoFree( tr_crypto * crypto )
{
+ if( crypto->dh != NULL )
+ DH_free( crypto->dh );
tr_free( crypto );
}
int len;
uint8_t secret[KEY_LEN];
BIGNUM * bn = BN_bin2bn( peerPublicKey, KEY_LEN, NULL );
- DH * dh = getSharedDH( );
+ DH * dh;
+
+ ensureKeyExists( crypto );
+ dh = crypto->dh;
assert( DH_size( dh ) == KEY_LEN );
tr_cryptoGetMyPublicKey( const tr_crypto * crypto,
int * setme_len )
{
+ ensureKeyExists( (tr_crypto *) crypto );
*setme_len = KEY_LEN;
return crypto->myPublicKey;
}