...

Source file src/github.com/tjfoc/gmsm/gmtls/gm_support.go

Documentation: github.com/tjfoc/gmsm/gmtls

     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 gmtls
     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  	"github.com/tjfoc/gmsm/sm2"
    19  	"github.com/tjfoc/gmsm/sm3"
    20  	"github.com/tjfoc/gmsm/sm4"
    21  	"github.com/tjfoc/gmsm/x509"
    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  		name: "FABRIC",
    65  		pem: `-----BEGIN CERTIFICATE-----
    66  MIICMDCCAdagAwIBAgIRANnwbA2SIB/k0VNSkTi7TYUwCgYIKoEcz1UBg3UwaTEL
    67  MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG
    68  cmFuY2lzY28xFDASBgNVBAoTC2V4YW1wbGUuY29tMRcwFQYDVQQDEw5jYS5leGFt
    69  cGxlLmNvbTAeFw0xODEyMjcwNzE3MzBaFw0yODEyMjQwNzE3MzBaMGkxCzAJBgNV
    70  BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNp
    71  c2NvMRQwEgYDVQQKEwtleGFtcGxlLmNvbTEXMBUGA1UEAxMOY2EuZXhhbXBsZS5j
    72  b20wWTATBgcqhkjOPQIBBggqgRzPVQGCLQNCAARAp0oXL9xvWjkipnru0gsuL95g
    73  jpjscT5fQw0bHXPBSzYSq0+hoJf7C3t6tzjnI6pN0156KZg8Y1Bg7fx9xxOHo18w
    74  XTAOBgNVHQ8BAf8EBAMCAaYwDwYDVR0lBAgwBgYEVR0lADAPBgNVHRMBAf8EBTAD
    75  AQH/MCkGA1UdDgQiBCAt1zWEo9mUfmTAZlZthCkppNjgQlpQ9A77ylguCH4tRDAK
    76  BggqgRzPVQGDdQNIADBFAiBFx066bqQswz5eFA6IWZjj7GmdAyypq48IUaI8cs+b
    77  AwIhAPKX+rTHK3IHmZ3MHU2ajoJcGwq0h7aWpcpljF6cld4r
    78  -----END CERTIFICATE-----`,
    79  	},
    80  }
    81  
    82  var certCAs []*x509.Certificate
    83  
    84  var initonce sync.Once
    85  
    86  func getCAs() []*x509.Certificate {
    87  	// mod by syl remove pre insert ca certs
    88  	return nil
    89  	initonce.Do(func() {
    90  		for _, pemca := range pemCAs {
    91  			block, _ := pem.Decode([]byte(pemca.pem))
    92  			ca, err := x509.ParseCertificate(block.Bytes)
    93  			if err != nil {
    94  				panic(err)
    95  			}
    96  			certCAs = append(certCAs, ca)
    97  		}
    98  	})
    99  	return certCAs
   100  }
   101  
   102  // A list of cipher suite IDs that are, or have been, implemented by this
   103  // package.
   104  const (
   105  	//GM crypto suites ID  Taken from GM/T 0024-2014
   106  	GMTLS_ECDHE_SM2_WITH_SM1_SM3 uint16 = 0xe001
   107  	GMTLS_SM2_WITH_SM1_SM3       uint16 = 0xe003
   108  	GMTLS_IBSDH_WITH_SM1_SM3     uint16 = 0xe005
   109  	GMTLS_IBC_WITH_SM1_SM3       uint16 = 0xe007
   110  	GMTLS_RSA_WITH_SM1_SM3       uint16 = 0xe009
   111  	GMTLS_RSA_WITH_SM1_SHA1      uint16 = 0xe00a
   112  	GMTLS_ECDHE_SM2_WITH_SM4_SM3 uint16 = 0xe011
   113  	GMTLS_SM2_WITH_SM4_SM3       uint16 = 0xe013
   114  	GMTLS_IBSDH_WITH_SM4_SM3     uint16 = 0xe015
   115  	GMTLS_IBC_WITH_SM4_SM3       uint16 = 0xe017
   116  	GMTLS_RSA_WITH_SM4_SM3       uint16 = 0xe019
   117  	GMTLS_RSA_WITH_SM4_SHA1      uint16 = 0xe01a
   118  )
   119  
   120  var gmCipherSuites = []*cipherSuite{
   121  	{GMTLS_SM2_WITH_SM4_SM3, 16, 32, 16, eccGMKA, suiteECDSA, cipherSM4, macSM3, nil},
   122  	{GMTLS_ECDHE_SM2_WITH_SM4_SM3, 16, 32, 16, ecdheGMKA, suiteECDHE | suiteECDSA, cipherSM4, macSM3, nil},
   123  }
   124  
   125  func getCipherSuites(c *Config) []uint16 {
   126  	s := c.CipherSuites
   127  	if s == nil {
   128  		s = []uint16{GMTLS_SM2_WITH_SM4_SM3, GMTLS_ECDHE_SM2_WITH_SM4_SM3}
   129  	}
   130  	return s
   131  }
   132  
   133  func cipherSM4(key, iv []byte, isRead bool) interface{} {
   134  	block, _ := sm4.NewCipher(key)
   135  	if isRead {
   136  		return cipher.NewCBCDecrypter(block, iv)
   137  	}
   138  	return cipher.NewCBCEncrypter(block, iv)
   139  }
   140  
   141  // macSHA1 returns a macFunction for the given protocol version.
   142  func macSM3(version uint16, key []byte) macFunction {
   143  	return tls10MAC{hmac.New(sm3.New, key)}
   144  }
   145  
   146  //used for adapt the demand of finishHash write
   147  type nilMD5Hash struct{}
   148  
   149  func (nilMD5Hash) Write(p []byte) (n int, err error) {
   150  	return 0, nil
   151  }
   152  
   153  func (nilMD5Hash) Sum(b []byte) []byte {
   154  	return nil
   155  }
   156  
   157  func (nilMD5Hash) Reset() {
   158  }
   159  
   160  func (nilMD5Hash) Size() int {
   161  	return 0
   162  }
   163  
   164  func (nilMD5Hash) BlockSize() int {
   165  	return 0
   166  }
   167  
   168  func newFinishedHashGM(cipherSuite *cipherSuite) finishedHash {
   169  	return finishedHash{sm3.New(), sm3.New(), new(nilMD5Hash), new(nilMD5Hash), []byte{}, VersionGMSSL, prf12(sm3.New)}
   170  
   171  }
   172  
   173  func ecdheGMKA(version uint16) keyAgreement {
   174  	return &ecdheKeyAgreementGM{
   175  		version: version,
   176  	}
   177  }
   178  
   179  func eccGMKA(version uint16) keyAgreement {
   180  	return &eccKeyAgreementGM{
   181  		version: version,
   182  	}
   183  }
   184  
   185  // mutualCipherSuite returns a cipherSuite given a list of supported
   186  // ciphersuites and the id requested by the peer.
   187  func mutualCipherSuiteGM(have []uint16, want uint16) *cipherSuite {
   188  	for _, id := range have {
   189  		if id == want {
   190  			for _, suite := range gmCipherSuites {
   191  				if suite.id == want {
   192  					return suite
   193  				}
   194  			}
   195  			return nil
   196  		}
   197  	}
   198  	return nil
   199  }
   200  
   201  const (
   202  	ModeGMSSLOnly  = "GMSSLOnly"  // 仅支持 国密SSL模式
   203  	ModeAutoSwitch = "AutoSwitch" // GMSSL/TLS 自动切换模式
   204  )
   205  
   206  type GMSupport struct {
   207  	WorkMode string // 工作模式
   208  }
   209  
   210  func NewGMSupport() *GMSupport {
   211  	return &GMSupport{WorkMode: ModeGMSSLOnly}
   212  }
   213  
   214  func (support *GMSupport) GetVersion() uint16 {
   215  	return VersionGMSSL
   216  }
   217  
   218  func (support *GMSupport) IsAvailable() bool {
   219  	return true
   220  }
   221  
   222  func (support *GMSupport) cipherSuites() []*cipherSuite {
   223  	return gmCipherSuites
   224  }
   225  
   226  // EnableMixMode 启用 GMSSL/TLS 自动切换的工作模式
   227  func (support *GMSupport) EnableMixMode() {
   228  	support.WorkMode = ModeAutoSwitch
   229  }
   230  
   231  // IsAutoSwitchMode 是否处于混合工作模式
   232  // return true - GMSSL/TLS 均支持, false - 不处于混合模式
   233  func (support *GMSupport) IsAutoSwitchMode() bool {
   234  	return support.WorkMode == ModeAutoSwitch
   235  }
   236  
   237  // LoadGMX509KeyPairs reads and parses two public/private key pairs from pairs
   238  // of files. The files must contain PEM encoded data. The certificate file
   239  // may contain intermediate certificates following the leaf certificate to
   240  // form a certificate chain. On successful return, Certificate.Leaf will
   241  // be nil because the parsed form of the certificate is not retained.
   242  func LoadGMX509KeyPairs(certFile, keyFile, encCertFile, encKeyFile string) (Certificate, error) {
   243  	certPEMBlock, err := ioutil.ReadFile(certFile)
   244  	if err != nil {
   245  		return Certificate{}, err
   246  	}
   247  	keyPEMBlock, err := ioutil.ReadFile(keyFile)
   248  	if err != nil {
   249  		return Certificate{}, err
   250  	}
   251  	encCertPEMBlock, err := ioutil.ReadFile(encCertFile)
   252  	if err != nil {
   253  		return Certificate{}, err
   254  	}
   255  	encKeyPEMBlock, err := ioutil.ReadFile(encKeyFile)
   256  	if err != nil {
   257  		return Certificate{}, err
   258  	}
   259  
   260  	return GMX509KeyPairs(certPEMBlock, keyPEMBlock, encCertPEMBlock, encKeyPEMBlock)
   261  }
   262  
   263  // add by syl add sigle key pair sitiation
   264  func LoadGMX509KeyPair(certFile, keyFile string) (Certificate, error) {
   265  	certPEMBlock, err := ioutil.ReadFile(certFile)
   266  	if err != nil {
   267  		return Certificate{}, err
   268  	}
   269  	keyPEMBlock, err := ioutil.ReadFile(keyFile)
   270  	if err != nil {
   271  		return Certificate{}, err
   272  	}
   273  
   274  	return GMX509KeyPairsSingle(certPEMBlock, keyPEMBlock)
   275  }
   276  
   277  ////load sign/enc certs and sign/enc privatekey from one single file respectively
   278  //func LoadGMX509KeyPairs2(certFile, keyFile string) (Certificate, error) {
   279  //	certPEMBlock, err := ioutil.ReadFile(certFile)
   280  //	if err != nil {
   281  //		return Certificate{}, err
   282  //	}
   283  //	keyPEMBlock, err := ioutil.ReadFile(keyFile)
   284  //	if err != nil {
   285  //		return Certificate{}, err
   286  //	}
   287  //	encCertPEMBlock, err := ioutil.ReadFile(encCertFile)
   288  //	if err != nil {
   289  //		return Certificate{}, err
   290  //	}
   291  //	encKeyPEMBlock, err := ioutil.ReadFile(encKeyFile)
   292  //	if err != nil {
   293  //		return Certificate{}, err
   294  //	}
   295  //
   296  //	return GMX509KeyPairs(certPEMBlock, keyPEMBlock, encCertPEMBlock, encKeyPEMBlock)
   297  //}
   298  
   299  func getCert(certPEMBlock []byte) ([][]byte, error) {
   300  
   301  	var certs [][]byte
   302  	var skippedBlockTypes []string
   303  	for {
   304  		var certDERBlock *pem.Block
   305  		certDERBlock, certPEMBlock = pem.Decode(certPEMBlock)
   306  		if certDERBlock == nil {
   307  			break
   308  		}
   309  		if certDERBlock.Type == "CERTIFICATE" {
   310  			certs = append(certs, certDERBlock.Bytes)
   311  		} else {
   312  			skippedBlockTypes = append(skippedBlockTypes, certDERBlock.Type)
   313  		}
   314  	}
   315  
   316  	if len(certs) == 0 {
   317  		if len(skippedBlockTypes) == 0 {
   318  			return nil, errors.New("tls: failed to find any PEM data in certificate input")
   319  		}
   320  		if len(skippedBlockTypes) == 1 && strings.HasSuffix(skippedBlockTypes[0], "PRIVATE KEY") {
   321  			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")
   322  		}
   323  		return nil, fmt.Errorf("tls: failed to find \"CERTIFICATE\" PEM block in certificate input after skipping PEM blocks of the following types: %v", skippedBlockTypes)
   324  	}
   325  	return certs, nil
   326  }
   327  
   328  func getKey(keyPEMBlock []byte) (*pem.Block, error) {
   329  	var skippedBlockTypes []string
   330  	var keyDERBlock *pem.Block
   331  	for {
   332  		keyDERBlock, keyPEMBlock = pem.Decode(keyPEMBlock)
   333  		if keyDERBlock == nil {
   334  			if len(skippedBlockTypes) == 0 {
   335  				return nil, errors.New("tls: failed to find any PEM data in key input")
   336  			}
   337  			if len(skippedBlockTypes) == 1 && skippedBlockTypes[0] == "CERTIFICATE" {
   338  				return nil, errors.New("tls: found a certificate rather than a key in the PEM for the private key")
   339  			}
   340  			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)
   341  		}
   342  		if keyDERBlock.Type == "PRIVATE KEY" || strings.HasSuffix(keyDERBlock.Type, " PRIVATE KEY") {
   343  			break
   344  		}
   345  		skippedBlockTypes = append(skippedBlockTypes, keyDERBlock.Type)
   346  	}
   347  	return keyDERBlock, nil
   348  }
   349  
   350  func matchKeyCert(keyDERBlock *pem.Block, certDERBlock []byte) (crypto.PrivateKey, error) {
   351  	// We don't need to parse the public key for TLS, but we so do anyway
   352  	// to check that it looks sane and matches the private key.
   353  	x509Cert, err := x509.ParseCertificate(certDERBlock)
   354  	if err != nil {
   355  		return nil, err
   356  	}
   357  
   358  	privateKey, err := parsePrivateKey(keyDERBlock.Bytes)
   359  	if err != nil {
   360  		return nil, err
   361  	}
   362  
   363  	switch pub := x509Cert.PublicKey.(type) {
   364  	case *sm2.PublicKey:
   365  		priv, ok := privateKey.(*sm2.PrivateKey)
   366  		if !ok {
   367  			return nil, errors.New("tls: private key type does not match public key type")
   368  		}
   369  		if pub.X.Cmp(priv.X) != 0 || pub.Y.Cmp(priv.Y) != 0 {
   370  			return nil, errors.New("tls: private key does not match public key")
   371  		}
   372  	default:
   373  		return nil, errors.New("tls: unknown public key algorithm")
   374  	}
   375  	return privateKey, nil
   376  }
   377  
   378  // X509KeyPair parses a public/private key pair from a pair of
   379  // PEM encoded data. On successful return, Certificate.Leaf will be nil because
   380  // the parsed form of the certificate is not retained.
   381  func GMX509KeyPairs(certPEMBlock, keyPEMBlock, encCertPEMBlock, encKeyPEMBlock []byte) (Certificate, error) {
   382  	fail := func(err error) (Certificate, error) { return Certificate{}, err }
   383  
   384  	var certificate Certificate
   385  
   386  	signCerts, err := getCert(certPEMBlock)
   387  	if err != nil {
   388  		return certificate, err
   389  	}
   390  	if len(signCerts) == 0 {
   391  		return certificate, errors.New("tls: failed to find any sign cert PEM data in cert input")
   392  	}
   393  	certificate.Certificate = append(certificate.Certificate, signCerts[0])
   394  
   395  	encCerts, err := getCert(encCertPEMBlock)
   396  	if err != nil {
   397  		return certificate, err
   398  	}
   399  	if len(encCerts) == 0 {
   400  		return certificate, errors.New("tls: failed to find any enc cert PEM data in cert input")
   401  	}
   402  	certificate.Certificate = append(certificate.Certificate, encCerts[0])
   403  
   404  	keyDERBlock, err := getKey(keyPEMBlock)
   405  	if err != nil {
   406  		return certificate, err
   407  	}
   408  
   409  	certificate.PrivateKey, err = matchKeyCert(keyDERBlock, certificate.Certificate[0])
   410  	if err != nil {
   411  		return fail(err)
   412  	}
   413  
   414  	return certificate, nil
   415  }
   416  
   417  //one cert for enc and sign
   418  func GMX509KeyPairsSingle(certPEMBlock, keyPEMBlock []byte) (Certificate, error) {
   419  	fail := func(err error) (Certificate, error) { return Certificate{}, err }
   420  
   421  	var certificate Certificate
   422  
   423  	certs, err := getCert(certPEMBlock)
   424  	if err != nil {
   425  		return certificate, err
   426  	}
   427  	if len(certs) == 0 {
   428  		return certificate, errors.New("tls: failed to find any sign cert PEM data in cert input")
   429  	}
   430  	checkCert, err := x509.ParseCertificate(certs[0])
   431  	if err != nil {
   432  		return certificate, errors.New("tls: failed to parse certificate")
   433  	}
   434  
   435  	//if cert is not for GM, use default X509KeyPair
   436  	if checkCert.PublicKeyAlgorithm != x509.SM2 {
   437  		return X509KeyPair(certPEMBlock, keyPEMBlock)
   438  	}
   439  
   440  	certificate.Certificate = append(certificate.Certificate, certs[0]) //this is for sign and env
   441  
   442  	keyDERBlock, err := getKey(keyPEMBlock)
   443  	if err != nil {
   444  		return certificate, err
   445  	}
   446  
   447  	certificate.PrivateKey, err = matchKeyCert(keyDERBlock, certificate.Certificate[0])
   448  	if err != nil {
   449  		return fail(err)
   450  	}
   451  
   452  	return certificate, nil
   453  }
   454  

View as plain text