github.com/FUSIONFoundation/efsn@v3.6.2-0.20200916075423-dbb5dd5d2cc7+incompatible/swarm/pss/pss.go (about)

     1  // Copyright 2018 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package pss
    18  
    19  import (
    20  	"bytes"
    21  	"context"
    22  	"crypto/ecdsa"
    23  	"crypto/rand"
    24  	"errors"
    25  	"fmt"
    26  	"sync"
    27  	"time"
    28  
    29  	"github.com/FusionFoundation/efsn/common"
    30  	"github.com/FusionFoundation/efsn/crypto"
    31  	"github.com/FusionFoundation/efsn/metrics"
    32  	"github.com/FusionFoundation/efsn/p2p"
    33  	"github.com/FusionFoundation/efsn/p2p/discover"
    34  	"github.com/FusionFoundation/efsn/p2p/protocols"
    35  	"github.com/FusionFoundation/efsn/rpc"
    36  	"github.com/FusionFoundation/efsn/swarm/log"
    37  	"github.com/FusionFoundation/efsn/swarm/network"
    38  	"github.com/FusionFoundation/efsn/swarm/pot"
    39  	"github.com/FusionFoundation/efsn/swarm/storage"
    40  	whisper "github.com/FusionFoundation/efsn/whisper/whisperv5"
    41  )
    42  
    43  const (
    44  	defaultPaddingByteSize     = 16
    45  	DefaultMsgTTL              = time.Second * 120
    46  	defaultDigestCacheTTL      = time.Second * 10
    47  	defaultSymKeyCacheCapacity = 512
    48  	digestLength               = 32 // byte length of digest used for pss cache (currently same as swarm chunk hash)
    49  	defaultWhisperWorkTime     = 3
    50  	defaultWhisperPoW          = 0.0000000001
    51  	defaultMaxMsgSize          = 1024 * 1024
    52  	defaultCleanInterval       = time.Second * 60 * 10
    53  	defaultOutboxCapacity      = 100000
    54  	pssProtocolName            = "pss"
    55  	pssVersion                 = 2
    56  	hasherCount                = 8
    57  )
    58  
    59  var (
    60  	addressLength = len(pot.Address{})
    61  )
    62  
    63  // cache is used for preventing backwards routing
    64  // will also be instrumental in flood guard mechanism
    65  // and mailbox implementation
    66  type pssCacheEntry struct {
    67  	expiresAt time.Time
    68  }
    69  
    70  // abstraction to enable access to p2p.protocols.Peer.Send
    71  type senderPeer interface {
    72  	Info() *p2p.PeerInfo
    73  	ID() discover.NodeID
    74  	Address() []byte
    75  	Send(context.Context, interface{}) error
    76  }
    77  
    78  // per-key peer related information
    79  // member `protected` prevents garbage collection of the instance
    80  type pssPeer struct {
    81  	lastSeen  time.Time
    82  	address   *PssAddress
    83  	protected bool
    84  }
    85  
    86  // Pss configuration parameters
    87  type PssParams struct {
    88  	MsgTTL              time.Duration
    89  	CacheTTL            time.Duration
    90  	privateKey          *ecdsa.PrivateKey
    91  	SymKeyCacheCapacity int
    92  	AllowRaw            bool // If true, enables sending and receiving messages without builtin pss encryption
    93  }
    94  
    95  // Sane defaults for Pss
    96  func NewPssParams() *PssParams {
    97  	return &PssParams{
    98  		MsgTTL:              DefaultMsgTTL,
    99  		CacheTTL:            defaultDigestCacheTTL,
   100  		SymKeyCacheCapacity: defaultSymKeyCacheCapacity,
   101  	}
   102  }
   103  
   104  func (params *PssParams) WithPrivateKey(privatekey *ecdsa.PrivateKey) *PssParams {
   105  	params.privateKey = privatekey
   106  	return params
   107  }
   108  
   109  // Toplevel pss object, takes care of message sending, receiving, decryption and encryption, message handler dispatchers and message forwarding.
   110  //
   111  // Implements node.Service
   112  type Pss struct {
   113  	*network.Kademlia                   // we can get the Kademlia address from this
   114  	privateKey        *ecdsa.PrivateKey // pss can have it's own independent key
   115  	w                 *whisper.Whisper  // key and encryption backend
   116  	auxAPIs           []rpc.API         // builtins (handshake, test) can add APIs
   117  
   118  	// sending and forwarding
   119  	fwdPool         map[string]*protocols.Peer // keep track of all peers sitting on the pssmsg routing layer
   120  	fwdPoolMu       sync.RWMutex
   121  	fwdCache        map[pssDigest]pssCacheEntry // checksum of unique fields from pssmsg mapped to expiry, cache to determine whether to drop msg
   122  	fwdCacheMu      sync.RWMutex
   123  	cacheTTL        time.Duration // how long to keep messages in fwdCache (not implemented)
   124  	msgTTL          time.Duration
   125  	paddingByteSize int
   126  	capstring       string
   127  	outbox          chan *PssMsg
   128  
   129  	// keys and peers
   130  	pubKeyPool                 map[string]map[Topic]*pssPeer // mapping of hex public keys to peer address by topic.
   131  	pubKeyPoolMu               sync.RWMutex
   132  	symKeyPool                 map[string]map[Topic]*pssPeer // mapping of symkeyids to peer address by topic.
   133  	symKeyPoolMu               sync.RWMutex
   134  	symKeyDecryptCache         []*string // fast lookup of symkeys recently used for decryption; last used is on top of stack
   135  	symKeyDecryptCacheCursor   int       // modular cursor pointing to last used, wraps on symKeyDecryptCache array
   136  	symKeyDecryptCacheCapacity int       // max amount of symkeys to keep.
   137  
   138  	// message handling
   139  	handlers   map[Topic]map[*Handler]bool // topic and version based pss payload handlers. See pss.Handle()
   140  	handlersMu sync.RWMutex
   141  	allowRaw   bool
   142  	hashPool   sync.Pool
   143  
   144  	// process
   145  	quitC chan struct{}
   146  }
   147  
   148  func (p *Pss) String() string {
   149  	return fmt.Sprintf("pss: addr %x, pubkey %v", p.BaseAddr(), common.ToHex(crypto.FromECDSAPub(&p.privateKey.PublicKey)))
   150  }
   151  
   152  // Creates a new Pss instance.
   153  //
   154  // In addition to params, it takes a swarm network Kademlia
   155  // and a FileStore storage for message cache storage.
   156  func NewPss(k *network.Kademlia, params *PssParams) (*Pss, error) {
   157  	if params.privateKey == nil {
   158  		return nil, errors.New("missing private key for pss")
   159  	}
   160  	cap := p2p.Cap{
   161  		Name:    pssProtocolName,
   162  		Version: pssVersion,
   163  	}
   164  	ps := &Pss{
   165  		Kademlia:   k,
   166  		privateKey: params.privateKey,
   167  		w:          whisper.New(&whisper.DefaultConfig),
   168  		quitC:      make(chan struct{}),
   169  
   170  		fwdPool:         make(map[string]*protocols.Peer),
   171  		fwdCache:        make(map[pssDigest]pssCacheEntry),
   172  		cacheTTL:        params.CacheTTL,
   173  		msgTTL:          params.MsgTTL,
   174  		paddingByteSize: defaultPaddingByteSize,
   175  		capstring:       cap.String(),
   176  		outbox:          make(chan *PssMsg, defaultOutboxCapacity),
   177  
   178  		pubKeyPool:                 make(map[string]map[Topic]*pssPeer),
   179  		symKeyPool:                 make(map[string]map[Topic]*pssPeer),
   180  		symKeyDecryptCache:         make([]*string, params.SymKeyCacheCapacity),
   181  		symKeyDecryptCacheCapacity: params.SymKeyCacheCapacity,
   182  
   183  		handlers: make(map[Topic]map[*Handler]bool),
   184  		allowRaw: params.AllowRaw,
   185  		hashPool: sync.Pool{
   186  			New: func() interface{} {
   187  				return storage.MakeHashFunc(storage.DefaultHash)()
   188  			},
   189  		},
   190  	}
   191  
   192  	for i := 0; i < hasherCount; i++ {
   193  		hashfunc := storage.MakeHashFunc(storage.DefaultHash)()
   194  		ps.hashPool.Put(hashfunc)
   195  	}
   196  
   197  	return ps, nil
   198  }
   199  
   200  /////////////////////////////////////////////////////////////////////
   201  // SECTION: node.Service interface
   202  /////////////////////////////////////////////////////////////////////
   203  
   204  func (p *Pss) Start(srv *p2p.Server) error {
   205  	go func() {
   206  		ticker := time.NewTicker(defaultCleanInterval)
   207  		cacheTicker := time.NewTicker(p.cacheTTL)
   208  		defer ticker.Stop()
   209  		defer cacheTicker.Stop()
   210  		for {
   211  			select {
   212  			case <-cacheTicker.C:
   213  				p.cleanFwdCache()
   214  			case <-ticker.C:
   215  				p.cleanKeys()
   216  			case <-p.quitC:
   217  				return
   218  			}
   219  		}
   220  	}()
   221  	go func() {
   222  		for {
   223  			select {
   224  			case msg := <-p.outbox:
   225  				err := p.forward(msg)
   226  				if err != nil {
   227  					log.Error(err.Error())
   228  					metrics.GetOrRegisterCounter("pss.forward.err", nil).Inc(1)
   229  				}
   230  			case <-p.quitC:
   231  				return
   232  			}
   233  		}
   234  	}()
   235  	log.Info("Started Pss")
   236  	log.Info("Loaded EC keys", "pubkey", common.ToHex(crypto.FromECDSAPub(p.PublicKey())), "secp256", common.ToHex(crypto.CompressPubkey(p.PublicKey())))
   237  	return nil
   238  }
   239  
   240  func (p *Pss) Stop() error {
   241  	log.Info("Pss shutting down")
   242  	close(p.quitC)
   243  	return nil
   244  }
   245  
   246  var pssSpec = &protocols.Spec{
   247  	Name:       pssProtocolName,
   248  	Version:    pssVersion,
   249  	MaxMsgSize: defaultMaxMsgSize,
   250  	Messages: []interface{}{
   251  		PssMsg{},
   252  	},
   253  }
   254  
   255  func (p *Pss) Protocols() []p2p.Protocol {
   256  	return []p2p.Protocol{
   257  		{
   258  			Name:    pssSpec.Name,
   259  			Version: pssSpec.Version,
   260  			Length:  pssSpec.Length(),
   261  			Run:     p.Run,
   262  		},
   263  	}
   264  }
   265  
   266  func (p *Pss) Run(peer *p2p.Peer, rw p2p.MsgReadWriter) error {
   267  	pp := protocols.NewPeer(peer, rw, pssSpec)
   268  	p.fwdPoolMu.Lock()
   269  	p.fwdPool[peer.Info().ID] = pp
   270  	p.fwdPoolMu.Unlock()
   271  	return pp.Run(p.handlePssMsg)
   272  }
   273  
   274  func (p *Pss) APIs() []rpc.API {
   275  	apis := []rpc.API{
   276  		{
   277  			Namespace: "pss",
   278  			Version:   "1.0",
   279  			Service:   NewAPI(p),
   280  			Public:    true,
   281  		},
   282  	}
   283  	apis = append(apis, p.auxAPIs...)
   284  	return apis
   285  }
   286  
   287  // add API methods to the pss API
   288  // must be run before node is started
   289  func (p *Pss) addAPI(api rpc.API) {
   290  	p.auxAPIs = append(p.auxAPIs, api)
   291  }
   292  
   293  // Returns the swarm Kademlia address of the pss node
   294  func (p *Pss) BaseAddr() []byte {
   295  	return p.Kademlia.BaseAddr()
   296  }
   297  
   298  // Returns the pss node's public key
   299  func (p *Pss) PublicKey() *ecdsa.PublicKey {
   300  	return &p.privateKey.PublicKey
   301  }
   302  
   303  /////////////////////////////////////////////////////////////////////
   304  // SECTION: Message handling
   305  /////////////////////////////////////////////////////////////////////
   306  
   307  // Links a handler function to a Topic
   308  //
   309  // All incoming messages with an envelope Topic matching the
   310  // topic specified will be passed to the given Handler function.
   311  //
   312  // There may be an arbitrary number of handler functions per topic.
   313  //
   314  // Returns a deregister function which needs to be called to
   315  // deregister the handler,
   316  func (p *Pss) Register(topic *Topic, handler Handler) func() {
   317  	p.handlersMu.Lock()
   318  	defer p.handlersMu.Unlock()
   319  	handlers := p.handlers[*topic]
   320  	if handlers == nil {
   321  		handlers = make(map[*Handler]bool)
   322  		p.handlers[*topic] = handlers
   323  	}
   324  	handlers[&handler] = true
   325  	return func() { p.deregister(topic, &handler) }
   326  }
   327  func (p *Pss) deregister(topic *Topic, h *Handler) {
   328  	p.handlersMu.Lock()
   329  	defer p.handlersMu.Unlock()
   330  	handlers := p.handlers[*topic]
   331  	if len(handlers) == 1 {
   332  		delete(p.handlers, *topic)
   333  		return
   334  	}
   335  	delete(handlers, h)
   336  }
   337  
   338  // get all registered handlers for respective topics
   339  func (p *Pss) getHandlers(topic Topic) map[*Handler]bool {
   340  	p.handlersMu.RLock()
   341  	defer p.handlersMu.RUnlock()
   342  	return p.handlers[topic]
   343  }
   344  
   345  // Filters incoming messages for processing or forwarding.
   346  // Check if address partially matches
   347  // If yes, it CAN be for us, and we process it
   348  // Only passes error to pss protocol handler if payload is not valid pssmsg
   349  func (p *Pss) handlePssMsg(ctx context.Context, msg interface{}) error {
   350  	metrics.GetOrRegisterCounter("pss.handlepssmsg", nil).Inc(1)
   351  
   352  	pssmsg, ok := msg.(*PssMsg)
   353  
   354  	if !ok {
   355  		return fmt.Errorf("invalid message type. Expected *PssMsg, got %T ", msg)
   356  	}
   357  	if int64(pssmsg.Expire) < time.Now().Unix() {
   358  		metrics.GetOrRegisterCounter("pss.expire", nil).Inc(1)
   359  		log.Warn("pss filtered expired message", "from", common.ToHex(p.Kademlia.BaseAddr()), "to", common.ToHex(pssmsg.To))
   360  		return nil
   361  	}
   362  	if p.checkFwdCache(pssmsg) {
   363  		log.Trace("pss relay block-cache match (process)", "from", common.ToHex(p.Kademlia.BaseAddr()), "to", (common.ToHex(pssmsg.To)))
   364  		return nil
   365  	}
   366  	p.addFwdCache(pssmsg)
   367  
   368  	if !p.isSelfPossibleRecipient(pssmsg) {
   369  		log.Trace("pss was for someone else :'( ... forwarding", "pss", common.ToHex(p.BaseAddr()))
   370  		return p.enqueue(pssmsg)
   371  	}
   372  
   373  	log.Trace("pss for us, yay! ... let's process!", "pss", common.ToHex(p.BaseAddr()))
   374  	if err := p.process(pssmsg); err != nil {
   375  		qerr := p.enqueue(pssmsg)
   376  		if qerr != nil {
   377  			return fmt.Errorf("process fail: processerr %v, queueerr: %v", err, qerr)
   378  		}
   379  	}
   380  	return nil
   381  
   382  }
   383  
   384  // Entry point to processing a message for which the current node can be the intended recipient.
   385  // Attempts symmetric and asymmetric decryption with stored keys.
   386  // Dispatches message to all handlers matching the message topic
   387  func (p *Pss) process(pssmsg *PssMsg) error {
   388  	metrics.GetOrRegisterCounter("pss.process", nil).Inc(1)
   389  
   390  	var err error
   391  	var recvmsg *whisper.ReceivedMessage
   392  	var payload []byte
   393  	var from *PssAddress
   394  	var asymmetric bool
   395  	var keyid string
   396  	var keyFunc func(envelope *whisper.Envelope) (*whisper.ReceivedMessage, string, *PssAddress, error)
   397  
   398  	envelope := pssmsg.Payload
   399  	psstopic := Topic(envelope.Topic)
   400  	if pssmsg.isRaw() {
   401  		if !p.allowRaw {
   402  			return errors.New("raw message support disabled")
   403  		}
   404  		payload = pssmsg.Payload.Data
   405  	} else {
   406  		if pssmsg.isSym() {
   407  			keyFunc = p.processSym
   408  		} else {
   409  			asymmetric = true
   410  			keyFunc = p.processAsym
   411  		}
   412  
   413  		recvmsg, keyid, from, err = keyFunc(envelope)
   414  		if err != nil {
   415  			return errors.New("Decryption failed")
   416  		}
   417  		payload = recvmsg.Payload
   418  	}
   419  
   420  	if len(pssmsg.To) < addressLength {
   421  		if err := p.enqueue(pssmsg); err != nil {
   422  			return err
   423  		}
   424  	}
   425  	p.executeHandlers(psstopic, payload, from, asymmetric, keyid)
   426  
   427  	return nil
   428  
   429  }
   430  
   431  func (p *Pss) executeHandlers(topic Topic, payload []byte, from *PssAddress, asymmetric bool, keyid string) {
   432  	handlers := p.getHandlers(topic)
   433  	nid, _ := discover.HexID("0x00") // this hack is needed to satisfy the p2p method
   434  	peer := p2p.NewPeer(nid, fmt.Sprintf("%x", from), []p2p.Cap{})
   435  	for f := range handlers {
   436  		err := (*f)(payload, peer, asymmetric, keyid)
   437  		if err != nil {
   438  			log.Warn("Pss handler %p failed: %v", f, err)
   439  		}
   440  	}
   441  }
   442  
   443  // will return false if using partial address
   444  func (p *Pss) isSelfRecipient(msg *PssMsg) bool {
   445  	return bytes.Equal(msg.To, p.Kademlia.BaseAddr())
   446  }
   447  
   448  // test match of leftmost bytes in given message to node's Kademlia address
   449  func (p *Pss) isSelfPossibleRecipient(msg *PssMsg) bool {
   450  	local := p.Kademlia.BaseAddr()
   451  	return bytes.Equal(msg.To, local[:len(msg.To)])
   452  }
   453  
   454  /////////////////////////////////////////////////////////////////////
   455  // SECTION: Encryption
   456  /////////////////////////////////////////////////////////////////////
   457  
   458  // Links a peer ECDSA public key to a topic
   459  //
   460  // This is required for asymmetric message exchange
   461  // on the given topic
   462  //
   463  // The value in `address` will be used as a routing hint for the
   464  // public key / topic association
   465  func (p *Pss) SetPeerPublicKey(pubkey *ecdsa.PublicKey, topic Topic, address *PssAddress) error {
   466  	pubkeybytes := crypto.FromECDSAPub(pubkey)
   467  	if len(pubkeybytes) == 0 {
   468  		return fmt.Errorf("invalid public key: %v", pubkey)
   469  	}
   470  	pubkeyid := common.ToHex(pubkeybytes)
   471  	psp := &pssPeer{
   472  		address: address,
   473  	}
   474  	p.pubKeyPoolMu.Lock()
   475  	if _, ok := p.pubKeyPool[pubkeyid]; !ok {
   476  		p.pubKeyPool[pubkeyid] = make(map[Topic]*pssPeer)
   477  	}
   478  	p.pubKeyPool[pubkeyid][topic] = psp
   479  	p.pubKeyPoolMu.Unlock()
   480  	log.Trace("added pubkey", "pubkeyid", pubkeyid, "topic", topic, "address", common.ToHex(*address))
   481  	return nil
   482  }
   483  
   484  // Automatically generate a new symkey for a topic and address hint
   485  func (p *Pss) GenerateSymmetricKey(topic Topic, address *PssAddress, addToCache bool) (string, error) {
   486  	keyid, err := p.w.GenerateSymKey()
   487  	if err != nil {
   488  		return "", err
   489  	}
   490  	p.addSymmetricKeyToPool(keyid, topic, address, addToCache, false)
   491  	return keyid, nil
   492  }
   493  
   494  // Links a peer symmetric key (arbitrary byte sequence) to a topic
   495  //
   496  // This is required for symmetrically encrypted message exchange
   497  // on the given topic
   498  //
   499  // The key is stored in the whisper backend.
   500  //
   501  // If addtocache is set to true, the key will be added to the cache of keys
   502  // used to attempt symmetric decryption of incoming messages.
   503  //
   504  // Returns a string id that can be used to retrieve the key bytes
   505  // from the whisper backend (see pss.GetSymmetricKey())
   506  func (p *Pss) SetSymmetricKey(key []byte, topic Topic, address *PssAddress, addtocache bool) (string, error) {
   507  	return p.setSymmetricKey(key, topic, address, addtocache, true)
   508  }
   509  
   510  func (p *Pss) setSymmetricKey(key []byte, topic Topic, address *PssAddress, addtocache bool, protected bool) (string, error) {
   511  	keyid, err := p.w.AddSymKeyDirect(key)
   512  	if err != nil {
   513  		return "", err
   514  	}
   515  	p.addSymmetricKeyToPool(keyid, topic, address, addtocache, protected)
   516  	return keyid, nil
   517  }
   518  
   519  // adds a symmetric key to the pss key pool, and optionally adds the key
   520  // to the collection of keys used to attempt symmetric decryption of
   521  // incoming messages
   522  func (p *Pss) addSymmetricKeyToPool(keyid string, topic Topic, address *PssAddress, addtocache bool, protected bool) {
   523  	psp := &pssPeer{
   524  		address:   address,
   525  		protected: protected,
   526  	}
   527  	p.symKeyPoolMu.Lock()
   528  	if _, ok := p.symKeyPool[keyid]; !ok {
   529  		p.symKeyPool[keyid] = make(map[Topic]*pssPeer)
   530  	}
   531  	p.symKeyPool[keyid][topic] = psp
   532  	p.symKeyPoolMu.Unlock()
   533  	if addtocache {
   534  		p.symKeyDecryptCacheCursor++
   535  		p.symKeyDecryptCache[p.symKeyDecryptCacheCursor%cap(p.symKeyDecryptCache)] = &keyid
   536  	}
   537  	key, _ := p.GetSymmetricKey(keyid)
   538  	log.Trace("added symkey", "symkeyid", keyid, "symkey", common.ToHex(key), "topic", topic, "address", fmt.Sprintf("%p", address), "cache", addtocache)
   539  }
   540  
   541  // Returns a symmetric key byte seqyence stored in the whisper backend
   542  // by its unique id
   543  //
   544  // Passes on the error value from the whisper backend
   545  func (p *Pss) GetSymmetricKey(symkeyid string) ([]byte, error) {
   546  	symkey, err := p.w.GetSymKey(symkeyid)
   547  	if err != nil {
   548  		return nil, err
   549  	}
   550  	return symkey, nil
   551  }
   552  
   553  // Returns all recorded topic and address combination for a specific public key
   554  func (p *Pss) GetPublickeyPeers(keyid string) (topic []Topic, address []PssAddress, err error) {
   555  	p.pubKeyPoolMu.RLock()
   556  	defer p.pubKeyPoolMu.RUnlock()
   557  	for t, peer := range p.pubKeyPool[keyid] {
   558  		topic = append(topic, t)
   559  		address = append(address, *peer.address)
   560  	}
   561  
   562  	return topic, address, nil
   563  }
   564  
   565  func (p *Pss) getPeerAddress(keyid string, topic Topic) (PssAddress, error) {
   566  	p.pubKeyPoolMu.RLock()
   567  	defer p.pubKeyPoolMu.RUnlock()
   568  	if peers, ok := p.pubKeyPool[keyid]; ok {
   569  		if t, ok := peers[topic]; ok {
   570  			return *t.address, nil
   571  		}
   572  	}
   573  	return nil, fmt.Errorf("peer with pubkey %s, topic %x not found", keyid, topic)
   574  }
   575  
   576  // Attempt to decrypt, validate and unpack a
   577  // symmetrically encrypted message
   578  // If successful, returns the unpacked whisper ReceivedMessage struct
   579  // encapsulating the decrypted message, and the whisper backend id
   580  // of the symmetric key used to decrypt the message.
   581  // It fails if decryption of the message fails or if the message is corrupted
   582  func (p *Pss) processSym(envelope *whisper.Envelope) (*whisper.ReceivedMessage, string, *PssAddress, error) {
   583  	metrics.GetOrRegisterCounter("pss.process.sym", nil).Inc(1)
   584  
   585  	for i := p.symKeyDecryptCacheCursor; i > p.symKeyDecryptCacheCursor-cap(p.symKeyDecryptCache) && i > 0; i-- {
   586  		symkeyid := p.symKeyDecryptCache[i%cap(p.symKeyDecryptCache)]
   587  		symkey, err := p.w.GetSymKey(*symkeyid)
   588  		if err != nil {
   589  			continue
   590  		}
   591  		recvmsg, err := envelope.OpenSymmetric(symkey)
   592  		if err != nil {
   593  			continue
   594  		}
   595  		if !recvmsg.Validate() {
   596  			return nil, "", nil, fmt.Errorf("symmetrically encrypted message has invalid signature or is corrupt")
   597  		}
   598  		p.symKeyPoolMu.Lock()
   599  		from := p.symKeyPool[*symkeyid][Topic(envelope.Topic)].address
   600  		p.symKeyPoolMu.Unlock()
   601  		p.symKeyDecryptCacheCursor++
   602  		p.symKeyDecryptCache[p.symKeyDecryptCacheCursor%cap(p.symKeyDecryptCache)] = symkeyid
   603  		return recvmsg, *symkeyid, from, nil
   604  	}
   605  	return nil, "", nil, fmt.Errorf("could not decrypt message")
   606  }
   607  
   608  // Attempt to decrypt, validate and unpack an
   609  // asymmetrically encrypted message
   610  // If successful, returns the unpacked whisper ReceivedMessage struct
   611  // encapsulating the decrypted message, and the byte representation of
   612  // the public key used to decrypt the message.
   613  // It fails if decryption of message fails, or if the message is corrupted
   614  func (p *Pss) processAsym(envelope *whisper.Envelope) (*whisper.ReceivedMessage, string, *PssAddress, error) {
   615  	metrics.GetOrRegisterCounter("pss.process.asym", nil).Inc(1)
   616  
   617  	recvmsg, err := envelope.OpenAsymmetric(p.privateKey)
   618  	if err != nil {
   619  		return nil, "", nil, fmt.Errorf("could not decrypt message: %s", err)
   620  	}
   621  	// check signature (if signed), strip padding
   622  	if !recvmsg.Validate() {
   623  		return nil, "", nil, fmt.Errorf("invalid message")
   624  	}
   625  	pubkeyid := common.ToHex(crypto.FromECDSAPub(recvmsg.Src))
   626  	var from *PssAddress
   627  	p.pubKeyPoolMu.Lock()
   628  	if p.pubKeyPool[pubkeyid][Topic(envelope.Topic)] != nil {
   629  		from = p.pubKeyPool[pubkeyid][Topic(envelope.Topic)].address
   630  	}
   631  	p.pubKeyPoolMu.Unlock()
   632  	return recvmsg, pubkeyid, from, nil
   633  }
   634  
   635  // Symkey garbage collection
   636  // a key is removed if:
   637  // - it is not marked as protected
   638  // - it is not in the incoming decryption cache
   639  func (p *Pss) cleanKeys() (count int) {
   640  	for keyid, peertopics := range p.symKeyPool {
   641  		var expiredtopics []Topic
   642  		for topic, psp := range peertopics {
   643  			if psp.protected {
   644  				continue
   645  			}
   646  
   647  			var match bool
   648  			for i := p.symKeyDecryptCacheCursor; i > p.symKeyDecryptCacheCursor-cap(p.symKeyDecryptCache) && i > 0; i-- {
   649  				cacheid := p.symKeyDecryptCache[i%cap(p.symKeyDecryptCache)]
   650  				if *cacheid == keyid {
   651  					match = true
   652  				}
   653  			}
   654  			if !match {
   655  				expiredtopics = append(expiredtopics, topic)
   656  			}
   657  		}
   658  		for _, topic := range expiredtopics {
   659  			p.symKeyPoolMu.Lock()
   660  			delete(p.symKeyPool[keyid], topic)
   661  			log.Trace("symkey cleanup deletion", "symkeyid", keyid, "topic", topic, "val", p.symKeyPool[keyid])
   662  			p.symKeyPoolMu.Unlock()
   663  			count++
   664  		}
   665  	}
   666  	return
   667  }
   668  
   669  /////////////////////////////////////////////////////////////////////
   670  // SECTION: Message sending
   671  /////////////////////////////////////////////////////////////////////
   672  
   673  func (p *Pss) enqueue(msg *PssMsg) error {
   674  	select {
   675  	case p.outbox <- msg:
   676  		return nil
   677  	default:
   678  	}
   679  
   680  	metrics.GetOrRegisterCounter("pss.enqueue.outbox.full", nil).Inc(1)
   681  	return errors.New("outbox full")
   682  }
   683  
   684  // Send a raw message (any encryption is responsibility of calling client)
   685  //
   686  // Will fail if raw messages are disallowed
   687  func (p *Pss) SendRaw(address PssAddress, topic Topic, msg []byte) error {
   688  	if !p.allowRaw {
   689  		return errors.New("Raw messages not enabled")
   690  	}
   691  	pssMsgParams := &msgParams{
   692  		raw: true,
   693  	}
   694  	payload := &whisper.Envelope{
   695  		Data:  msg,
   696  		Topic: whisper.TopicType(topic),
   697  	}
   698  	pssMsg := newPssMsg(pssMsgParams)
   699  	pssMsg.To = address
   700  	pssMsg.Expire = uint32(time.Now().Add(p.msgTTL).Unix())
   701  	pssMsg.Payload = payload
   702  	p.addFwdCache(pssMsg)
   703  	return p.enqueue(pssMsg)
   704  }
   705  
   706  // Send a message using symmetric encryption
   707  //
   708  // Fails if the key id does not match any of the stored symmetric keys
   709  func (p *Pss) SendSym(symkeyid string, topic Topic, msg []byte) error {
   710  	symkey, err := p.GetSymmetricKey(symkeyid)
   711  	if err != nil {
   712  		return fmt.Errorf("missing valid send symkey %s: %v", symkeyid, err)
   713  	}
   714  	p.symKeyPoolMu.Lock()
   715  	psp, ok := p.symKeyPool[symkeyid][topic]
   716  	p.symKeyPoolMu.Unlock()
   717  	if !ok {
   718  		return fmt.Errorf("invalid topic '%s' for symkey '%s'", topic.String(), symkeyid)
   719  	} else if psp.address == nil {
   720  		return fmt.Errorf("no address hint for topic '%s' symkey '%s'", topic.String(), symkeyid)
   721  	}
   722  	err = p.send(*psp.address, topic, msg, false, symkey)
   723  	return err
   724  }
   725  
   726  // Send a message using asymmetric encryption
   727  //
   728  // Fails if the key id does not match any in of the stored public keys
   729  func (p *Pss) SendAsym(pubkeyid string, topic Topic, msg []byte) error {
   730  	if _, err := crypto.UnmarshalPubkey(common.FromHex(pubkeyid)); err != nil {
   731  		return fmt.Errorf("Cannot unmarshal pubkey: %x", pubkeyid)
   732  	}
   733  	p.pubKeyPoolMu.Lock()
   734  	psp, ok := p.pubKeyPool[pubkeyid][topic]
   735  	p.pubKeyPoolMu.Unlock()
   736  	if !ok {
   737  		return fmt.Errorf("invalid topic '%s' for pubkey '%s'", topic.String(), pubkeyid)
   738  	} else if psp.address == nil {
   739  		return fmt.Errorf("no address hint for topic '%s' pubkey '%s'", topic.String(), pubkeyid)
   740  	}
   741  	go func() {
   742  		p.send(*psp.address, topic, msg, true, common.FromHex(pubkeyid))
   743  	}()
   744  	return nil
   745  }
   746  
   747  // Send is payload agnostic, and will accept any byte slice as payload
   748  // It generates an whisper envelope for the specified recipient and topic,
   749  // and wraps the message payload in it.
   750  // TODO: Implement proper message padding
   751  func (p *Pss) send(to []byte, topic Topic, msg []byte, asymmetric bool, key []byte) error {
   752  	metrics.GetOrRegisterCounter("pss.send", nil).Inc(1)
   753  
   754  	if key == nil || bytes.Equal(key, []byte{}) {
   755  		return fmt.Errorf("Zero length key passed to pss send")
   756  	}
   757  	padding := make([]byte, p.paddingByteSize)
   758  	c, err := rand.Read(padding)
   759  	if err != nil {
   760  		return err
   761  	} else if c < p.paddingByteSize {
   762  		return fmt.Errorf("invalid padding length: %d", c)
   763  	}
   764  	wparams := &whisper.MessageParams{
   765  		TTL:      defaultWhisperTTL,
   766  		Src:      p.privateKey,
   767  		Topic:    whisper.TopicType(topic),
   768  		WorkTime: defaultWhisperWorkTime,
   769  		PoW:      defaultWhisperPoW,
   770  		Payload:  msg,
   771  		Padding:  padding,
   772  	}
   773  	if asymmetric {
   774  		pk, err := crypto.UnmarshalPubkey(key)
   775  		if err != nil {
   776  			return fmt.Errorf("Cannot unmarshal pubkey: %x", key)
   777  		}
   778  		wparams.Dst = pk
   779  	} else {
   780  		wparams.KeySym = key
   781  	}
   782  	// set up outgoing message container, which does encryption and envelope wrapping
   783  	woutmsg, err := whisper.NewSentMessage(wparams)
   784  	if err != nil {
   785  		return fmt.Errorf("failed to generate whisper message encapsulation: %v", err)
   786  	}
   787  	// performs encryption.
   788  	// Does NOT perform / performs negligible PoW due to very low difficulty setting
   789  	// after this the message is ready for sending
   790  	envelope, err := woutmsg.Wrap(wparams)
   791  	if err != nil {
   792  		return fmt.Errorf("failed to perform whisper encryption: %v", err)
   793  	}
   794  	log.Trace("pssmsg whisper done", "env", envelope, "wparams payload", common.ToHex(wparams.Payload), "to", common.ToHex(to), "asym", asymmetric, "key", common.ToHex(key))
   795  
   796  	// prepare for devp2p transport
   797  	pssMsgParams := &msgParams{
   798  		sym: !asymmetric,
   799  	}
   800  	pssMsg := newPssMsg(pssMsgParams)
   801  	pssMsg.To = to
   802  	pssMsg.Expire = uint32(time.Now().Add(p.msgTTL).Unix())
   803  	pssMsg.Payload = envelope
   804  	return p.enqueue(pssMsg)
   805  }
   806  
   807  // Forwards a pss message to the peer(s) closest to the to recipient address in the PssMsg struct
   808  // The recipient address can be of any length, and the byte slice will be matched to the MSB slice
   809  // of the peer address of the equivalent length.
   810  func (p *Pss) forward(msg *PssMsg) error {
   811  	metrics.GetOrRegisterCounter("pss.forward", nil).Inc(1)
   812  
   813  	to := make([]byte, addressLength)
   814  	copy(to[:len(msg.To)], msg.To)
   815  
   816  	// send with kademlia
   817  	// find the closest peer to the recipient and attempt to send
   818  	sent := 0
   819  	p.Kademlia.EachConn(to, 256, func(sp *network.Peer, po int, isproxbin bool) bool {
   820  		info := sp.Info()
   821  
   822  		// check if the peer is running pss
   823  		var ispss bool
   824  		for _, cap := range info.Caps {
   825  			if cap == p.capstring {
   826  				ispss = true
   827  				break
   828  			}
   829  		}
   830  		if !ispss {
   831  			log.Trace("peer doesn't have matching pss capabilities, skipping", "peer", info.Name, "caps", info.Caps)
   832  			return true
   833  		}
   834  
   835  		// get the protocol peer from the forwarding peer cache
   836  		sendMsg := fmt.Sprintf("MSG TO %x FROM %x VIA %x", to, p.BaseAddr(), sp.Address())
   837  		p.fwdPoolMu.RLock()
   838  		pp := p.fwdPool[sp.Info().ID]
   839  		p.fwdPoolMu.RUnlock()
   840  
   841  		// attempt to send the message
   842  		err := pp.Send(context.TODO(), msg)
   843  		if err != nil {
   844  			metrics.GetOrRegisterCounter("pss.pp.send.error", nil).Inc(1)
   845  			log.Error(err.Error())
   846  			return true
   847  		}
   848  		sent++
   849  		log.Trace(fmt.Sprintf("%v: successfully forwarded", sendMsg))
   850  
   851  		// continue forwarding if:
   852  		// - if the peer is end recipient but the full address has not been disclosed
   853  		// - if the peer address matches the partial address fully
   854  		// - if the peer is in proxbin
   855  		if len(msg.To) < addressLength && bytes.Equal(msg.To, sp.Address()[:len(msg.To)]) {
   856  			log.Trace(fmt.Sprintf("Pss keep forwarding: Partial address + full partial match"))
   857  			return true
   858  		} else if isproxbin {
   859  			log.Trace(fmt.Sprintf("%x is in proxbin, keep forwarding", common.ToHex(sp.Address())))
   860  			return true
   861  		}
   862  		// at this point we stop forwarding, and the state is as follows:
   863  		// - the peer is end recipient and we have full address
   864  		// - we are not in proxbin (directed routing)
   865  		// - partial addresses don't fully match
   866  		return false
   867  	})
   868  
   869  	if sent == 0 {
   870  		log.Debug("unable to forward to any peers")
   871  		if err := p.enqueue(msg); err != nil {
   872  			metrics.GetOrRegisterCounter("pss.forward.enqueue.error", nil).Inc(1)
   873  			log.Error(err.Error())
   874  			return err
   875  		}
   876  	}
   877  
   878  	// cache the message
   879  	p.addFwdCache(msg)
   880  	return nil
   881  }
   882  
   883  /////////////////////////////////////////////////////////////////////
   884  // SECTION: Caching
   885  /////////////////////////////////////////////////////////////////////
   886  
   887  // cleanFwdCache is used to periodically remove expired entries from the forward cache
   888  func (p *Pss) cleanFwdCache() {
   889  	metrics.GetOrRegisterCounter("pss.cleanfwdcache", nil).Inc(1)
   890  	p.fwdCacheMu.Lock()
   891  	defer p.fwdCacheMu.Unlock()
   892  	for k, v := range p.fwdCache {
   893  		if v.expiresAt.Before(time.Now()) {
   894  			delete(p.fwdCache, k)
   895  		}
   896  	}
   897  }
   898  
   899  // add a message to the cache
   900  func (p *Pss) addFwdCache(msg *PssMsg) error {
   901  	metrics.GetOrRegisterCounter("pss.addfwdcache", nil).Inc(1)
   902  
   903  	var entry pssCacheEntry
   904  	var ok bool
   905  
   906  	p.fwdCacheMu.Lock()
   907  	defer p.fwdCacheMu.Unlock()
   908  
   909  	digest := p.digest(msg)
   910  	if entry, ok = p.fwdCache[digest]; !ok {
   911  		entry = pssCacheEntry{}
   912  	}
   913  	entry.expiresAt = time.Now().Add(p.cacheTTL)
   914  	p.fwdCache[digest] = entry
   915  	return nil
   916  }
   917  
   918  // check if message is in the cache
   919  func (p *Pss) checkFwdCache(msg *PssMsg) bool {
   920  	p.fwdCacheMu.Lock()
   921  	defer p.fwdCacheMu.Unlock()
   922  
   923  	digest := p.digest(msg)
   924  	entry, ok := p.fwdCache[digest]
   925  	if ok {
   926  		if entry.expiresAt.After(time.Now()) {
   927  			log.Trace("unexpired cache", "digest", fmt.Sprintf("%x", digest))
   928  			metrics.GetOrRegisterCounter("pss.checkfwdcache.unexpired", nil).Inc(1)
   929  			return true
   930  		}
   931  		metrics.GetOrRegisterCounter("pss.checkfwdcache.expired", nil).Inc(1)
   932  	}
   933  	return false
   934  }
   935  
   936  // Digest of message
   937  func (p *Pss) digest(msg *PssMsg) pssDigest {
   938  	hasher := p.hashPool.Get().(storage.SwarmHash)
   939  	defer p.hashPool.Put(hasher)
   940  	hasher.Reset()
   941  	hasher.Write(msg.serialize())
   942  	digest := pssDigest{}
   943  	key := hasher.Sum(nil)
   944  	copy(digest[:], key[:digestLength])
   945  	return digest
   946  }