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