func (mod *module) handle_connect(ch *e3x.Channel) { defer ch.Kill() var ( from hashname.H localIdent *e3x.Identity remoteIdent *e3x.Identity handshake cipherset.Handshake innerData = bufpool.New() err error ) localIdent, err = mod.e.LocalIdentity() if err != nil { return } pkt, err := ch.ReadPacket() if err != nil { return } pkt.Body(innerData.SetLen(pkt.BodyLen()).RawBytes()[:0]) inner, err := lob.Decode(innerData) if err != nil { return } innerHdr := inner.Header() if innerHdr.IsBinary() && len(innerHdr.Bytes) == 1 { // handshake var ( csid = innerHdr.Bytes[0] key = localIdent.Keys()[csid] ) if key == nil { return } handshake, err = cipherset.DecryptHandshake(csid, key, inner.Body(nil)) if err != nil { return } from, err = hashname.FromIntermediates(handshake.Parts()) if err != nil { return } remoteIdent, err = e3x.NewIdentity(cipherset.Keys{ handshake.CSID(): handshake.PublicKey(), }, handshake.Parts(), nil) if err != nil { return } } else { // key packet var parts = make(cipherset.Parts) var csid uint8 for key, value := range inner.Header().Extra { if len(key) != 2 { continue } keyData, err := hex.DecodeString(key) if err != nil { continue } partCSID := keyData[0] switch v := value.(type) { case bool: csid = partCSID case string: parts[partCSID] = v } } hn, err := hashname.FromKeyAndIntermediates(csid, inner.Body(nil), parts) if err != nil { return } from = hn pubKey, err := cipherset.DecodeKeyBytes(csid, inner.Body(nil), nil) if err != nil { return } remoteIdent, err = e3x.NewIdentity(cipherset.Keys{csid: pubKey}, parts, nil) if err != nil { return } } if from == "" { return } if mod.config.AllowConnect != nil && !mod.config.AllowConnect(from, ch.RemoteHashname()) { return } x, err := mod.e.CreateExchange(remoteIdent) if err != nil { return } // when the BODY contains a handshake if handshake != nil { routerExchange := ch.Exchange() routerAddr := &peerAddr{ router: routerExchange.RemoteHashname(), } conn := newConnection(x.RemoteHashname(), routerAddr, routerExchange, func() { mod.unregisterConnection(routerExchange, x.LocalToken()) }) pipe, added := x.AddPipeConnection(conn, nil) if added { mod.registerConnection(routerExchange, x.LocalToken(), conn) } resp, ok := x.ApplyHandshake(handshake, pipe) if !ok { return } if resp != nil { err = mod.peerVia(ch.Exchange(), from, resp) if err != nil { return } } } // when the BODY contains a key packet if handshake == nil { pkt, err := x.GenerateHandshake() if err != nil { return } err = mod.peerVia(ch.Exchange(), from, pkt) if err != nil { return } } // Notify on-exchange callbacks mod.getIntroduction(from).resolve(x, nil) }
func (s *cipherTestSuite) TestHandshake() { var ( assert = s.Assertions c = s.cipher ) var ( ka cipherset.Key kb cipherset.Key sa cipherset.State sb cipherset.State ha cipherset.Handshake hb cipherset.Handshake box []byte err error ok bool ) ka, err = c.GenerateKey() assert.NoError(err) assert.NotNil(ka) sa, err = c.NewState(ka) assert.NoError(err) assert.NotNil(sa) assert.False(sa.CanEncryptMessage()) assert.False(sa.CanEncryptHandshake()) assert.False(sa.CanDecryptMessage()) assert.True(sa.CanDecryptHandshake()) assert.True(sa.NeedsRemoteKey()) kb, err = c.GenerateKey() assert.NoError(err) assert.NotNil(kb) err = sa.SetRemoteKey(kb) assert.NoError(err) assert.True(sa.CanEncryptMessage()) assert.True(sa.CanEncryptHandshake()) assert.True(sa.CanDecryptMessage()) assert.True(sa.CanDecryptHandshake()) assert.False(sa.NeedsRemoteKey()) box, err = sa.EncryptHandshake(1, cipherset.Parts{0x01: "foobarzzzzfoobarzzzzfoobarzzzzfoobarzzzzfoobarzzzz34"}) assert.NoError(err) assert.NotNil(box) hb, err = c.DecryptHandshake(kb, box) assert.NoError(err) if assert.NotNil(hb) { assert.Equal(ka.Public(), hb.PublicKey().Public()) assert.Equal(cipherset.Parts{0x01: "foobarzzzzfoobarzzzzfoobarzzzzfoobarzzzzfoobarzzzz34"}, hb.Parts()) assert.Equal(uint32(1), hb.At()) } sb, err = c.NewState(kb) assert.NoError(err) if assert.NotNil(sb) { assert.False(sb.CanEncryptMessage()) assert.False(sb.CanEncryptHandshake()) assert.False(sb.CanDecryptMessage()) assert.True(sb.CanDecryptHandshake()) assert.True(sb.NeedsRemoteKey()) } if sb != nil && hb != nil { ok = sb.ApplyHandshake(hb) assert.True(ok) assert.True(sb.CanEncryptMessage()) assert.True(sb.CanEncryptHandshake()) assert.True(sb.CanDecryptMessage()) assert.True(sb.CanDecryptHandshake()) assert.False(sb.NeedsRemoteKey()) } box, err = sb.EncryptHandshake(1, cipherset.Parts{0x01: "foobarzzzzfoobarzzzzfoobarzzzzfoobarzzzzfoobarzzzz34"}) assert.NoError(err) assert.NotNil(box) ha, err = c.DecryptHandshake(ka, box) assert.NoError(err) assert.NotNil(ha) assert.Equal(kb.Public(), ha.PublicKey().Public()) assert.Equal(cipherset.Parts{0x01: "foobarzzzzfoobarzzzzfoobarzzzzfoobarzzzzfoobarzzzz34"}, ha.Parts()) assert.Equal(uint32(1), ha.At()) ok = sa.ApplyHandshake(ha) assert.True(ok) assert.True(sa.CanEncryptMessage()) assert.True(sa.CanEncryptHandshake()) assert.True(sa.CanDecryptMessage()) assert.True(sa.CanDecryptHandshake()) assert.False(sa.NeedsRemoteKey()) }