github.com/turingchain2020/turingchain@v1.1.21/executor/authority/core/gmimpl.go (about)

     1  // Copyright Turing Corp. 2018 All Rights Reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package core
     6  
     7  import (
     8  	"bytes"
     9  	"crypto/ecdsa"
    10  	"crypto/x509/pkix"
    11  	"encoding/asn1"
    12  	"encoding/pem"
    13  	"errors"
    14  	"fmt"
    15  	"math/big"
    16  	"reflect"
    17  	"time"
    18  
    19  	"github.com/turingchain2020/turingchain/executor/authority/utils"
    20  
    21  	sm2_util "github.com/turingchain2020/turingchain/system/crypto/sm2"
    22  	"github.com/turingchain2020/turingchain/types"
    23  	"github.com/tjfoc/gmsm/sm2"
    24  )
    25  
    26  type gmValidator struct {
    27  	rootCerts []*sm2.Certificate
    28  
    29  	intermediateCerts []*sm2.Certificate
    30  
    31  	certificationTreeInternalNodesMap map[string]bool
    32  
    33  	opts *sm2.VerifyOptions
    34  
    35  	CRL []*pkix.CertificateList
    36  }
    37  
    38  // NewGmValidator 创建国密证书校验器
    39  func NewGmValidator() Validator {
    40  	return &gmValidator{}
    41  }
    42  
    43  func (validator *gmValidator) getCertFromPem(idBytes []byte) (*sm2.Certificate, error) {
    44  	if idBytes == nil {
    45  		return nil, fmt.Errorf("getIdentityFromConf error: nil idBytes")
    46  	}
    47  
    48  	pemCert, _ := pem.Decode(idBytes)
    49  	if pemCert == nil {
    50  		return nil, fmt.Errorf("getIdentityFromBytes error: could not decode pem bytes [%v]", idBytes)
    51  	}
    52  
    53  	var cert *sm2.Certificate
    54  	cert, err := sm2.ParseCertificate(pemCert.Bytes)
    55  	if err != nil {
    56  		return nil, fmt.Errorf("getIdentityFromBytes error: failed to parse sm2 cert, err %s", err)
    57  	}
    58  
    59  	return cert, nil
    60  }
    61  
    62  func (validator *gmValidator) Setup(conf *AuthConfig) error {
    63  	if conf == nil {
    64  		return fmt.Errorf("Setup error: nil conf reference")
    65  	}
    66  
    67  	if err := validator.setupCAs(conf); err != nil {
    68  		return err
    69  	}
    70  
    71  	if err := validator.setupCRLs(conf); err != nil {
    72  		return err
    73  	}
    74  
    75  	if err := validator.finalizeSetupCAs(conf); err != nil {
    76  		return err
    77  	}
    78  
    79  	return nil
    80  }
    81  
    82  func (validator *gmValidator) Validate(certByte []byte, pubKey []byte) error {
    83  	authLogger.Debug("validating certificate")
    84  
    85  	cert, err := validator.getCertFromPem(certByte)
    86  	if err != nil {
    87  		return fmt.Errorf("ParseCertificate failed %s", err)
    88  	}
    89  
    90  	certPubKey, ok := cert.PublicKey.(*ecdsa.PublicKey)
    91  	if !ok {
    92  		return fmt.Errorf("Error publick key type in transaction. expect SM2")
    93  	}
    94  
    95  	if !bytes.Equal(pubKey, sm2_util.SerializePublicKey(
    96  		ParseECDSAPubKey2SM2PubKey(certPubKey), len(pubKey) == sm2_util.SM2PublicKeyCompressed)) {
    97  		return fmt.Errorf("Invalid public key")
    98  	}
    99  
   100  	validationChain, err := validator.getCertificationChain(cert)
   101  	if err != nil {
   102  		return fmt.Errorf("Could not obtain certification chain, err %s", err)
   103  	}
   104  
   105  	err = validator.validateCertAgainstChain(cert.SerialNumber, validationChain)
   106  	if err != nil {
   107  		return fmt.Errorf("Could not validate identity against certification chain, err %s", err)
   108  	}
   109  
   110  	return nil
   111  }
   112  
   113  func (validator *gmValidator) getCertificationChain(cert *sm2.Certificate) ([]*sm2.Certificate, error) {
   114  	if validator.opts == nil {
   115  		return nil, errors.New("Invalid validator instance")
   116  	}
   117  
   118  	if cert.IsCA {
   119  		return nil, errors.New("A CA certificate cannot be used directly by this validator")
   120  	}
   121  
   122  	return validator.getValidationChain(cert, false)
   123  }
   124  
   125  func (validator *gmValidator) getUniqueValidationChain(cert *sm2.Certificate, opts sm2.VerifyOptions) ([]*sm2.Certificate, error) {
   126  	if validator.opts == nil {
   127  		return nil, fmt.Errorf("The supplied identity has no verify options")
   128  	}
   129  
   130  	validationChains, err := cert.Verify(opts)
   131  	if err != nil {
   132  		return nil, fmt.Errorf("The supplied identity is not valid, Verify() returned %s", err)
   133  	}
   134  
   135  	if len(validationChains) != 1 {
   136  		return nil, fmt.Errorf("This validator only supports a single validation chain, got %d", len(validationChains))
   137  	}
   138  
   139  	return validationChains[0], nil
   140  }
   141  
   142  func (validator *gmValidator) getValidationChain(cert *sm2.Certificate, isIntermediateChain bool) ([]*sm2.Certificate, error) {
   143  	validationChain, err := validator.getUniqueValidationChain(cert, validator.getValidityOptsForCert(cert))
   144  	if err != nil {
   145  		return nil, fmt.Errorf("Failed getting validation chain %s", err)
   146  	}
   147  
   148  	if len(validationChain) < 2 {
   149  		return nil, fmt.Errorf("Expected a chain of length at least 2, got %d", len(validationChain))
   150  	}
   151  
   152  	parentPosition := 1
   153  	if isIntermediateChain {
   154  		parentPosition = 0
   155  	}
   156  	if validator.certificationTreeInternalNodesMap[string(validationChain[parentPosition].Raw)] {
   157  		return nil, fmt.Errorf("Invalid validation chain. Parent certificate should be a leaf of the certification tree [%v]", cert.Raw)
   158  	}
   159  	return validationChain, nil
   160  }
   161  
   162  func (validator *gmValidator) setupCAs(conf *AuthConfig) error {
   163  	if len(conf.RootCerts) == 0 {
   164  		return errors.New("Expected at least one CA certificate")
   165  	}
   166  
   167  	validator.opts = &sm2.VerifyOptions{Roots: sm2.NewCertPool(), Intermediates: sm2.NewCertPool()}
   168  	for _, v := range conf.RootCerts {
   169  		cert, err := validator.getCertFromPem(v)
   170  		if err != nil {
   171  			return err
   172  		}
   173  		validator.opts.Roots.AddCert(cert)
   174  	}
   175  	for _, v := range conf.IntermediateCerts {
   176  		cert, err := validator.getCertFromPem(v)
   177  		if err != nil {
   178  			return err
   179  		}
   180  		validator.opts.Intermediates.AddCert(cert)
   181  	}
   182  
   183  	validator.rootCerts = make([]*sm2.Certificate, len(conf.RootCerts))
   184  	for i, trustedCert := range conf.RootCerts {
   185  		cert, err := validator.getCertFromPem(trustedCert)
   186  		if err != nil {
   187  			return err
   188  		}
   189  
   190  		validator.rootCerts[i] = cert
   191  	}
   192  
   193  	validator.intermediateCerts = make([]*sm2.Certificate, len(conf.IntermediateCerts))
   194  	for i, trustedCert := range conf.IntermediateCerts {
   195  		cert, err := validator.getCertFromPem(trustedCert)
   196  		if err != nil {
   197  			return err
   198  		}
   199  
   200  		validator.intermediateCerts[i] = cert
   201  	}
   202  
   203  	validator.opts = &sm2.VerifyOptions{Roots: sm2.NewCertPool(), Intermediates: sm2.NewCertPool()}
   204  	for _, cert := range validator.rootCerts {
   205  		validator.opts.Roots.AddCert(cert)
   206  	}
   207  	for _, cert := range validator.intermediateCerts {
   208  		validator.opts.Intermediates.AddCert(cert)
   209  	}
   210  
   211  	return nil
   212  }
   213  
   214  func (validator *gmValidator) setupCRLs(conf *AuthConfig) error {
   215  	validator.CRL = make([]*pkix.CertificateList, len(conf.RevocationList))
   216  	for i, crlbytes := range conf.RevocationList {
   217  		crl, err := sm2.ParseCRL(crlbytes)
   218  		if err != nil {
   219  			return fmt.Errorf("Could not parse RevocationList, err %s", err)
   220  		}
   221  
   222  		validator.CRL[i] = crl
   223  	}
   224  
   225  	return nil
   226  }
   227  
   228  func (validator *gmValidator) finalizeSetupCAs(config *AuthConfig) error {
   229  	for _, cert := range append(append([]*sm2.Certificate{}, validator.rootCerts...), validator.intermediateCerts...) {
   230  		if !isSm2CACert(cert) {
   231  			return fmt.Errorf("CA Certificate did not have the Subject Key Identifier extension, (SN: %s)", cert.SerialNumber)
   232  		}
   233  
   234  		if err := validator.validateCAIdentity(cert); err != nil {
   235  			return fmt.Errorf("CA Certificate is not valid, (SN: %s) [%s]", cert.SerialNumber, err)
   236  		}
   237  	}
   238  
   239  	validator.certificationTreeInternalNodesMap = make(map[string]bool)
   240  	for _, cert := range append([]*sm2.Certificate{}, validator.intermediateCerts...) {
   241  		chain, err := validator.getUniqueValidationChain(cert, validator.getValidityOptsForCert(cert))
   242  		if err != nil {
   243  			return fmt.Errorf("Failed getting validation chain, (SN: %s)", cert.SerialNumber)
   244  		}
   245  
   246  		for i := 1; i < len(chain); i++ {
   247  			validator.certificationTreeInternalNodesMap[string(chain[i].Raw)] = true
   248  		}
   249  	}
   250  
   251  	return nil
   252  }
   253  
   254  func getSubjectKeyIdentifierFromSm2Cert(cert *sm2.Certificate) ([]byte, error) {
   255  	var SKI []byte
   256  
   257  	for _, ext := range cert.Extensions {
   258  		if reflect.DeepEqual(ext.Id, asn1.ObjectIdentifier{2, 5, 29, 14}) {
   259  			_, err := asn1.Unmarshal(ext.Value, &SKI)
   260  			if err != nil {
   261  				return nil, fmt.Errorf("Failed to unmarshal Subject Key Identifier, err %s", err)
   262  			}
   263  
   264  			return SKI, nil
   265  		}
   266  	}
   267  
   268  	return nil, errors.New("subjectKeyIdentifier not found in certificate")
   269  }
   270  
   271  func isSm2CACert(cert *sm2.Certificate) bool {
   272  	_, err := getSubjectKeyIdentifierFromSm2Cert(cert)
   273  	if err != nil {
   274  		return false
   275  	}
   276  
   277  	if !cert.IsCA {
   278  		return false
   279  	}
   280  
   281  	return true
   282  }
   283  
   284  func (validator *gmValidator) validateCAIdentity(cert *sm2.Certificate) error {
   285  	if !cert.IsCA {
   286  		return errors.New("Only CA identities can be validated")
   287  	}
   288  
   289  	validationChain, err := validator.getUniqueValidationChain(cert, validator.getValidityOptsForCert(cert))
   290  	if err != nil {
   291  		return fmt.Errorf("Could not obtain certification chain, err %s", err)
   292  	}
   293  	if len(validationChain) == 1 {
   294  		return nil
   295  	}
   296  
   297  	return validator.validateCertAgainstChain(cert.SerialNumber, validationChain)
   298  }
   299  
   300  func (validator *gmValidator) validateCertAgainstChain(serialNumber *big.Int, validationChain []*sm2.Certificate) error {
   301  	SKI, err := getSubjectKeyIdentifierFromSm2Cert(validationChain[1])
   302  	if err != nil {
   303  		return fmt.Errorf("Could not obtain Subject Key Identifier for signer cert, err %s", err)
   304  	}
   305  
   306  	for _, crl := range validator.CRL {
   307  		aki, err := getAuthorityKeyIdentifierFromCrl(crl)
   308  		if err != nil {
   309  			return fmt.Errorf("Could not obtain Authority Key Identifier for crl, err %s", err)
   310  		}
   311  
   312  		if bytes.Equal(aki, SKI) {
   313  			for _, rc := range crl.TBSCertList.RevokedCertificates {
   314  				if rc.SerialNumber.Cmp(serialNumber) == 0 {
   315  					err = validationChain[1].CheckCRLSignature(crl)
   316  					if err != nil {
   317  						authLogger.Warn(fmt.Sprintf("Invalid signature over the identified CRL, error %s", err))
   318  						continue
   319  					}
   320  
   321  					return errors.New("The certificate has been revoked")
   322  				}
   323  			}
   324  		}
   325  	}
   326  
   327  	return nil
   328  }
   329  
   330  func (validator *gmValidator) getValidityOptsForCert(cert *sm2.Certificate) sm2.VerifyOptions {
   331  	var tempOpts sm2.VerifyOptions
   332  	tempOpts.Roots = validator.opts.Roots
   333  
   334  	tempOpts.DNSName = validator.opts.DNSName
   335  	tempOpts.Intermediates = validator.opts.Intermediates
   336  	tempOpts.KeyUsages = validator.opts.KeyUsages
   337  	tempOpts.CurrentTime = cert.NotBefore.Add(time.Second)
   338  
   339  	return tempOpts
   340  }
   341  
   342  func (validator *gmValidator) GetCertFromSignature(signature []byte) ([]byte, error) {
   343  	if len(signature) <= sm2_util.SM2SignatureMinLength {
   344  		authLogger.Error("invalid signature, please make sure certificate info encoded.")
   345  		return nil, types.ErrCertificate
   346  	}
   347  
   348  	// 从proto中解码signature
   349  	cert, err := utils.DecodeCertFromSignature(signature)
   350  	if err != nil {
   351  		authLogger.Error("unmashal certificate from signature failed.", "error", err.Error())
   352  		return nil, err
   353  	}
   354  
   355  	if len(cert.Cert) == 0 {
   356  		authLogger.Error("cert can not be null")
   357  		return nil, types.ErrInvalidParam
   358  	}
   359  
   360  	return cert.Cert, nil
   361  }