github.com/kaituanwang/hyperledger@v2.0.1+incompatible/msp/mspimplvalidate.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package msp
     8  
     9  import (
    10  	"bytes"
    11  	"crypto/x509"
    12  	"crypto/x509/pkix"
    13  	"encoding/asn1"
    14  	"math/big"
    15  	"reflect"
    16  	"time"
    17  
    18  	"github.com/pkg/errors"
    19  )
    20  
    21  func (msp *bccspmsp) validateIdentity(id *identity) error {
    22  	id.validationMutex.Lock()
    23  	defer id.validationMutex.Unlock()
    24  
    25  	// return cached validation value if already validated
    26  	if id.validated {
    27  		return id.validationErr
    28  	}
    29  
    30  	id.validated = true
    31  
    32  	validationChain, err := msp.getCertificationChainForBCCSPIdentity(id)
    33  	if err != nil {
    34  		id.validationErr = errors.WithMessage(err, "could not obtain certification chain")
    35  		return id.validationErr
    36  	}
    37  
    38  	err = msp.validateIdentityAgainstChain(id, validationChain)
    39  	if err != nil {
    40  		id.validationErr = errors.WithMessage(err, "could not validate identity against certification chain")
    41  		return id.validationErr
    42  	}
    43  
    44  	err = msp.internalValidateIdentityOusFunc(id)
    45  	if err != nil {
    46  		id.validationErr = errors.WithMessage(err, "could not validate identity's OUs")
    47  		return id.validationErr
    48  	}
    49  
    50  	return nil
    51  }
    52  
    53  func (msp *bccspmsp) validateCAIdentity(id *identity) error {
    54  	if !id.cert.IsCA {
    55  		return errors.New("Only CA identities can be validated")
    56  	}
    57  
    58  	validationChain, err := msp.getUniqueValidationChain(id.cert, msp.getValidityOptsForCert(id.cert))
    59  	if err != nil {
    60  		return errors.WithMessage(err, "could not obtain certification chain")
    61  	}
    62  	if len(validationChain) == 1 {
    63  		// validationChain[0] is the root CA certificate
    64  		return nil
    65  	}
    66  
    67  	return msp.validateIdentityAgainstChain(id, validationChain)
    68  }
    69  
    70  func (msp *bccspmsp) validateTLSCAIdentity(cert *x509.Certificate, opts *x509.VerifyOptions) error {
    71  	if !cert.IsCA {
    72  		return errors.New("Only CA identities can be validated")
    73  	}
    74  
    75  	validationChain, err := msp.getUniqueValidationChain(cert, *opts)
    76  	if err != nil {
    77  		return errors.WithMessage(err, "could not obtain certification chain")
    78  	}
    79  	if len(validationChain) == 1 {
    80  		// validationChain[0] is the root CA certificate
    81  		return nil
    82  	}
    83  
    84  	return msp.validateCertAgainstChain(cert, validationChain)
    85  }
    86  
    87  func (msp *bccspmsp) validateIdentityAgainstChain(id *identity, validationChain []*x509.Certificate) error {
    88  	return msp.validateCertAgainstChain(id.cert, validationChain)
    89  }
    90  
    91  func (msp *bccspmsp) validateCertAgainstChain(cert *x509.Certificate, validationChain []*x509.Certificate) error {
    92  	// here we know that the identity is valid; now we have to check whether it has been revoked
    93  
    94  	// identify the SKI of the CA that signed this cert
    95  	SKI, err := getSubjectKeyIdentifierFromCert(validationChain[1])
    96  	if err != nil {
    97  		return errors.WithMessage(err, "could not obtain Subject Key Identifier for signer cert")
    98  	}
    99  
   100  	// check whether one of the CRLs we have has this cert's
   101  	// SKI as its AuthorityKeyIdentifier
   102  	for _, crl := range msp.CRL {
   103  		aki, err := getAuthorityKeyIdentifierFromCrl(crl)
   104  		if err != nil {
   105  			return errors.WithMessage(err, "could not obtain Authority Key Identifier for crl")
   106  		}
   107  
   108  		// check if the SKI of the cert that signed us matches the AKI of any of the CRLs
   109  		if bytes.Equal(aki, SKI) {
   110  			// we have a CRL, check whether the serial number is revoked
   111  			for _, rc := range crl.TBSCertList.RevokedCertificates {
   112  				if rc.SerialNumber.Cmp(cert.SerialNumber) == 0 {
   113  					// We have found a CRL whose AKI matches the SKI of
   114  					// the CA (root or intermediate) that signed the
   115  					// certificate that is under validation. As a
   116  					// precaution, we verify that said CA is also the
   117  					// signer of this CRL.
   118  					err = validationChain[1].CheckCRLSignature(crl)
   119  					if err != nil {
   120  						// the CA cert that signed the certificate
   121  						// that is under validation did not sign the
   122  						// candidate CRL - skip
   123  						mspLogger.Warningf("Invalid signature over the identified CRL, error %+v", err)
   124  						continue
   125  					}
   126  
   127  					// A CRL also includes a time of revocation so that
   128  					// the CA can say "this cert is to be revoked starting
   129  					// from this time"; however here we just assume that
   130  					// revocation applies instantaneously from the time
   131  					// the MSP config is committed and used so we will not
   132  					// make use of that field
   133  					return errors.New("The certificate has been revoked")
   134  				}
   135  			}
   136  		}
   137  	}
   138  
   139  	return nil
   140  }
   141  
   142  func (msp *bccspmsp) validateIdentityOUsV1(id *identity) error {
   143  	// Check that the identity's OUs are compatible with those recognized by this MSP,
   144  	// meaning that the intersection is not empty.
   145  	if len(msp.ouIdentifiers) > 0 {
   146  		found := false
   147  
   148  		for _, OU := range id.GetOrganizationalUnits() {
   149  			certificationIDs, exists := msp.ouIdentifiers[OU.OrganizationalUnitIdentifier]
   150  
   151  			if exists {
   152  				for _, certificationID := range certificationIDs {
   153  					if bytes.Equal(certificationID, OU.CertifiersIdentifier) {
   154  						found = true
   155  						break
   156  					}
   157  				}
   158  			}
   159  		}
   160  
   161  		if !found {
   162  			if len(id.GetOrganizationalUnits()) == 0 {
   163  				return errors.New("the identity certificate does not contain an Organizational Unit (OU)")
   164  			}
   165  			return errors.Errorf("none of the identity's organizational units %s are in MSP %s", OUIDs(id.GetOrganizationalUnits()), msp.name)
   166  		}
   167  	}
   168  
   169  	return nil
   170  }
   171  
   172  func (msp *bccspmsp) validateIdentityOUsV11(id *identity) error {
   173  	// Run the same checks as per V1
   174  	err := msp.validateIdentityOUsV1(id)
   175  	if err != nil {
   176  		return err
   177  	}
   178  
   179  	// Perform V1_1 additional checks:
   180  	//
   181  	// -- Check for OU enforcement
   182  	if !msp.ouEnforcement {
   183  		// No enforcement required
   184  		return nil
   185  	}
   186  
   187  	// Make sure that the identity has only one of the special OUs
   188  	// used to tell apart clients or peers.
   189  	counter := 0
   190  	for _, OU := range id.GetOrganizationalUnits() {
   191  		// Is OU.OrganizationalUnitIdentifier one of the special OUs?
   192  		var nodeOU *OUIdentifier
   193  		switch OU.OrganizationalUnitIdentifier {
   194  		case msp.clientOU.OrganizationalUnitIdentifier:
   195  			nodeOU = msp.clientOU
   196  		case msp.peerOU.OrganizationalUnitIdentifier:
   197  			nodeOU = msp.peerOU
   198  		default:
   199  			continue
   200  		}
   201  
   202  		// Yes. Then, enforce the certifiers identifier is this is specified.
   203  		// It is not specified, it means that any certification path is fine.
   204  		if len(nodeOU.CertifiersIdentifier) != 0 && !bytes.Equal(nodeOU.CertifiersIdentifier, OU.CertifiersIdentifier) {
   205  			return errors.Errorf("certifiersIdentifier does not match: %v, MSP: [%s]", OUIDs(id.GetOrganizationalUnits()), msp.name)
   206  		}
   207  		counter++
   208  		if counter > 1 {
   209  			break
   210  		}
   211  	}
   212  	if counter != 1 {
   213  		return errors.Errorf("the identity must be a client or a peer identity to be valid, not a combination of them. OUs: %s, MSP: [%s]", OUIDs(id.GetOrganizationalUnits()), msp.name)
   214  	}
   215  
   216  	return nil
   217  }
   218  
   219  func (msp *bccspmsp) validateIdentityOUsV142(id *identity) error {
   220  	// Run the same checks as per V1
   221  	err := msp.validateIdentityOUsV1(id)
   222  	if err != nil {
   223  		return err
   224  	}
   225  
   226  	// -- Check for OU enforcement
   227  	if !msp.ouEnforcement {
   228  		// No enforcement required
   229  		return nil
   230  	}
   231  
   232  	// Make sure that the identity has only one of the special OUs
   233  	// used to tell apart clients, peers and admins.
   234  	counter := 0
   235  	validOUs := make(map[string]*OUIdentifier)
   236  	if msp.clientOU != nil {
   237  		validOUs[msp.clientOU.OrganizationalUnitIdentifier] = msp.clientOU
   238  	}
   239  	if msp.peerOU != nil {
   240  		validOUs[msp.peerOU.OrganizationalUnitIdentifier] = msp.peerOU
   241  	}
   242  	if msp.adminOU != nil {
   243  		validOUs[msp.adminOU.OrganizationalUnitIdentifier] = msp.adminOU
   244  	}
   245  	if msp.ordererOU != nil {
   246  		validOUs[msp.ordererOU.OrganizationalUnitIdentifier] = msp.ordererOU
   247  	}
   248  
   249  	for _, OU := range id.GetOrganizationalUnits() {
   250  		// Is OU.OrganizationalUnitIdentifier one of the special OUs?
   251  		nodeOU := validOUs[OU.OrganizationalUnitIdentifier]
   252  		if nodeOU == nil {
   253  			continue
   254  		}
   255  
   256  		// Yes. Then, enforce the certifiers identifier in this is specified.
   257  		// If is not specified, it means that any certification path is fine.
   258  		if len(nodeOU.CertifiersIdentifier) != 0 && !bytes.Equal(nodeOU.CertifiersIdentifier, OU.CertifiersIdentifier) {
   259  			return errors.Errorf("certifiersIdentifier does not match: %s, MSP: [%s]", OUIDs(id.GetOrganizationalUnits()), msp.name)
   260  		}
   261  		counter++
   262  		if counter > 1 {
   263  			break
   264  		}
   265  	}
   266  	if counter != 1 {
   267  		return errors.Errorf("the identity must be a client, a peer, an orderer or an admin identity to be valid, not a combination of them. OUs: %s, MSP: [%s]", OUIDs(id.GetOrganizationalUnits()), msp.name)
   268  	}
   269  
   270  	return nil
   271  }
   272  
   273  func (msp *bccspmsp) getValidityOptsForCert(cert *x509.Certificate) x509.VerifyOptions {
   274  	// First copy the opts to override the CurrentTime field
   275  	// in order to make the certificate passing the expiration test
   276  	// independently from the real local current time.
   277  	// This is a temporary workaround for FAB-3678
   278  
   279  	var tempOpts x509.VerifyOptions
   280  	tempOpts.Roots = msp.opts.Roots
   281  	tempOpts.DNSName = msp.opts.DNSName
   282  	tempOpts.Intermediates = msp.opts.Intermediates
   283  	tempOpts.KeyUsages = msp.opts.KeyUsages
   284  	tempOpts.CurrentTime = cert.NotBefore.Add(time.Second)
   285  
   286  	return tempOpts
   287  }
   288  
   289  /*
   290     This is the definition of the ASN.1 marshalling of AuthorityKeyIdentifier
   291     from https://www.ietf.org/rfc/rfc5280.txt
   292  
   293     AuthorityKeyIdentifier ::= SEQUENCE {
   294        keyIdentifier             [0] KeyIdentifier           OPTIONAL,
   295        authorityCertIssuer       [1] GeneralNames            OPTIONAL,
   296        authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL  }
   297  
   298     KeyIdentifier ::= OCTET STRING
   299  
   300     CertificateSerialNumber  ::=  INTEGER
   301  
   302  */
   303  
   304  type authorityKeyIdentifier struct {
   305  	KeyIdentifier             []byte  `asn1:"optional,tag:0"`
   306  	AuthorityCertIssuer       []byte  `asn1:"optional,tag:1"`
   307  	AuthorityCertSerialNumber big.Int `asn1:"optional,tag:2"`
   308  }
   309  
   310  // getAuthorityKeyIdentifierFromCrl returns the Authority Key Identifier
   311  // for the supplied CRL. The authority key identifier can be used to identify
   312  // the public key corresponding to the private key which was used to sign the CRL.
   313  func getAuthorityKeyIdentifierFromCrl(crl *pkix.CertificateList) ([]byte, error) {
   314  	aki := authorityKeyIdentifier{}
   315  
   316  	for _, ext := range crl.TBSCertList.Extensions {
   317  		// Authority Key Identifier is identified by the following ASN.1 tag
   318  		// authorityKeyIdentifier (2 5 29 35) (see https://tools.ietf.org/html/rfc3280.html)
   319  		if reflect.DeepEqual(ext.Id, asn1.ObjectIdentifier{2, 5, 29, 35}) {
   320  			_, err := asn1.Unmarshal(ext.Value, &aki)
   321  			if err != nil {
   322  				return nil, errors.Wrap(err, "failed to unmarshal AKI")
   323  			}
   324  
   325  			return aki.KeyIdentifier, nil
   326  		}
   327  	}
   328  
   329  	return nil, errors.New("authorityKeyIdentifier not found in certificate")
   330  }
   331  
   332  // getSubjectKeyIdentifierFromCert returns the Subject Key Identifier for the supplied certificate
   333  // Subject Key Identifier is an identifier of the public key of this certificate
   334  func getSubjectKeyIdentifierFromCert(cert *x509.Certificate) ([]byte, error) {
   335  	var SKI []byte
   336  
   337  	for _, ext := range cert.Extensions {
   338  		// Subject Key Identifier is identified by the following ASN.1 tag
   339  		// subjectKeyIdentifier (2 5 29 14) (see https://tools.ietf.org/html/rfc3280.html)
   340  		if reflect.DeepEqual(ext.Id, asn1.ObjectIdentifier{2, 5, 29, 14}) {
   341  			_, err := asn1.Unmarshal(ext.Value, &SKI)
   342  			if err != nil {
   343  				return nil, errors.Wrap(err, "failed to unmarshal Subject Key Identifier")
   344  			}
   345  
   346  			return SKI, nil
   347  		}
   348  	}
   349  
   350  	return nil, errors.New("subjectKeyIdentifier not found in certificate")
   351  }