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