github.com/tw-bc-group/fabric-ca-gm@v0.0.0-20201218004200-3b690512bd5a/lib/gmca.go (about)

     1  package lib
     2  
     3  import (
     4  	"crypto/sha1"
     5  	"crypto/x509"
     6  	"crypto/x509/pkix"
     7  	"encoding/asn1"
     8  	"encoding/hex"
     9  	"errors"
    10  	"fmt"
    11  	"net"
    12  	"net/mail"
    13  	"time"
    14  
    15  	"github.com/cloudflare/cfssl/config"
    16  	cferr "github.com/cloudflare/cfssl/errors"
    17  	"github.com/cloudflare/cfssl/helpers"
    18  
    19  	"crypto"
    20  	"crypto/rand"
    21  	"encoding/pem"
    22  	"io"
    23  	"math/big"
    24  
    25  	"github.com/Hyperledger-TWGC/tjfoc-gm/sm2"
    26  	x509GM "github.com/Hyperledger-TWGC/tjfoc-gm/x509"
    27  	"github.com/cloudflare/cfssl/certdb"
    28  	"github.com/cloudflare/cfssl/csr"
    29  	"github.com/cloudflare/cfssl/log"
    30  	"github.com/tw-bc-group/fabric-gm/bccsp"
    31  	"github.com/tw-bc-group/fabric-gm/bccsp/gm"
    32  
    33  	"github.com/cloudflare/cfssl/signer"
    34  	"github.com/tw-bc-group/fabric-ca-gm/util"
    35  )
    36  
    37  // add by thoughtwork's matrix
    38  func OverrideHosts(template *x509GM.Certificate, hosts []string) {
    39  	if hosts != nil {
    40  		template.IPAddresses = []net.IP{}
    41  		template.EmailAddresses = []string{}
    42  		template.DNSNames = []string{}
    43  	}
    44  
    45  	for i := range hosts {
    46  		if ip := net.ParseIP(hosts[i]); ip != nil {
    47  			template.IPAddresses = append(template.IPAddresses, ip)
    48  		} else if email, err := mail.ParseAddress(hosts[i]); err == nil && email != nil {
    49  			template.EmailAddresses = append(template.EmailAddresses, email.Address)
    50  		} else {
    51  			template.DNSNames = append(template.DNSNames, hosts[i])
    52  		}
    53  	}
    54  }
    55  
    56  // replaceSliceIfEmpty replaces the contents of replaced with newContents if
    57  // the slice referenced by replaced is empty
    58  func replaceSliceIfEmpty(replaced, newContents *[]string) {
    59  	if len(*replaced) == 0 {
    60  		*replaced = *newContents
    61  	}
    62  }
    63  
    64  // PopulateSubjectFromCSR has functionality similar to Name, except
    65  // it fills the fields of the resulting pkix.Name with req's if the
    66  // subject's corresponding fields are empty
    67  func PopulateSubjectFromCSR(s *signer.Subject, req pkix.Name) pkix.Name {
    68  	// if no subject, use req
    69  	if s == nil {
    70  		return req
    71  	}
    72  	name := s.Name()
    73  
    74  	if name.CommonName == "" {
    75  		name.CommonName = req.CommonName
    76  	}
    77  
    78  	replaceSliceIfEmpty(&name.Country, &req.Country)
    79  	replaceSliceIfEmpty(&name.Province, &req.Province)
    80  	replaceSliceIfEmpty(&name.Locality, &req.Locality)
    81  	replaceSliceIfEmpty(&name.Organization, &req.Organization)
    82  	replaceSliceIfEmpty(&name.OrganizationalUnit, &req.OrganizationalUnit)
    83  	if name.SerialNumber == "" {
    84  		name.SerialNumber = req.SerialNumber
    85  	}
    86  	return name
    87  }
    88  
    89  //证书签名
    90  func signCert(req signer.SignRequest, ca *CA) (cert []byte, err error) {
    91  	block, _ := pem.Decode([]byte(req.Request))
    92  	if block == nil {
    93  		return nil, fmt.Errorf("decode error")
    94  	}
    95  	if block.Type != "NEW CERTIFICATE REQUEST" && block.Type != "CERTIFICATE REQUEST" {
    96  		return nil, fmt.Errorf("not a csr")
    97  	}
    98  	template, err := parseCertificateRequest(block.Bytes)
    99  	if err != nil {
   100  		log.Infof("xxxx gmca.go ParseCertificateRequest error:[%s]", err)
   101  		return nil, err
   102  	}
   103  
   104  	certfile := ca.Config.CA.Certfile
   105  	//certfile := req.Profile
   106  	log.Infof("^^^^^^^^^^^^^^^^^^^^^^^certifle = %s", certfile)
   107  	_, rootSigner, x509cert, err := util.GetSignerFromCertFile(certfile, ca.csp)
   108  	if err != nil {
   109  
   110  		return nil, err
   111  	}
   112  	log.Infof("^^^^^^^^^^^^^^^^^^^^^^^x509cert = %v", x509cert)
   113  	rootca := ParseX509Certificate2Sm2(x509cert)
   114  
   115  	// add by thoughtwork's matrix
   116  	// override the ou with role
   117  	OverrideHosts(template, req.Hosts)
   118  	template.Subject = PopulateSubjectFromCSR(req.Subject, template.Subject)
   119  	profile, err := FindProfile(ca.enrollSigner.Policy(), req.Profile)
   120  	if err != nil {
   121  		return nil, err
   122  	}
   123  
   124  	err = FillTemplate(template, ca.enrollSigner.Policy().Default, profile, template.NotBefore, template.NotAfter)
   125  	if err != nil {
   126  		return nil, err
   127  	}
   128  
   129  
   130  
   131  	cert, err = gm.CreateCertificateToMem(template, rootca, rootSigner)
   132  	if err != nil {
   133  		return nil, err
   134  	}
   135  	log.Infof("^^^^^^^^^^^^^^^^^^^^^^^template = %v\n cert = %v\n Type = %T", template, cert, template.PublicKey)
   136  	clientCert, err := x509GM.ReadCertificateFromPem(cert)
   137  	log.Info("==================== Exit ParseCertificate")
   138  	if err == nil {
   139  		log.Infof("xxxx gmca.go signCert ok the sign cert len [%d]", len(cert))
   140  	} else {
   141  		return nil, err
   142  	}
   143  
   144  	var certRecord = certdb.CertificateRecord{
   145  		Serial:  clientCert.SerialNumber.String(),
   146  		AKI:     hex.EncodeToString(clientCert.AuthorityKeyId),
   147  		CALabel: req.Label,
   148  		Status:  "good",
   149  		Expiry:  clientCert.NotAfter,
   150  		PEM:     string(cert),
   151  	}
   152  	//aki := hex.EncodeToString(cert.AuthorityKeyId)
   153  	//serial := util.GetSerialAsHex(cert.SerialNumber)
   154  	err = ca.certDBAccessor.InsertCertificate(certRecord)
   155  	return
   156  }
   157  
   158  // CAPolicy contains the CA issuing policy as default policy.
   159  var CAPolicy = func() *config.Signing {
   160  	return &config.Signing{
   161  		Default: &config.SigningProfile{
   162  			Usage:        []string{"cert sign", "crl sign"},
   163  			ExpiryString: "43800h",
   164  			Expiry:       5 * helpers.OneYear,
   165  			CAConstraint: config.CAConstraint{IsCA: true},
   166  		},
   167  	}
   168  }
   169  
   170  type subjectPublicKeyInfo struct {
   171  	Algorithm        pkix.AlgorithmIdentifier
   172  	SubjectPublicKey asn1.BitString
   173  }
   174  
   175  func ComputeSKI(template *x509GM.Certificate) ([]byte, error) {
   176  	pub := template.PublicKey
   177  	encodedPub, err := x509GM.MarshalPKIXPublicKey(pub)
   178  	if err != nil {
   179  		return nil, err
   180  	}
   181  
   182  	var subPKI subjectPublicKeyInfo
   183  	_, err = asn1.Unmarshal(encodedPub, &subPKI)
   184  	if err != nil {
   185  		return nil, err
   186  	}
   187  
   188  	pubHash := sha1.Sum(subPKI.SubjectPublicKey.Bytes)
   189  	return pubHash[:], nil
   190  }
   191  
   192  type policyInformation struct {
   193  	PolicyIdentifier asn1.ObjectIdentifier
   194  	Qualifiers       []interface{} `asn1:"tag:optional,omitempty"`
   195  }
   196  
   197  type cpsPolicyQualifier struct {
   198  	PolicyQualifierID asn1.ObjectIdentifier
   199  	Qualifier         string `asn1:"tag:optional,ia5"`
   200  }
   201  
   202  type userNotice struct {
   203  	ExplicitText string `asn1:"tag:optional,utf8"`
   204  }
   205  type userNoticePolicyQualifier struct {
   206  	PolicyQualifierID asn1.ObjectIdentifier
   207  	Qualifier         userNotice
   208  }
   209  
   210  var (
   211  	// Per https://tools.ietf.org/html/rfc3280.html#page-106, this represents:
   212  	// iso(1) identified-organization(3) dod(6) internet(1) security(5)
   213  	//   mechanisms(5) pkix(7) id-qt(2) id-qt-cps(1)
   214  	iDQTCertificationPracticeStatement = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 2, 1}
   215  	// iso(1) identified-organization(3) dod(6) internet(1) security(5)
   216  	//   mechanisms(5) pkix(7) id-qt(2) id-qt-unotice(2)
   217  	iDQTUserNotice = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 2, 2}
   218  
   219  	// CTPoisonOID is the object ID of the critical poison extension for precertificates
   220  	// https://tools.ietf.org/html/rfc6962#page-9
   221  	CTPoisonOID = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 11129, 2, 4, 3}
   222  
   223  	// SCTListOID is the object ID for the Signed Certificate Timestamp certificate extension
   224  	// https://tools.ietf.org/html/rfc6962#page-14
   225  	SCTListOID = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 11129, 2, 4, 2}
   226  )
   227  
   228  func addPolicies(template *x509GM.Certificate, policies []config.CertificatePolicy) error {
   229  	var asn1PolicyList []policyInformation
   230  
   231  	for _, policy := range policies {
   232  		pi := policyInformation{
   233  			// The PolicyIdentifier is an OID assigned to a given issuer.
   234  			PolicyIdentifier: asn1.ObjectIdentifier(policy.ID),
   235  		}
   236  		for _, qualifier := range policy.Qualifiers {
   237  			switch qualifier.Type {
   238  			case "id-qt-unotice":
   239  				pi.Qualifiers = append(pi.Qualifiers,
   240  					userNoticePolicyQualifier{
   241  						PolicyQualifierID: iDQTUserNotice,
   242  						Qualifier: userNotice{
   243  							ExplicitText: qualifier.Value,
   244  						},
   245  					})
   246  			case "id-qt-cps":
   247  				pi.Qualifiers = append(pi.Qualifiers,
   248  					cpsPolicyQualifier{
   249  						PolicyQualifierID: iDQTCertificationPracticeStatement,
   250  						Qualifier:         qualifier.Value,
   251  					})
   252  			default:
   253  				return errors.New("Invalid qualifier type in Policies " + qualifier.Type)
   254  			}
   255  		}
   256  		asn1PolicyList = append(asn1PolicyList, pi)
   257  	}
   258  
   259  	asn1Bytes, err := asn1.Marshal(asn1PolicyList)
   260  	if err != nil {
   261  		return err
   262  	}
   263  
   264  	template.ExtraExtensions = append(template.ExtraExtensions, pkix.Extension{
   265  		Id:       asn1.ObjectIdentifier{2, 5, 29, 32},
   266  		Critical: false,
   267  		Value:    asn1Bytes,
   268  	})
   269  	return nil
   270  }
   271  
   272  func FillTemplate(template *x509GM.Certificate, defaultProfile, profile *config.SigningProfile, notBefore time.Time, notAfter time.Time) error {
   273  	ski, err := ComputeSKI(template)
   274  	if err != nil {
   275  		return err
   276  	}
   277  
   278  	var (
   279  		eku             []x509.ExtKeyUsage
   280  		ku              x509.KeyUsage
   281  		backdate        time.Duration
   282  		expiry          time.Duration
   283  		crlURL, ocspURL string
   284  		issuerURL       = profile.IssuerURL
   285  	)
   286  
   287  	// The third value returned from Usages is a list of unknown key usages.
   288  	// This should be used when validating the profile at load, and isn't used
   289  	// here.
   290  	ku, eku, _ = profile.Usages()
   291  	sm2eku := make([]x509GM.ExtKeyUsage, len(eku))
   292  
   293  	for i := 0; i < len(eku); i++ {
   294  		sm2eku[i] = x509GM.ExtKeyUsage(eku[i])
   295  	}
   296  
   297  	if profile.IssuerURL == nil {
   298  		issuerURL = defaultProfile.IssuerURL
   299  	}
   300  
   301  	if ku == 0 && len(eku) == 0 {
   302  		return cferr.New(cferr.PolicyError, cferr.NoKeyUsages)
   303  	}
   304  
   305  	if expiry = profile.Expiry; expiry == 0 {
   306  		expiry = defaultProfile.Expiry
   307  	}
   308  
   309  	if crlURL = profile.CRL; crlURL == "" {
   310  		crlURL = defaultProfile.CRL
   311  	}
   312  	if ocspURL = profile.OCSP; ocspURL == "" {
   313  		ocspURL = defaultProfile.OCSP
   314  	}
   315  
   316  	if notBefore.IsZero() {
   317  		if !profile.NotBefore.IsZero() {
   318  			notBefore = profile.NotBefore
   319  		} else {
   320  			if backdate = profile.Backdate; backdate == 0 {
   321  				backdate = -5 * time.Minute
   322  			} else {
   323  				backdate = -1 * profile.Backdate
   324  			}
   325  			notBefore = time.Now().Round(time.Minute).Add(backdate)
   326  		}
   327  	}
   328  	notBefore = notBefore.UTC()
   329  
   330  	if notAfter.IsZero() {
   331  		if !profile.NotAfter.IsZero() {
   332  			notAfter = profile.NotAfter
   333  		} else {
   334  			notAfter = notBefore.Add(expiry)
   335  		}
   336  	}
   337  	notAfter = notAfter.UTC()
   338  
   339  	template.NotBefore = notBefore
   340  	template.NotAfter = notAfter
   341  	template.KeyUsage = x509GM.KeyUsage(ku)
   342  	template.ExtKeyUsage = sm2eku
   343  	template.BasicConstraintsValid = true
   344  	template.IsCA = profile.CAConstraint.IsCA
   345  	if template.IsCA {
   346  		template.MaxPathLen = profile.CAConstraint.MaxPathLen
   347  		if template.MaxPathLen == 0 {
   348  			template.MaxPathLenZero = profile.CAConstraint.MaxPathLenZero
   349  		}
   350  		template.DNSNames = nil
   351  		template.EmailAddresses = nil
   352  	}
   353  	template.SubjectKeyId = ski
   354  
   355  	if ocspURL != "" {
   356  		template.OCSPServer = []string{ocspURL}
   357  	}
   358  	if crlURL != "" {
   359  		template.CRLDistributionPoints = []string{crlURL}
   360  	}
   361  
   362  	if len(issuerURL) != 0 {
   363  		template.IssuingCertificateURL = issuerURL
   364  	}
   365  	if len(profile.Policies) != 0 {
   366  		err = addPolicies(template, profile.Policies)
   367  		if err != nil {
   368  			return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, err)
   369  		}
   370  	}
   371  	if profile.OCSPNoCheck {
   372  		ocspNoCheckExtension := pkix.Extension{
   373  			Id:       asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 1, 5},
   374  			Critical: false,
   375  			Value:    []byte{0x05, 0x00},
   376  		}
   377  		template.ExtraExtensions = append(template.ExtraExtensions, ocspNoCheckExtension)
   378  	}
   379  
   380  	return nil
   381  }
   382  
   383  func FindProfile(policy *config.Signing, profile string) (*config.SigningProfile, error) {
   384  	var p *config.SigningProfile
   385  	if policy != nil && policy.Profiles != nil && profile != "" {
   386  		p = policy.Profiles[profile]
   387  	}
   388  
   389  	if p == nil && policy != nil {
   390  		p = policy.Default
   391  	}
   392  
   393  	if p == nil {
   394  		return nil, cferr.Wrap(cferr.APIClientError, cferr.ClientHTTPError, errors.New("profile must not be nil"))
   395  	}
   396  	return p, nil
   397  }
   398  
   399  //生成证书
   400  func createGmSm2Cert(key bccsp.Key, req *csr.CertificateRequest, signer crypto.Signer) (cert []byte, err error) {
   401  	log.Infof("xxx xxx in gmca.go  createGmSm2Cert...key :%T", key)
   402  
   403  	policy := CAPolicy()
   404  	if req.CA != nil {
   405  		if req.CA.Expiry != "" {
   406  			policy.Default.ExpiryString = req.CA.Expiry
   407  			policy.Default.Expiry, err = time.ParseDuration(req.CA.Expiry)
   408  			if err != nil {
   409  				return nil, err
   410  			}
   411  		}
   412  
   413  		policy.Default.CAConstraint.MaxPathLen = req.CA.PathLength
   414  		if req.CA.PathLength != 0 && req.CA.PathLenZero == true {
   415  			log.Infof("ignore invalid 'pathlenzero' value")
   416  		} else {
   417  			policy.Default.CAConstraint.MaxPathLenZero = req.CA.PathLenZero
   418  		}
   419  	}
   420  
   421  	if !policy.Valid() {
   422  		return nil, cferr.New(cferr.PolicyError, cferr.InvalidPolicy)
   423  	}
   424  
   425  	csrPEM, err := generate(signer, req)
   426  	if err != nil {
   427  		log.Infof("xxxxxxxxxxxxx create csr error:%s", err)
   428  	}
   429  	log.Infof("xxxxxxxxxxxxx create gm csr completed!")
   430  	block, _ := pem.Decode(csrPEM)
   431  	if block == nil {
   432  		return nil, fmt.Errorf("sm2 csr DecodeFailed")
   433  	}
   434  
   435  	if block.Type != "NEW CERTIFICATE REQUEST" && block.Type != "CERTIFICATE REQUEST" {
   436  		return nil, fmt.Errorf("sm2 not a csr")
   437  	}
   438  	sm2Template, err := parseCertificateRequest(block.Bytes)
   439  	if err != nil {
   440  		log.Infof("parseCertificateRequest return err:%s", err)
   441  		return nil, err
   442  	}
   443  
   444  	err = FillTemplate(sm2Template, policy.Default, policy.Default, time.Time{}, time.Time{})
   445  	if err != nil {
   446  		return nil, err
   447  	}
   448  
   449  	sm2Template.SubjectKeyId = key.SKI()
   450  	log.Infof("key is %T   ---%T", sm2Template.PublicKey, sm2Template)
   451  	cert, err = gm.CreateCertificateToMem(sm2Template, sm2Template, signer)
   452  	return cert, err
   453  }
   454  
   455  //证书请求转换成证书  参数为  block .Bytes
   456  func parseCertificateRequest(csrBytes []byte) (template *x509GM.Certificate, err error) {
   457  	csrv, err := x509GM.ParseCertificateRequest(csrBytes)
   458  	if err != nil {
   459  		//err = cferr.Wrap(cferr.CSRError, cferr.ParseFailed, err)
   460  		return
   461  	}
   462  	err = csrv.CheckSignature()
   463  	// if err != nil {
   464  	// 	//err = cferr.Wrap(cferr.CSRError, cferr.KeyMismatch, err)
   465  	// 	return
   466  	// }
   467  	template = &x509GM.Certificate{
   468  		Subject:            csrv.Subject,
   469  		PublicKeyAlgorithm: csrv.PublicKeyAlgorithm,
   470  		PublicKey:          csrv.PublicKey,
   471  		SignatureAlgorithm: csrv.SignatureAlgorithm,
   472  		DNSNames:           csrv.DNSNames,
   473  		IPAddresses:        csrv.IPAddresses,
   474  		EmailAddresses:     csrv.EmailAddresses,
   475  	}
   476  
   477  	fmt.Printf("^^^^^^^^^^^^^^^^^^^^^^^^^^algorithn = %v, %v\n", template.PublicKeyAlgorithm, template.SignatureAlgorithm)
   478  	log.Infof("xxxx publicKey :%T", template.PublicKey)
   479  
   480  	template.NotBefore = time.Now()
   481  	template.NotAfter = time.Now().Add(time.Hour * 1000)
   482  	//log.Infof("-----------csrv = %+v", csrv)
   483  	for _, val := range csrv.Extensions {
   484  		// Check the CSR for the X.509 BasicConstraints (RFC 5280, 4.2.1.9)
   485  		// extension and append to template if necessary
   486  		if val.Id.Equal(asn1.ObjectIdentifier{2, 5, 29, 19}) {
   487  			var constraints csr.BasicConstraints
   488  			var rest []byte
   489  
   490  			if rest, err = asn1.Unmarshal(val.Value, &constraints); err != nil {
   491  				//return nil, cferr.Wrap(cferr.CSRError, cferr.ParseFailed, err)
   492  			} else if len(rest) != 0 {
   493  				//return nil, cferr.Wrap(cferr.CSRError, cferr.ParseFailed, errors.New("x509: trailing data after X.509 BasicConstraints"))
   494  			}
   495  
   496  			template.BasicConstraintsValid = true
   497  			template.IsCA = constraints.IsCA
   498  			template.MaxPathLen = constraints.MaxPathLen
   499  			template.MaxPathLenZero = template.MaxPathLen == 0
   500  		}
   501  	}
   502  	serialNumber := make([]byte, 20)
   503  	_, err = io.ReadFull(rand.Reader, serialNumber)
   504  	if err != nil {
   505  		return nil, err
   506  	}
   507  
   508  	// SetBytes interprets buf as the bytes of a big-endian
   509  	// unsigned integer. The leading byte should be masked
   510  	// off to ensure it isn't negative.
   511  	serialNumber[0] &= 0x7F
   512  
   513  	template.SerialNumber = new(big.Int).SetBytes(serialNumber)
   514  
   515  	return
   516  }
   517  
   518  //cloudflare 证书请求 转成 国密证书请求
   519  func generate(priv crypto.Signer, req *csr.CertificateRequest) (csr []byte, err error) {
   520  	log.Info("xx entry gm generate")
   521  	sigAlgo := signerAlgo(priv)
   522  	if sigAlgo == x509GM.UnknownSignatureAlgorithm {
   523  		return nil, fmt.Errorf("Private key is unavailable")
   524  	}
   525  	log.Info("xx begin create sm2.CertificateRequest")
   526  	var tpl = x509GM.CertificateRequest{
   527  		Subject:            req.Name(),
   528  		SignatureAlgorithm: sigAlgo,
   529  	}
   530  	for i := range req.Hosts {
   531  		if ip := net.ParseIP(req.Hosts[i]); ip != nil {
   532  			tpl.IPAddresses = append(tpl.IPAddresses, ip)
   533  		} else if email, err := mail.ParseAddress(req.Hosts[i]); err == nil && email != nil {
   534  			tpl.EmailAddresses = append(tpl.EmailAddresses, email.Address)
   535  		} else {
   536  			tpl.DNSNames = append(tpl.DNSNames, req.Hosts[i])
   537  		}
   538  	}
   539  
   540  	if req.CA != nil {
   541  		err = appendCAInfoToCSRSm2(req.CA, &tpl)
   542  		if err != nil {
   543  			err = fmt.Errorf("sm2 GenerationFailed")
   544  			return
   545  		}
   546  	}
   547  	if req.SerialNumber != "" {
   548  
   549  	}
   550  	csr, err = gm.CreateSm2CertificateRequestToMem(&tpl, priv)
   551  	log.Info("xx exit generate")
   552  	return csr, err
   553  }
   554  
   555  func signerAlgo(priv crypto.Signer) x509GM.SignatureAlgorithm {
   556  	switch pub := priv.Public().(type) {
   557  	case *sm2.PublicKey:
   558  		switch pub.Curve {
   559  		case sm2.P256Sm2():
   560  			return x509GM.SM2WithSM3
   561  		default:
   562  			return x509GM.SM2WithSM3
   563  		}
   564  	default:
   565  		return x509GM.UnknownSignatureAlgorithm
   566  	}
   567  }
   568  
   569  // appendCAInfoToCSR appends CAConfig BasicConstraint extension to a CSR
   570  func appendCAInfoToCSR(reqConf *csr.CAConfig, csreq *x509.CertificateRequest) error {
   571  	pathlen := reqConf.PathLength
   572  	if pathlen == 0 && !reqConf.PathLenZero {
   573  		pathlen = -1
   574  	}
   575  	val, err := asn1.Marshal(csr.BasicConstraints{true, pathlen})
   576  
   577  	if err != nil {
   578  		return err
   579  	}
   580  
   581  	csreq.ExtraExtensions = []pkix.Extension{
   582  		{
   583  			Id:       asn1.ObjectIdentifier{2, 5, 29, 19},
   584  			Value:    val,
   585  			Critical: true,
   586  		},
   587  	}
   588  	return nil
   589  }
   590  
   591  // appendCAInfoToCSR appends CAConfig BasicConstraint extension to a CSR
   592  func appendCAInfoToCSRSm2(reqConf *csr.CAConfig, csreq *x509GM.CertificateRequest) error {
   593  	pathlen := reqConf.PathLength
   594  	if pathlen == 0 && !reqConf.PathLenZero {
   595  		pathlen = -1
   596  	}
   597  	val, err := asn1.Marshal(csr.BasicConstraints{true, pathlen})
   598  
   599  	if err != nil {
   600  		return err
   601  	}
   602  
   603  	csreq.ExtraExtensions = []pkix.Extension{
   604  		{
   605  			Id:       asn1.ObjectIdentifier{2, 5, 29, 19},
   606  			Value:    val,
   607  			Critical: true,
   608  		},
   609  	}
   610  
   611  	return nil
   612  }
   613  
   614  func ParseX509Certificate2Sm2(x509Cert *x509.Certificate) *x509GM.Certificate {
   615  	sm2cert := &x509GM.Certificate{
   616  		Raw:                         x509Cert.Raw,
   617  		RawTBSCertificate:           x509Cert.RawTBSCertificate,
   618  		RawSubjectPublicKeyInfo:     x509Cert.RawSubjectPublicKeyInfo,
   619  		RawSubject:                  x509Cert.RawSubject,
   620  		RawIssuer:                   x509Cert.RawIssuer,
   621  		Signature:                   x509Cert.Signature,
   622  		SignatureAlgorithm:          x509GM.SignatureAlgorithm(x509Cert.SignatureAlgorithm),
   623  		PublicKeyAlgorithm:          x509GM.PublicKeyAlgorithm(x509Cert.PublicKeyAlgorithm),
   624  		PublicKey:                   x509Cert.PublicKey,
   625  		Version:                     x509Cert.Version,
   626  		SerialNumber:                x509Cert.SerialNumber,
   627  		Issuer:                      x509Cert.Issuer,
   628  		Subject:                     x509Cert.Subject,
   629  		NotBefore:                   x509Cert.NotBefore,
   630  		NotAfter:                    x509Cert.NotAfter,
   631  		KeyUsage:                    x509GM.KeyUsage(x509Cert.KeyUsage),
   632  		Extensions:                  x509Cert.Extensions,
   633  		ExtraExtensions:             x509Cert.ExtraExtensions,
   634  		UnhandledCriticalExtensions: x509Cert.UnhandledCriticalExtensions,
   635  		//ExtKeyUsage:	[]x509.ExtKeyUsage(x509Cert.ExtKeyUsage) ,
   636  		UnknownExtKeyUsage:    x509Cert.UnknownExtKeyUsage,
   637  		BasicConstraintsValid: x509Cert.BasicConstraintsValid,
   638  		IsCA:                  x509Cert.IsCA,
   639  		MaxPathLen:            x509Cert.MaxPathLen,
   640  		// MaxPathLenZero indicates that BasicConstraintsValid==true and
   641  		// MaxPathLen==0 should be interpreted as an actual maximum path length
   642  		// of zero. Otherwise, that combination is interpreted as MaxPathLen
   643  		// not being set.
   644  		MaxPathLenZero: x509Cert.MaxPathLenZero,
   645  		SubjectKeyId:   x509Cert.SubjectKeyId,
   646  		AuthorityKeyId: x509Cert.AuthorityKeyId,
   647  		// RFC 5280, 4.2.2.1 (Authority Information Access)
   648  		OCSPServer:            x509Cert.OCSPServer,
   649  		IssuingCertificateURL: x509Cert.IssuingCertificateURL,
   650  		// Subject Alternate Name values
   651  		DNSNames:       x509Cert.DNSNames,
   652  		EmailAddresses: x509Cert.EmailAddresses,
   653  		IPAddresses:    x509Cert.IPAddresses,
   654  		// Name constraints
   655  		PermittedDNSDomainsCritical: x509Cert.PermittedDNSDomainsCritical,
   656  		PermittedDNSDomains:         x509Cert.PermittedDNSDomains,
   657  		// CRL Distribution Points
   658  		CRLDistributionPoints: x509Cert.CRLDistributionPoints,
   659  		PolicyIdentifiers:     x509Cert.PolicyIdentifiers,
   660  	}
   661  	for _, val := range x509Cert.ExtKeyUsage {
   662  		sm2cert.ExtKeyUsage = append(sm2cert.ExtKeyUsage, x509GM.ExtKeyUsage(val))
   663  	}
   664  	return sm2cert
   665  }