github.com/defanghe/fabric@v2.1.1+incompatible/internal/peer/gossip/mcs.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package gossip
     8  
     9  import (
    10  	"bytes"
    11  	"fmt"
    12  	"time"
    13  
    14  	pcommon "github.com/hyperledger/fabric-protos-go/common"
    15  	"github.com/hyperledger/fabric/bccsp"
    16  	"github.com/hyperledger/fabric/common/flogging"
    17  	"github.com/hyperledger/fabric/common/policies"
    18  	"github.com/hyperledger/fabric/common/util"
    19  	"github.com/hyperledger/fabric/gossip/api"
    20  	"github.com/hyperledger/fabric/gossip/common"
    21  	"github.com/hyperledger/fabric/internal/pkg/identity"
    22  	"github.com/hyperledger/fabric/msp"
    23  	"github.com/hyperledger/fabric/msp/mgmt"
    24  	"github.com/hyperledger/fabric/protoutil"
    25  	"github.com/pkg/errors"
    26  )
    27  
    28  var mcsLogger = flogging.MustGetLogger("peer.gossip.mcs")
    29  
    30  // Hasher is the interface provides the hash function should be used for all gossip components.
    31  type Hasher interface {
    32  	Hash(msg []byte, opts bccsp.HashOpts) (hash []byte, err error)
    33  }
    34  
    35  // MSPMessageCryptoService implements the MessageCryptoService interface
    36  // using the peer MSPs (local and channel-related)
    37  //
    38  // In order for the system to be secure it is vital to have the
    39  // MSPs to be up-to-date. Channels' MSPs are updated via
    40  // configuration transactions distributed by the ordering service.
    41  //
    42  // A similar mechanism needs to be in place to update the local MSP, as well.
    43  // This implementation assumes that these mechanisms are all in place and working.
    44  type MSPMessageCryptoService struct {
    45  	channelPolicyManagerGetter policies.ChannelPolicyManagerGetter
    46  	localSigner                identity.SignerSerializer
    47  	deserializer               mgmt.DeserializersManager
    48  	hasher                     Hasher
    49  }
    50  
    51  // NewMCS creates a new instance of MSPMessageCryptoService
    52  // that implements MessageCryptoService.
    53  // The method takes in input:
    54  // 1. a policies.ChannelPolicyManagerGetter that gives access to the policy manager of a given channel via the Manager method.
    55  // 2. an instance of identity.SignerSerializer
    56  // 3. an identity deserializer manager
    57  func NewMCS(
    58  	channelPolicyManagerGetter policies.ChannelPolicyManagerGetter,
    59  	localSigner identity.SignerSerializer,
    60  	deserializer mgmt.DeserializersManager,
    61  	hasher Hasher,
    62  ) *MSPMessageCryptoService {
    63  	return &MSPMessageCryptoService{
    64  		channelPolicyManagerGetter: channelPolicyManagerGetter,
    65  		localSigner:                localSigner,
    66  		deserializer:               deserializer,
    67  		hasher:                     hasher,
    68  	}
    69  }
    70  
    71  // ValidateIdentity validates the identity of a remote peer.
    72  // If the identity is invalid, revoked, expired it returns an error.
    73  // Else, returns nil
    74  func (s *MSPMessageCryptoService) ValidateIdentity(peerIdentity api.PeerIdentityType) error {
    75  	// As prescribed by the contract of method,
    76  	// below we check only that peerIdentity is not
    77  	// invalid, revoked or expired.
    78  
    79  	_, _, err := s.getValidatedIdentity(peerIdentity)
    80  	return err
    81  }
    82  
    83  // GetPKIidOfCert returns the PKI-ID of a peer's identity
    84  // If any error occurs, the method return nil
    85  // The PKid of a peer is computed as the SHA2-256 of peerIdentity which
    86  // is supposed to be the serialized version of MSP identity.
    87  // This method does not validate peerIdentity.
    88  // This validation is supposed to be done appropriately during the execution flow.
    89  func (s *MSPMessageCryptoService) GetPKIidOfCert(peerIdentity api.PeerIdentityType) common.PKIidType {
    90  	// Validate arguments
    91  	if len(peerIdentity) == 0 {
    92  		mcsLogger.Error("Invalid Peer Identity. It must be different from nil.")
    93  
    94  		return nil
    95  	}
    96  
    97  	sid, err := s.deserializer.Deserialize(peerIdentity)
    98  	if err != nil {
    99  		mcsLogger.Errorf("Failed getting validated identity from peer identity %s: [%s]", peerIdentity, err)
   100  
   101  		return nil
   102  	}
   103  
   104  	// concatenate msp-id and idbytes
   105  	// idbytes is the low-level representation of an identity.
   106  	// it is supposed to be already in its minimal representation
   107  
   108  	mspIDRaw := []byte(sid.Mspid)
   109  	raw := append(mspIDRaw, sid.IdBytes...)
   110  
   111  	// Hash
   112  	digest, err := s.hasher.Hash(raw, &bccsp.SHA256Opts{})
   113  	if err != nil {
   114  		mcsLogger.Errorf("Failed computing digest of serialized identity %s: [%s]", peerIdentity, err)
   115  		return nil
   116  	}
   117  
   118  	return digest
   119  }
   120  
   121  // VerifyBlock returns nil if the block is properly signed, and the claimed seqNum is the
   122  // sequence number that the block's header contains.
   123  // else returns error
   124  func (s *MSPMessageCryptoService) VerifyBlock(chainID common.ChannelID, seqNum uint64, block *pcommon.Block) error {
   125  	if block.Header == nil {
   126  		return fmt.Errorf("Invalid Block on channel [%s]. Header must be different from nil.", chainID)
   127  	}
   128  
   129  	blockSeqNum := block.Header.Number
   130  	if seqNum != blockSeqNum {
   131  		return fmt.Errorf("Claimed seqNum is [%d] but actual seqNum inside block is [%d]", seqNum, blockSeqNum)
   132  	}
   133  
   134  	// - Extract channelID and compare with chainID
   135  	channelID, err := protoutil.GetChainIDFromBlock(block)
   136  	if err != nil {
   137  		return fmt.Errorf("Failed getting channel id from block with id [%d] on channel [%s]: [%s]", block.Header.Number, chainID, err)
   138  	}
   139  
   140  	if channelID != string(chainID) {
   141  		return fmt.Errorf("Invalid block's channel id. Expected [%s]. Given [%s]", chainID, channelID)
   142  	}
   143  
   144  	// - Unmarshal medatada
   145  	if block.Metadata == nil || len(block.Metadata.Metadata) == 0 {
   146  		return fmt.Errorf("Block with id [%d] on channel [%s] does not have metadata. Block not valid.", block.Header.Number, chainID)
   147  	}
   148  
   149  	metadata, err := protoutil.GetMetadataFromBlock(block, pcommon.BlockMetadataIndex_SIGNATURES)
   150  	if err != nil {
   151  		return fmt.Errorf("Failed unmarshalling medatata for signatures [%s]", err)
   152  	}
   153  
   154  	// - Verify that Header.DataHash is equal to the hash of block.Data
   155  	// This is to ensure that the header is consistent with the data carried by this block
   156  	if !bytes.Equal(protoutil.BlockDataHash(block.Data), block.Header.DataHash) {
   157  		return fmt.Errorf("Header.DataHash is different from Hash(block.Data) for block with id [%d] on channel [%s]", block.Header.Number, chainID)
   158  	}
   159  
   160  	// - Get Policy for block validation
   161  
   162  	// Get the policy manager for channelID
   163  	cpm := s.channelPolicyManagerGetter.Manager(channelID)
   164  	if cpm == nil {
   165  		return fmt.Errorf("Could not acquire policy manager for channel %s", channelID)
   166  	}
   167  	mcsLogger.Debugf("Got policy manager for channel [%s]", channelID)
   168  
   169  	// Get block validation policy
   170  	policy, ok := cpm.GetPolicy(policies.BlockValidation)
   171  	// ok is true if it was the policy requested, or false if it is the default policy
   172  	mcsLogger.Debugf("Got block validation policy for channel [%s] with flag [%t]", channelID, ok)
   173  
   174  	// - Prepare SignedData
   175  	signatureSet := []*protoutil.SignedData{}
   176  	for _, metadataSignature := range metadata.Signatures {
   177  		shdr, err := protoutil.UnmarshalSignatureHeader(metadataSignature.SignatureHeader)
   178  		if err != nil {
   179  			return fmt.Errorf("Failed unmarshalling signature header for block with id [%d] on channel [%s]: [%s]", block.Header.Number, chainID, err)
   180  		}
   181  		signatureSet = append(
   182  			signatureSet,
   183  			&protoutil.SignedData{
   184  				Identity:  shdr.Creator,
   185  				Data:      util.ConcatenateBytes(metadata.Value, metadataSignature.SignatureHeader, protoutil.BlockHeaderBytes(block.Header)),
   186  				Signature: metadataSignature.Signature,
   187  			},
   188  		)
   189  	}
   190  
   191  	// - Evaluate policy
   192  	return policy.EvaluateSignedData(signatureSet)
   193  }
   194  
   195  // Sign signs msg with this peer's signing key and outputs
   196  // the signature if no error occurred.
   197  func (s *MSPMessageCryptoService) Sign(msg []byte) ([]byte, error) {
   198  	return s.localSigner.Sign(msg)
   199  }
   200  
   201  // Verify checks that signature is a valid signature of message under a peer's verification key.
   202  // If the verification succeeded, Verify returns nil meaning no error occurred.
   203  // If peerIdentity is nil, then the verification fails.
   204  func (s *MSPMessageCryptoService) Verify(peerIdentity api.PeerIdentityType, signature, message []byte) error {
   205  	identity, chainID, err := s.getValidatedIdentity(peerIdentity)
   206  	if err != nil {
   207  		mcsLogger.Errorf("Failed getting validated identity from peer identity [%s]", err)
   208  
   209  		return err
   210  	}
   211  
   212  	if len(chainID) == 0 {
   213  		// At this stage, this means that peerIdentity
   214  		// belongs to this peer's LocalMSP.
   215  		// The signature is validated directly
   216  		return identity.Verify(message, signature)
   217  	}
   218  
   219  	// At this stage, the signature must be validated
   220  	// against the reader policy of the channel
   221  	// identified by chainID
   222  
   223  	return s.VerifyByChannel(chainID, peerIdentity, signature, message)
   224  }
   225  
   226  // VerifyByChannel checks that signature is a valid signature of message
   227  // under a peer's verification key, but also in the context of a specific channel.
   228  // If the verification succeeded, Verify returns nil meaning no error occurred.
   229  // If peerIdentity is nil, then the verification fails.
   230  func (s *MSPMessageCryptoService) VerifyByChannel(chainID common.ChannelID, peerIdentity api.PeerIdentityType, signature, message []byte) error {
   231  	// Validate arguments
   232  	if len(peerIdentity) == 0 {
   233  		return errors.New("Invalid Peer Identity. It must be different from nil.")
   234  	}
   235  
   236  	// Get the policy manager for channel chainID
   237  	cpm := s.channelPolicyManagerGetter.Manager(string(chainID))
   238  	if cpm == nil {
   239  		return fmt.Errorf("Could not acquire policy manager for channel %s", string(chainID))
   240  	}
   241  	mcsLogger.Debugf("Got policy manager for channel [%s]", string(chainID))
   242  
   243  	// Get channel reader policy
   244  	policy, flag := cpm.GetPolicy(policies.ChannelApplicationReaders)
   245  	mcsLogger.Debugf("Got reader policy for channel [%s] with flag [%t]", string(chainID), flag)
   246  
   247  	return policy.EvaluateSignedData(
   248  		[]*protoutil.SignedData{{
   249  			Data:      message,
   250  			Identity:  []byte(peerIdentity),
   251  			Signature: signature,
   252  		}},
   253  	)
   254  }
   255  
   256  func (s *MSPMessageCryptoService) Expiration(peerIdentity api.PeerIdentityType) (time.Time, error) {
   257  	id, _, err := s.getValidatedIdentity(peerIdentity)
   258  	if err != nil {
   259  		return time.Time{}, errors.Wrap(err, "Unable to extract msp.Identity from peer Identity")
   260  	}
   261  	return id.ExpiresAt(), nil
   262  
   263  }
   264  
   265  func (s *MSPMessageCryptoService) getValidatedIdentity(peerIdentity api.PeerIdentityType) (msp.Identity, common.ChannelID, error) {
   266  	// Validate arguments
   267  	if len(peerIdentity) == 0 {
   268  		return nil, nil, errors.New("Invalid Peer Identity. It must be different from nil.")
   269  	}
   270  
   271  	sId, err := s.deserializer.Deserialize(peerIdentity)
   272  	if err != nil {
   273  		mcsLogger.Error("failed deserializing identity", err)
   274  		return nil, nil, err
   275  	}
   276  
   277  	// Notice that peerIdentity is assumed to be the serialization of an identity.
   278  	// So, first step is the identity deserialization and then verify it.
   279  
   280  	// First check against the local MSP.
   281  	// If the peerIdentity is in the same organization of this node then
   282  	// the local MSP is required to take the final decision on the validity
   283  	// of the signature.
   284  	lDes := s.deserializer.GetLocalDeserializer()
   285  	identity, err := lDes.DeserializeIdentity([]byte(peerIdentity))
   286  	if err == nil {
   287  		// No error means that the local MSP successfully deserialized the identity.
   288  		// We now check additional properties.
   289  		if err := lDes.IsWellFormed(sId); err != nil {
   290  			return nil, nil, errors.Wrap(err, "identity is not well formed")
   291  		}
   292  		// TODO: The following check will be replaced by a check on the organizational units
   293  		// when we allow the gossip network to have organization unit (MSP subdivisions)
   294  		// scoped messages.
   295  		// The following check is consistent with the SecurityAdvisor#OrgByPeerIdentity
   296  		// implementation.
   297  		// TODO: Notice that the following check saves us from the fact
   298  		// that DeserializeIdentity does not yet enforce MSP-IDs consistency.
   299  		// This check can be removed once DeserializeIdentity will be fixed.
   300  		if identity.GetMSPIdentifier() == s.deserializer.GetLocalMSPIdentifier() {
   301  			// Check identity validity
   302  
   303  			// Notice that at this stage we don't have to check the identity
   304  			// against any channel's policies.
   305  			// This will be done by the caller function, if needed.
   306  			return identity, nil, identity.Validate()
   307  		}
   308  	}
   309  
   310  	// Check against managers
   311  	for chainID, mspManager := range s.deserializer.GetChannelDeserializers() {
   312  		// Deserialize identity
   313  		identity, err := mspManager.DeserializeIdentity([]byte(peerIdentity))
   314  		if err != nil {
   315  			mcsLogger.Debugf("Failed deserialization identity %s on [%s]: [%s]", peerIdentity, chainID, err)
   316  			continue
   317  		}
   318  
   319  		// We managed deserializing the identity with this MSP manager. Now we check if it's well formed.
   320  		if err := mspManager.IsWellFormed(sId); err != nil {
   321  			return nil, nil, errors.Wrap(err, "identity is not well formed")
   322  		}
   323  
   324  		// Check identity validity
   325  		// Notice that at this stage we don't have to check the identity
   326  		// against any channel's policies.
   327  		// This will be done by the caller function, if needed.
   328  
   329  		if err := identity.Validate(); err != nil {
   330  			mcsLogger.Debugf("Failed validating identity %s on [%s]: [%s]", peerIdentity, chainID, err)
   331  			continue
   332  		}
   333  
   334  		mcsLogger.Debugf("Validation succeeded %s on [%s]", peerIdentity, chainID)
   335  
   336  		return identity, common.ChannelID(chainID), nil
   337  	}
   338  
   339  	return nil, nil, fmt.Errorf("Peer Identity %s cannot be validated. No MSP found able to do that.", peerIdentity)
   340  }