Skip to content

Commit 3a0daf1

Browse files
committed
[FAB-1444] Move signature to top level in gossip msg
A gossip.GossipMessage is a oneof of different types of messages, and all messages in gossip are under that message. Messages that are signed have their signature in the inner field of the message. To make things more secure, and also more uniform, I'm moving the signature to the top level of the GossipMessage. Change-Id: Ia358015ed98270d882c3facdaca89355666a9f69 Signed-off-by: Yacov Manevich <[email protected]>
1 parent 62eac5b commit 3a0daf1

12 files changed

+449
-403
lines changed

gossip/comm/comm_impl.go

+24-10
Original file line numberDiff line numberDiff line change
@@ -388,20 +388,25 @@ func (c *commImpl) authenticateRemotePeer(stream stream) (common.PKIidType, erro
388388
ctx := stream.Context()
389389
remoteAddress := extractRemoteAddress(stream)
390390
remoteCertHash := extractCertificateHashFromContext(ctx)
391-
var sig []byte
392391
var err error
392+
var cMsg *proto.GossipMessage
393+
var signer proto.Signer
393394

394395
// If TLS is detected, sign the hash of our cert to bind our TLS cert
395396
// to the gRPC session
396397
if remoteCertHash != nil && c.selfCertHash != nil {
397-
sig, err = c.idMapper.Sign(c.selfCertHash)
398-
if err != nil {
399-
c.logger.Error("Failed signing self certificate hash:", err)
400-
return nil, err
398+
signer = func(msg []byte) ([]byte, error) {
399+
return c.idMapper.Sign(msg)
400+
}
401+
} else { // If we don't use TLS, we have no unique text to sign,
402+
// so don't sign anything
403+
signer = func(msg []byte) ([]byte, error) {
404+
return msg, nil
401405
}
402406
}
403407

404-
cMsg := createConnectionMsg(c.PKIID, sig, c.peerIdentity)
408+
cMsg = createConnectionMsg(c.PKIID, c.selfCertHash, c.peerIdentity, signer)
409+
405410
c.logger.Debug("Sending", cMsg, "to", remoteAddress)
406411
stream.Send(cMsg)
407412
m := readWithTimeout(stream, defConnTimeout)
@@ -433,7 +438,14 @@ func (c *commImpl) authenticateRemotePeer(stream stream) (common.PKIidType, erro
433438

434439
// if TLS is detected, verify remote peer
435440
if remoteCertHash != nil && c.selfCertHash != nil {
436-
err = c.idMapper.Verify(receivedMsg.PkiID, receivedMsg.Sig, remoteCertHash)
441+
if !bytes.Equal(remoteCertHash, receivedMsg.Hash) {
442+
return nil, fmt.Errorf("Expected %v in remote hash, but got %v", remoteCertHash, receivedMsg.Hash)
443+
}
444+
verifier := func(peerIdentity []byte, signature, message []byte) error {
445+
pkiID := c.idMapper.GetPKIidOfCert(api.PeerIdentityType(peerIdentity))
446+
return c.idMapper.Verify(pkiID, signature, message)
447+
}
448+
err = m.Verify(receivedMsg.Cert, verifier)
437449
if err != nil {
438450
c.logger.Error("Failed verifying signature from", remoteAddress, ":", err)
439451
return nil, err
@@ -516,18 +528,20 @@ func readWithTimeout(stream interface{}, timeout time.Duration) *proto.GossipMes
516528
}
517529
}
518530

519-
func createConnectionMsg(pkiID common.PKIidType, sig []byte, cert api.PeerIdentityType) *proto.GossipMessage {
520-
return &proto.GossipMessage{
531+
func createConnectionMsg(pkiID common.PKIidType, hash []byte, cert api.PeerIdentityType, signer proto.Signer) *proto.GossipMessage {
532+
m := &proto.GossipMessage{
521533
Tag: proto.GossipMessage_EMPTY,
522534
Nonce: 0,
523535
Content: &proto.GossipMessage_Conn{
524536
Conn: &proto.ConnEstablish{
537+
Hash: hash,
525538
Cert: cert,
526539
PkiID: pkiID,
527-
Sig: sig,
528540
},
529541
},
530542
}
543+
m.Sign(signer)
544+
return m
531545
}
532546

533547
type stream interface {

gossip/comm/comm_test.go

+14-7
Original file line numberDiff line numberDiff line change
@@ -116,22 +116,29 @@ func handshaker(endpoint string, comm Comm, t *testing.T, sigMutator func([]byte
116116
return nil
117117
}
118118
clientCertHash := certHashFromRawCert(cert.Certificate[0])
119-
sig, err := naiveSec.Sign(clientCertHash)
120-
if sigMutator != nil {
121-
sig = sigMutator(sig)
122-
}
119+
123120
pkiID := common.PKIidType(endpoint)
124121
if pkiIDmutator != nil {
125122
pkiID = common.PKIidType(pkiIDmutator([]byte(endpoint)))
126123
}
127-
128124
assert.NoError(t, err, "%v", err)
129-
msg := createConnectionMsg(pkiID, sig, []byte(endpoint))
125+
msg := createConnectionMsg(pkiID, clientCertHash, []byte(endpoint), func(msg []byte) ([]byte, error) {
126+
return msg, nil
127+
})
128+
129+
if sigMutator != nil {
130+
msg.Signature = sigMutator(msg.Signature)
131+
}
132+
130133
stream.Send(msg)
131134
msg, err = stream.Recv()
132135
assert.NoError(t, err, "%v", err)
133136
if sigMutator == nil {
134-
assert.Equal(t, extractCertificateHashFromContext(stream.Context()), msg.GetConn().Sig)
137+
hash := extractCertificateHashFromContext(stream.Context())
138+
expectedMsg := createConnectionMsg(common.PKIidType("localhost:9611"), hash, []byte("localhost:9611"), func(msg []byte) ([]byte, error) {
139+
return msg, nil
140+
})
141+
assert.Equal(t, expectedMsg.Signature, msg.Signature)
135142
}
136143
assert.Equal(t, []byte("localhost:9611"), msg.GetConn().PkiID)
137144
msg2Send := createGossipMsg()

gossip/discovery/discovery.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ import (
2323

2424
// CryptoService is an interface that the discovery expects to be implemented and passed on creation
2525
type CryptoService interface {
26-
// validateAliveMsg validates that an Alive message is authentic
27-
ValidateAliveMsg(*proto.AliveMessage) bool
26+
// ValidateAliveMsg validates that an Alive message is authentic
27+
ValidateAliveMsg(*proto.GossipMessage) bool
2828

29-
// SignMessage signs an AliveMessage and updates its signature field
30-
SignMessage(*proto.AliveMessage) *proto.AliveMessage
29+
// SignMessage signs a message
30+
SignMessage(m *proto.GossipMessage) *proto.GossipMessage
3131
}
3232

3333
// CommService is an interface that the discovery expects to be implemented and passed on creation

0 commit comments

Comments
 (0)