@ -106,6 +106,7 @@ func NewHandshakeParams() *HandshakeParams {
type HandshakeController struct {
pss * Pss
keyC map [ string ] chan [ ] string // adds a channel to report when a handshake succeeds
keyCMu sync . Mutex // protects keyC map
lock sync . Mutex
symKeyRequestTimeout time . Duration
symKeyExpiryTimeout time . Duration
@ -165,9 +166,9 @@ func (ctl *HandshakeController) validKeys(pubkeyid string, topic *Topic, in bool
for _ , key := range * keystore {
if key . limit <= key . count {
ctl . releaseKey ( * key . symKeyID , topic )
ctl . releaseKeyNoLock ( * key . symKeyID , topic )
} else if ! key . expiredAt . IsZero ( ) && key . expiredAt . Before ( now ) {
ctl . releaseKey ( * key . symKeyID , topic )
ctl . releaseKeyNoLock ( * key . symKeyID , topic )
} else {
validkeys = append ( validkeys , key . symKeyID )
}
@ -205,15 +206,23 @@ func (ctl *HandshakeController) updateKeys(pubkeyid string, topic *Topic, in boo
limit : limit ,
}
* keystore = append ( * keystore , storekey )
ctl . pss . mx . Lock ( )
ctl . pss . symKeyPool [ * storekey . symKeyID ] [ * topic ] . protected = true
ctl . pss . mx . Unlock ( )
}
for i := 0 ; i < len ( * keystore ) ; i ++ {
ctl . symKeyIndex [ * ( * keystore ) [ i ] . symKeyID ] = & ( ( * keystore ) [ i ] )
}
}
// Expire a symmetric key, making it elegible for garbage collection
func ( ctl * HandshakeController ) releaseKey ( symkeyid string , topic * Topic ) bool {
ctl . lock . Lock ( )
defer ctl . lock . Unlock ( )
return ctl . releaseKeyNoLock ( symkeyid , topic )
}
// Expire a symmetric key, making it eligible for garbage collection
func ( ctl * HandshakeController ) releaseKeyNoLock ( symkeyid string , topic * Topic ) bool {
if ctl . symKeyIndex [ symkeyid ] == nil {
log . Debug ( "no symkey" , "symkeyid" , symkeyid )
return false
@ -276,21 +285,18 @@ func (ctl *HandshakeController) clean() {
}
}
func ( ctl * HandshakeController ) getSymKey ( symkeyid string ) * handshakeKey {
ctl . lock . Lock ( )
defer ctl . lock . Unlock ( )
return ctl . symKeyIndex [ symkeyid ]
}
// Passed as a PssMsg handler for the topic handshake is activated on
// Handles incoming key exchange messages and
// ccunts message usage by symmetric key (expiry limit control)
// co unts message usage by symmetric key (expiry limit control)
// Only returns error if key handler fails
func ( ctl * HandshakeController ) handler ( msg [ ] byte , p * p2p . Peer , asymmetric bool , symkeyid string ) error {
if ! asymmetric {
if ctl . symKeyIndex [ symkeyid ] != nil {
if ctl . symKeyIndex [ symkeyid ] . count >= ctl . symKeyIndex [ symkeyid ] . limit {
return fmt . Errorf ( "discarding message using expired key: %s" , symkeyid )
}
ctl . symKeyIndex [ symkeyid ] . count ++
log . Trace ( "increment symkey recv use" , "symsymkeyid" , symkeyid , "count" , ctl . symKeyIndex [ symkeyid ] . count , "limit" , ctl . symKeyIndex [ symkeyid ] . limit , "receiver" , common . ToHex ( crypto . FromECDSAPub ( ctl . pss . PublicKey ( ) ) ) )
}
return nil
}
if asymmetric {
keymsg := & handshakeMsg { }
err := rlp . DecodeBytes ( msg , keymsg )
if err == nil {
@ -302,6 +308,28 @@ func (ctl *HandshakeController) handler(msg []byte, p *p2p.Peer, asymmetric bool
}
return nil
}
return ctl . registerSymKeyUse ( symkeyid )
}
func ( ctl * HandshakeController ) registerSymKeyUse ( symkeyid string ) error {
ctl . lock . Lock ( )
defer ctl . lock . Unlock ( )
symKey , ok := ctl . symKeyIndex [ symkeyid ]
if ! ok {
return nil
}
if symKey . count >= symKey . limit {
return fmt . Errorf ( "symetric key expired (id: %s)" , symkeyid )
}
symKey . count ++
receiver := common . ToHex ( crypto . FromECDSAPub ( ctl . pss . PublicKey ( ) ) )
log . Trace ( "increment symkey recv use" , "symsymkeyid" , symkeyid , "count" , symKey . count , "limit" , symKey . limit , "receiver" , receiver )
return nil
}
// Handle incoming key exchange message
// Add keys received from peer to store
@ -417,6 +445,8 @@ func (ctl *HandshakeController) sendKey(pubkeyid string, topic *Topic, keycount
// Enables callback for keys received from a key exchange request
func ( ctl * HandshakeController ) alertHandshake ( pubkeyid string , symkeys [ ] string ) chan [ ] string {
ctl . keyCMu . Lock ( )
defer ctl . keyCMu . Unlock ( )
if len ( symkeys ) > 0 {
if _ , ok := ctl . keyC [ pubkeyid ] ; ok {
ctl . keyC [ pubkeyid ] <- symkeys
@ -519,7 +549,7 @@ func (api *HandshakeAPI) GetHandshakeKeys(pubkeyid string, topic Topic, in bool,
// Returns the amount of messages the specified symmetric key
// is still valid for under the handshake scheme
func ( api * HandshakeAPI ) GetHandshakeKeyCapacity ( symkeyid string ) ( uint16 , error ) {
storekey := api . ctrl . symKeyIndex [ symkeyid ]
storekey := api . ctrl . getSymKey ( symkeyid )
if storekey == nil {
return 0 , fmt . Errorf ( "invalid symkey id %s" , symkeyid )
}
@ -529,7 +559,7 @@ func (api *HandshakeAPI) GetHandshakeKeyCapacity(symkeyid string) (uint16, error
// Returns the byte representation of the public key in ascii hex
// associated with the given symmetric key
func ( api * HandshakeAPI ) GetHandshakePublicKey ( symkeyid string ) ( string , error ) {
storekey := api . ctrl . symKeyIndex [ symkeyid ]
storekey := api . ctrl . getSymKey ( symkeyid )
if storekey == nil {
return "" , fmt . Errorf ( "invalid symkey id %s" , symkeyid )
}
@ -555,12 +585,8 @@ func (api *HandshakeAPI) ReleaseHandshakeKey(pubkeyid string, topic Topic, symke
// for message expiry control
func ( api * HandshakeAPI ) SendSym ( symkeyid string , topic Topic , msg hexutil . Bytes ) ( err error ) {
err = api . ctrl . pss . SendSym ( symkeyid , topic , msg [ : ] )
if api . ctrl . symKeyIndex [ symkeyid ] != nil {
if api . ctrl . symKeyIndex [ symkeyid ] . count >= api . ctrl . symKeyIndex [ symkeyid ] . limit {
return errors . New ( "attempted send with expired key" )
}
api . ctrl . symKeyIndex [ symkeyid ] . count ++
log . Trace ( "increment symkey send use" , "symkeyid" , symkeyid , "count" , api . ctrl . symKeyIndex [ symkeyid ] . count , "limit" , api . ctrl . symKeyIndex [ symkeyid ] . limit , "receiver" , common . ToHex ( crypto . FromECDSAPub ( api . ctrl . pss . PublicKey ( ) ) ) )
if otherErr := api . ctrl . registerSymKeyUse ( symkeyid ) ; otherErr != nil {
return otherErr
}
return err
}