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