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 }