gitee.com/lh-her-team/common@v1.5.1/crypto/tls/gm_support.go (about)

     1  // Copyright 2017 The Go Authors. 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 tls
     6  
     7  import (
     8  	"crypto"
     9  	"crypto/cipher"
    10  	"crypto/hmac"
    11  	"encoding/pem"
    12  	"errors"
    13  	"fmt"
    14  	"io/ioutil"
    15  	"strings"
    16  	"sync"
    17  
    18  	"gitee.com/lh-her-team/common/crypto/x509"
    19  	"github.com/tjfoc/gmsm/sm2"
    20  	"github.com/tjfoc/gmsm/sm3"
    21  	"github.com/tjfoc/gmsm/sm4"
    22  )
    23  
    24  const VersionGMSSL = 0x0101 // GM/T 0024-2014
    25  
    26  var pemCAs = []struct {
    27  	name string
    28  	pem  string
    29  }{
    30  	{
    31  		name: "CFCA",
    32  		pem: `-----BEGIN CERTIFICATE-----
    33  MIICezCCAh6gAwIBAgIQJRABs1dlPn+86pb7bT74wjAMBggqgRzPVQGDdQUAMFgx
    34  CzAJBgNVBAYTAkNOMTAwLgYDVQQKDCdDaGluYSBGaW5hbmNpYWwgQ2VydGlmaWNh
    35  dGlvbiBBdXRob3JpdHkxFzAVBgNVBAMMDkNGQ0EgQ1MgU00yIENBMB4XDTE1MDcx
    36  MTAzMTUxM1oXDTM1MDcwNDAzMTUxM1owJTELMAkGA1UEBhMCQ04xFjAUBgNVBAoM
    37  DUNGQ0EgU00yIE9DQTEwWTATBgcqhkjOPQIBBggqgRzPVQGCLQNCAAR8mpCijT4m
    38  jIJHLSaxLZibTvrydXWlIu4r261LWKPfyhtYPKarSgxFHBTMMwRAjX0JqOjclSgY
    39  XE6+wD5ha7dco4H6MIH3MB8GA1UdIwQYMBaAFOSO3dSj57YP7h0nls113CUlcmnd
    40  MA8GA1UdEwEB/wQFMAMBAf8wgZMGA1UdHwSBizCBiDBVoFOgUaRPME0xCzAJBgNV
    41  BAYTAkNOMRMwEQYDVQQKDApDRkNBIENTIENBMQwwCgYDVQQLDANDUkwxDDAKBgNV
    42  BAsMA1NNMjENMAsGA1UEAwwEY3JsMTAvoC2gK4YpaHR0cDovL2NybC5jZmNhLmNv
    43  bS5jbi9jc3JjYS9TTTIvY3JsMS5jcmwwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQW
    44  BBRck1ggWiRzVhAbZFAQ7OmnygdBETAMBggqgRzPVQGDdQUAA0kAMEYCIQCka+W4
    45  lEDJGbdoQKfMyMIrwkuRjxV4fXu+CQZIsYGFnQIhAKFs1nR4OHFxsdjHPXG0CBx+
    46  1C++KMPnVTWTsfH9fKPf
    47  -----END CERTIFICATE-----`,
    48  	},
    49  	{
    50  		name: "TEST",
    51  		pem: `-----BEGIN CERTIFICATE-----
    52  MIIBgTCCASegAwIBAgIRAJa6ZDaSc3wau4+2sLM2zhMwCgYIKoEcz1UBg3UwJTEL
    53  MAkGA1UEBhMCQ04xFjAUBgNVBAoTDWNhLmNldGNzYy5jb20wHhcNMTgxMjI0MDk1
    54  NDMyWhcNMzgxMjE5MDk1NDMyWjAlMQswCQYDVQQGEwJDTjEWMBQGA1UEChMNY2Eu
    55  Y2V0Y3NjLmNvbTBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABNzzDdS5/RMcpbYW
    56  d+hzCdocFpSOynYzalPvPWdyINM/7AP3DKYrYKyfa4jtW5xqYTpufWUabhSkvG3C
    57  DGBbmE6jODA2MA4GA1UdDwEB/wQEAwIChDATBgNVHSUEDDAKBggrBgEFBQcDATAP
    58  BgNVHRMBAf8EBTADAQH/MAoGCCqBHM9VAYN1A0gAMEUCIQCsbtt9tJOtgwO6iavS
    59  NB8Cs3U2so5gFQq6YdtX7d4EtgIgcVu9SQzlDmmmk61AaEES9UJgENmxrdhkon2T
    60  vHTeE7Y=
    61  -----END CERTIFICATE-----`,
    62  	},
    63  }
    64  
    65  var certCAs []*x509.Certificate
    66  
    67  var initonce sync.Once
    68  
    69  func getCAs() []*x509.Certificate {
    70  	// mod by syl remove pre insert ca certs
    71  	return nil
    72  	initonce.Do(func() {
    73  		for _, pemca := range pemCAs {
    74  			block, _ := pem.Decode([]byte(pemca.pem))
    75  			ca, err := x509.ParseCertificate(block.Bytes)
    76  			if err != nil {
    77  				panic(err)
    78  			}
    79  			certCAs = append(certCAs, ca)
    80  		}
    81  	})
    82  	return certCAs
    83  }
    84  
    85  // A list of cipher suite IDs that are, or have been, implemented by this
    86  // package.
    87  const (
    88  	//GM crypto suites ID  Taken from GM/T 0024-2014
    89  	GMTLS_ECDHE_SM2_WITH_SM1_SM3 uint16 = 0xe001
    90  	GMTLS_SM2_WITH_SM1_SM3       uint16 = 0xe003
    91  	GMTLS_IBSDH_WITH_SM1_SM3     uint16 = 0xe005
    92  	GMTLS_IBC_WITH_SM1_SM3       uint16 = 0xe007
    93  	GMTLS_RSA_WITH_SM1_SM3       uint16 = 0xe009
    94  	GMTLS_RSA_WITH_SM1_SHA1      uint16 = 0xe00a
    95  	GMTLS_ECDHE_SM2_WITH_SM4_SM3 uint16 = 0xe011
    96  	GMTLS_ECDHE_SM4_CBC_SM3      uint16 = 0xe011
    97  	GMTLS_ECDHE_SM4_GCM_SM3      uint16 = 0xe051
    98  	GMTLS_SM2_WITH_SM4_SM3       uint16 = 0xe013
    99  	GMTLS_ECC_SM4_CBC_SM3        uint16 = 0xe013
   100  	GMTLS_ECC_SM4_GCM_SM3        uint16 = 0xe053
   101  	GMTLS_IBSDH_WITH_SM4_SM3     uint16 = 0xe015
   102  	GMTLS_IBC_WITH_SM4_SM3       uint16 = 0xe017
   103  	GMTLS_RSA_WITH_SM4_SM3       uint16 = 0xe019
   104  	GMTLS_RSA_WITH_SM4_SHA1      uint16 = 0xe01a
   105  )
   106  
   107  var gmCipherSuites = []*cipherSuite{
   108  	{GMTLS_ECC_SM4_CBC_SM3, 16, 32, 16, eccGMKA, suiteECSign, cipherSM4, macSM3, nil},
   109  	{GMTLS_ECC_SM4_GCM_SM3, 16, 0, 4, eccGMKA, suiteECSign, nil, nil, aeadSM4GCM},
   110  
   111  	{GMTLS_ECDHE_SM4_CBC_SM3, 16, 32, 16, ecdheGMKA, suiteECDHE | suiteECSign, cipherSM4, macSM3, nil},
   112  	{GMTLS_ECDHE_SM4_GCM_SM3, 16, 0, 4, ecdheGMKA, suiteECDHE | suiteECSign, nil, nil, aeadSM4GCM},
   113  }
   114  
   115  // aeadSM4GCM SM4 GCM向前加解密函数
   116  // key: 对称密钥
   117  // nonce: 隐式随机数 (implicit nonce 4 Byte)
   118  func aeadSM4GCM(key []byte, nonce []byte) cipher.AEAD {
   119  	if len(nonce) != noncePrefixLength {
   120  		panic("tls: internal error: wrong implicit nonce length")
   121  	}
   122  	block, err := sm4.NewCipher(key)
   123  	if err != nil {
   124  		panic(err)
   125  	}
   126  	aead, err := cipher.NewGCMWithNonceSize(block, 12)
   127  	if err != nil {
   128  		panic(err)
   129  	}
   130  	// AEAD 使用的随机数应由显式和隐式两部分构成,
   131  	// 显式部分即 nonce explicit,客户端和服务端使用隐式部分
   132  	// 分别来自 client_write_iv 和 server_write_iv。
   133  	// AEAD使用的随机数和计数器的构造参见 RFC 5116
   134  	ret := &prefixNonceAEAD{aead: aead}
   135  	copy(ret.nonce[:], nonce)
   136  	return ret
   137  }
   138  
   139  func getCipherSuites(c *Config) []uint16 {
   140  	s := c.CipherSuites
   141  	if s == nil {
   142  		s = []uint16{
   143  			GMTLS_ECC_SM4_CBC_SM3,
   144  			GMTLS_ECC_SM4_GCM_SM3,
   145  			GMTLS_ECDHE_SM4_CBC_SM3,
   146  			GMTLS_ECDHE_SM4_GCM_SM3,
   147  		}
   148  	}
   149  	return s
   150  }
   151  
   152  func cipherSM4(key, iv []byte, isRead bool) interface{} {
   153  	block, _ := sm4.NewCipher(key)
   154  	if isRead {
   155  		return cipher.NewCBCDecrypter(block, iv)
   156  	}
   157  	return cipher.NewCBCEncrypter(block, iv)
   158  }
   159  
   160  // macSHA1 returns a macFunction for the given protocol version.
   161  func macSM3(version uint16, key []byte) macFunction {
   162  	return tls10MAC{h: hmac.New(sm3.New, key)}
   163  }
   164  
   165  //used for adapt the demand of finishHash write
   166  type nilMD5Hash struct{}
   167  
   168  func (nilMD5Hash) Write(p []byte) (n int, err error) {
   169  	return 0, nil
   170  }
   171  
   172  func (nilMD5Hash) Sum(b []byte) []byte {
   173  	return nil
   174  }
   175  
   176  func (nilMD5Hash) Reset() {
   177  }
   178  
   179  func (nilMD5Hash) Size() int {
   180  	return 0
   181  }
   182  
   183  func (nilMD5Hash) BlockSize() int {
   184  	return 0
   185  }
   186  
   187  func newFinishedHashGM(cipherSuite *cipherSuite) finishedHash {
   188  	return finishedHash{sm3.New(), sm3.New(), new(nilMD5Hash), new(nilMD5Hash), []byte{}, VersionGMSSL, prf12(sm3.New)}
   189  }
   190  
   191  func ecdheGMKA(version uint16) keyAgreement {
   192  	return &ecdheKeyAgreementGM{
   193  		version: version,
   194  	}
   195  }
   196  
   197  func eccGMKA(version uint16) keyAgreement {
   198  	return &eccKeyAgreementGM{
   199  		version: version,
   200  	}
   201  }
   202  
   203  // mutualCipherSuite returns a cipherSuite given a list of supported
   204  // ciphersuites and the id requested by the peer.
   205  func mutualCipherSuiteGM(have []uint16, want uint16) *cipherSuite {
   206  	for _, id := range have {
   207  		if id == want {
   208  			for _, suite := range gmCipherSuites {
   209  				if suite.id == want {
   210  					return suite
   211  				}
   212  			}
   213  			return nil
   214  		}
   215  	}
   216  	return nil
   217  }
   218  
   219  const (
   220  	ModeGMSSLOnly  = "GMSSLOnly"  // only support GMSSL
   221  	ModeAutoSwitch = "AutoSwitch" // support GMSSL/TLS auto switch
   222  )
   223  
   224  type GMSupport struct {
   225  	WorkMode      string // working mode
   226  	EncCertEnable bool   // enable encryption certificate
   227  }
   228  
   229  func NewGMSupport() *GMSupport {
   230  	return &GMSupport{WorkMode: ModeGMSSLOnly, EncCertEnable: true}
   231  }
   232  
   233  func (support *GMSupport) GetVersion() uint16 {
   234  	return VersionGMSSL
   235  }
   236  
   237  func (support *GMSupport) IsAvailable() bool {
   238  	return true
   239  }
   240  
   241  func (support *GMSupport) cipherSuites() []*cipherSuite {
   242  	return gmCipherSuites
   243  }
   244  
   245  // EnableMixMode 启用 GMSSL/TLS 自动切换的工作模式
   246  func (support *GMSupport) EnableMixMode() {
   247  	support.WorkMode = ModeAutoSwitch
   248  }
   249  
   250  // IsAutoSwitchMode 是否处于混合工作模式
   251  // return true - GMSSL/TLS 均支持, false - 不处于混合模式
   252  func (support *GMSupport) IsAutoSwitchMode() bool {
   253  	return support.WorkMode == ModeAutoSwitch
   254  }
   255  
   256  // LoadGMX509KeyPairs reads and parses two public/private key pairs from pairs
   257  // of files. The files must contain PEM encoded data. The certificate file
   258  // may contain intermediate certificates following the leaf certificate to
   259  // form a certificate chain. On successful return, Certificate.Leaf will
   260  // be nil because the parsed form of the certificate is not retained.
   261  func LoadGMX509KeyPairs(certFile, keyFile, encCertFile, encKeyFile string) (Certificate, error) {
   262  	certPEMBlock, err := ioutil.ReadFile(certFile)
   263  	if err != nil {
   264  		return Certificate{}, err
   265  	}
   266  	keyPEMBlock, err := ioutil.ReadFile(keyFile)
   267  	if err != nil {
   268  		return Certificate{}, err
   269  	}
   270  	encCertPEMBlock, err := ioutil.ReadFile(encCertFile)
   271  	if err != nil {
   272  		return Certificate{}, err
   273  	}
   274  	encKeyPEMBlock, err := ioutil.ReadFile(encKeyFile)
   275  	if err != nil {
   276  		return Certificate{}, err
   277  	}
   278  	return GMX509KeyPairs(certPEMBlock, keyPEMBlock, encCertPEMBlock, encKeyPEMBlock)
   279  }
   280  
   281  // add by syl add sigle key pair sitiation
   282  func LoadGMX509KeyPair(certFile, keyFile string) (Certificate, error) {
   283  	certPEMBlock, err := ioutil.ReadFile(certFile)
   284  	if err != nil {
   285  		return Certificate{}, err
   286  	}
   287  	keyPEMBlock, err := ioutil.ReadFile(keyFile)
   288  	if err != nil {
   289  		return Certificate{}, err
   290  	}
   291  	return GMX509KeyPairsSingle(certPEMBlock, keyPEMBlock)
   292  }
   293  
   294  func getCert(certPEMBlock []byte) ([][]byte, error) {
   295  	var certs [][]byte
   296  	var skippedBlockTypes []string
   297  	for {
   298  		var certDERBlock *pem.Block
   299  		certDERBlock, certPEMBlock = pem.Decode(certPEMBlock)
   300  		if certDERBlock == nil {
   301  			break
   302  		}
   303  		if certDERBlock.Type == "CERTIFICATE" {
   304  			certs = append(certs, certDERBlock.Bytes)
   305  		} else {
   306  			skippedBlockTypes = append(skippedBlockTypes, certDERBlock.Type)
   307  		}
   308  	}
   309  	if len(certs) == 0 {
   310  		if len(skippedBlockTypes) == 0 {
   311  			return nil, errors.New("tls: failed to find any PEM data in certificate input")
   312  		}
   313  		if len(skippedBlockTypes) == 1 && strings.HasSuffix(skippedBlockTypes[0], "PRIVATE KEY") {
   314  			return nil, errors.New("tls: failed to find certificate PEM data in certificate input, but did find a private key; PEM inputs may have been switched")
   315  		}
   316  		return nil, fmt.Errorf("tls: failed to find \"CERTIFICATE\" PEM block in certificate input after skipping PEM blocks of the following types: %v", skippedBlockTypes)
   317  	}
   318  	return certs, nil
   319  }
   320  
   321  func getKey(keyPEMBlock []byte) (*pem.Block, error) {
   322  	var skippedBlockTypes []string
   323  	var keyDERBlock *pem.Block
   324  	for {
   325  		keyDERBlock, keyPEMBlock = pem.Decode(keyPEMBlock)
   326  		if keyDERBlock == nil {
   327  			if len(skippedBlockTypes) == 0 {
   328  				return nil, errors.New("tls: failed to find any PEM data in key input")
   329  			}
   330  			if len(skippedBlockTypes) == 1 && skippedBlockTypes[0] == "CERTIFICATE" {
   331  				return nil, errors.New("tls: found a certificate rather than a key in the PEM for the private key")
   332  			}
   333  			return nil, fmt.Errorf("tls: failed to find PEM block with type ending in \"PRIVATE KEY\" in key input after skipping PEM blocks of the following types: %v", skippedBlockTypes)
   334  		}
   335  		if keyDERBlock.Type == "PRIVATE KEY" || strings.HasSuffix(keyDERBlock.Type, " PRIVATE KEY") {
   336  			break
   337  		}
   338  		skippedBlockTypes = append(skippedBlockTypes, keyDERBlock.Type)
   339  	}
   340  	return keyDERBlock, nil
   341  }
   342  
   343  func matchKeyCert(keyDERBlock *pem.Block, certDERBlock []byte) (crypto.PrivateKey, error) {
   344  	// We don't need to parse the public key for TLS, but we so do anyway
   345  	// to check that it looks sane and matches the private key.
   346  	x509Cert, err := x509.ParseCertificate(certDERBlock)
   347  	if err != nil {
   348  		return nil, err
   349  	}
   350  	privateKey, err := parsePrivateKey(keyDERBlock.Bytes)
   351  	if err != nil {
   352  		return nil, err
   353  	}
   354  	pubKey := x509Cert.PublicKey.ToStandardKey()
   355  	switch pub := pubKey.(type) {
   356  	case *sm2.PublicKey:
   357  		priv, ok := privateKey.(*sm2.PrivateKey)
   358  		if !ok {
   359  			return nil, errors.New("tls: private key type does not match public key type")
   360  		}
   361  		if pub.X.Cmp(priv.X) != 0 || pub.Y.Cmp(priv.Y) != 0 {
   362  			return nil, errors.New("tls: private key does not match public key")
   363  		}
   364  	default:
   365  		return nil, errors.New("tls: unknown public key algorithm")
   366  	}
   367  	return privateKey, nil
   368  }
   369  
   370  // X509KeyPair parses a public/private key pair from a pair of
   371  // PEM encoded data. On successful return, Certificate.Leaf will be nil because
   372  // the parsed form of the certificate is not retained.
   373  func GMX509KeyPairs(certPEMBlock, keyPEMBlock, encCertPEMBlock, encKeyPEMBlock []byte) (Certificate, error) {
   374  	fail := func(err error) (Certificate, error) { return Certificate{}, err }
   375  	var certificate Certificate
   376  	signCerts, err := getCert(certPEMBlock)
   377  	if err != nil {
   378  		return certificate, err
   379  	}
   380  	if len(signCerts) == 0 {
   381  		return certificate, errors.New("tls: failed to find any sign cert PEM data in cert input")
   382  	}
   383  	certificate.Certificate = append(certificate.Certificate, signCerts[0])
   384  	encCerts, err := getCert(encCertPEMBlock)
   385  	if err != nil {
   386  		return certificate, err
   387  	}
   388  	if len(encCerts) == 0 {
   389  		return certificate, errors.New("tls: failed to find any enc cert PEM data in cert input")
   390  	}
   391  	certificate.Certificate = append(certificate.Certificate, encCerts[0])
   392  	keyDERBlock, err := getKey(keyPEMBlock)
   393  	if err != nil {
   394  		return certificate, err
   395  	}
   396  	certificate.PrivateKey, err = matchKeyCert(keyDERBlock, certificate.Certificate[0])
   397  	if err != nil {
   398  		return fail(err)
   399  	}
   400  	return certificate, nil
   401  }
   402  
   403  //one cert for enc and sign
   404  func GMX509KeyPairsSingle(certPEMBlock, keyPEMBlock []byte) (Certificate, error) {
   405  	fail := func(err error) (Certificate, error) { return Certificate{}, err }
   406  	var certificate Certificate
   407  	certs, err := getCert(certPEMBlock)
   408  	if err != nil {
   409  		return certificate, err
   410  	}
   411  	if len(certs) == 0 {
   412  		return certificate, errors.New("tls: failed to find any sign cert PEM data in cert input")
   413  	}
   414  	checkCert, err := x509.ParseCertificate(certs[0])
   415  	if err != nil {
   416  		return certificate, errors.New("tls: failed to parse certificate")
   417  	}
   418  	//if cert is not for GM, use default X509KeyPair
   419  	if checkCert.PublicKeyAlgorithm != x509.SM2 {
   420  		return X509KeyPair(certPEMBlock, keyPEMBlock)
   421  	}
   422  	certificate.Certificate = append(certificate.Certificate, certs[0]) //this is for sign and env
   423  	keyDERBlock, err := getKey(keyPEMBlock)
   424  	if err != nil {
   425  		return certificate, err
   426  	}
   427  	certificate.PrivateKey, err = matchKeyCert(keyDERBlock, certificate.Certificate[0])
   428  	if err != nil {
   429  		return fail(err)
   430  	}
   431  	return certificate, nil
   432  }