├── README.md ├── gmcredentials ├── testdata │ ├── ecadminkey.pem │ ├── eccakey.pem │ ├── adminkey.pem │ ├── cakey.pem │ ├── ecadmin.pem │ ├── ecca.pem │ ├── ca.pem │ └── admin.pem ├── echo │ ├── echo.proto │ └── echo.pb.go ├── credentials_util_go18.go ├── credentials_test.go └── credentials.go ├── .travis.yml ├── alert.go ├── ticket.go ├── tls.go ├── LICENSE ├── prf.go ├── cipher_suites.go ├── key_agreement.go ├── handshake_client.go ├── handshake_server.go └── common.go /README.md: -------------------------------------------------------------------------------- 1 | 2 | ## GM TLS/SSL Based on Golang 3 | 4 | -------------------------------------------------------------------------------- /gmcredentials/testdata/ecadminkey.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgzMfzhfg65/0lyTG9 3 | 36PtTfHCTnmjP8PbOniXqu5Zq0uhRANCAARQZBis9FcQ2cDYM0BFrsWuTvIiK21i 4 | 2yO1c8s8tf6OwDn9bh/+gOebEXri1IUQuEL7uSbFnhwjcth7uNjCxN4c 5 | -----END PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /gmcredentials/testdata/eccakey.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg/eKOgfZvjde1eQ35 3 | oY6lGqbKoCRRLhCvq6oHZ87xXJuhRANCAASEd7IPpAvcuFbpuedZ5TAKIa3DwmWK 4 | Lh4Tl021gcNHoeHol1MT8ajQSKfz2amDrtnlXExpeRgx9jYTkqpxJ5Y5 5 | -----END PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /gmcredentials/echo/echo.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package echo; 4 | 5 | service Echo{ 6 | rpc Echo(EchoRequest) returns (EchoResponse){} 7 | } 8 | 9 | message EchoRequest{ 10 | string req = 1; 11 | } 12 | 13 | message EchoResponse{ 14 | string result = 1; 15 | } 16 | -------------------------------------------------------------------------------- /gmcredentials/testdata/adminkey.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQg510FuLDR3BTiXfh8 3 | bLs5ZMmzBN3d8xiQsp3Lp1G31qmgCgYIKoEcz1UBgi2hRANCAARkTEon4ejdjTLt 4 | 2c5kJq9rQ6sTmNBI2thnkxtYpIbWOVVXqUiL7TKrnMBMbFUACR1CLhl1gKm5ypuS 5 | /7dH4ywQ 6 | -----END PRIVATE KEY----- 7 | -------------------------------------------------------------------------------- /gmcredentials/testdata/cakey.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQg9Mrzr+8jnnvi2e3n 3 | WspzqEtPIoQe4TjVxQ1gS0xmDf+gCgYIKoEcz1UBgi2hRANCAASNkrYP1Ll1pQKo 4 | L1xOQnDyShVGxWlATDfYjiYxsI6f1HozJuMbQ0x2Ow3Lk5rgoPNMNIFZU61N6ceR 5 | 40IxWwMn 6 | -----END PRIVATE KEY----- 7 | -------------------------------------------------------------------------------- /gmcredentials/testdata/ecadmin.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICCTCCAbCgAwIBAgIQdfEbS2OOoMpa7bnPzBXbDDAKBggqhkjOPQQDAjBpMQsw 3 | CQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy 4 | YW5jaXNjbzEUMBIGA1UEChMLZXhhbXBsZS5jb20xFzAVBgNVBAMTDmNhLmV4YW1w 5 | bGUuY29tMB4XDTE3MDkyODA4MzAyMVoXDTI3MDkyNjA4MzAyMVowVjELMAkGA1UE 6 | BhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lz 7 | Y28xGjAYBgNVBAMMEUFkbWluQGV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZI 8 | zj0DAQcDQgAEUGQYrPRXENnA2DNARa7Frk7yIittYtsjtXPLPLX+jsA5/W4f/oDn 9 | mxF64tSFELhC+7kmxZ4cI3LYe7jYwsTeHKNNMEswDgYDVR0PAQH/BAQDAgeAMAwG 10 | A1UdEwEB/wQCMAAwKwYDVR0jBCQwIoAg9shsC5OiEbT12s4N3l5X91Q0PjGSpiIx 11 | Br0njdIX3NYwCgYIKoZIzj0EAwIDRwAwRAIgdW8oSXW8klV2679IW4RcFlDMYClo 12 | ehi0oXL3Mk/zaGQCIAOyE47yAUAdDlz7UQnKFwZjlZbcHsh/aJMJohow8tKd 13 | -----END CERTIFICATE----- 14 | -------------------------------------------------------------------------------- /gmcredentials/testdata/ecca.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICLzCCAdWgAwIBAgIQPqIwNwdDh+RjU18T9R+ioDAKBggqhkjOPQQDAjBpMQsw 3 | CQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy 4 | YW5jaXNjbzEUMBIGA1UEChMLZXhhbXBsZS5jb20xFzAVBgNVBAMTDmNhLmV4YW1w 5 | bGUuY29tMB4XDTE3MDkyODA4MzAyMVoXDTI3MDkyNjA4MzAyMVowaTELMAkGA1UE 6 | BhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lz 7 | Y28xFDASBgNVBAoTC2V4YW1wbGUuY29tMRcwFQYDVQQDEw5jYS5leGFtcGxlLmNv 8 | bTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABIR3sg+kC9y4Vum551nlMAohrcPC 9 | ZYouHhOXTbWBw0eh4eiXUxPxqNBIp/PZqYOu2eVcTGl5GDH2NhOSqnEnljmjXzBd 10 | MA4GA1UdDwEB/wQEAwIBpjAPBgNVHSUECDAGBgRVHSUAMA8GA1UdEwEB/wQFMAMB 11 | Af8wKQYDVR0OBCIEIPbIbAuTohG09drODd5eV/dUND4xkqYiMQa9J43SF9zWMAoG 12 | CCqGSM49BAMCA0gAMEUCIQDAPxbvlUwygYP/VpgV9I71UlOvlFdKqqH8hNoAGbum 13 | FgIgXwZRaMK1hX5YAIa/W4DJ+pkFpjBaX+T8DkL/Yr+tC18= 14 | -----END CERTIFICATE----- 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: 3 | - go 4 | go: 5 | - 1.8.3 6 | 7 | 8 | install: 9 | - go get -v github.com/golang/lint/golint 10 | - go get -v github.com/tjfoc/gmsm/sm2 11 | - go get -v golang.org/x/crypto/chacha20poly1305 12 | - go get -v golang.org/x/net/context 13 | - go get -v google.golang.org/grpc/credentials 14 | - go get -v github.com/golang/protobuf/proto 15 | - go get -v golang.org/x/text/secure/bidirule 16 | - go get -v google.golang.org/genproto/googleapis/rpc/status 17 | - pwd 18 | - go build 19 | - go build -v ./gmcredentials 20 | - go build -v ./gmcredentials/echo 21 | 22 | 23 | script: 24 | - go vet ./gmcredentials 25 | - go test ./gmcredentials 26 | 27 | after_failure: 28 | 29 | - | 30 | echo "Error!" 31 | notifications: 32 | email: 33 | recipients: 34 | - zhiqiang@tj-fintech.com 35 | - yanwenze@tj-fintech.com 36 | - maoxiuze@tj-fintech.com 37 | - yewei@tj-fintech.com 38 | 39 | on_success: never # default: change 40 | on_failure: always # default: always 41 | -------------------------------------------------------------------------------- /gmcredentials/credentials_util_go18.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | 16 | package gmcredentials 17 | 18 | import "github.com/tjfoc/gmtls" 19 | 20 | // cloneTLSConfig returns a shallow clone of the exported 21 | // fields of cfg, ignoring the unexported sync.Once, which 22 | // contains a mutex and must not be copied. 23 | // 24 | // If cfg is nil, a new zero tls.Config is returned. 25 | func cloneTLSConfig(cfg *gmtls.Config) *gmtls.Config { 26 | if cfg == nil { 27 | return &gmtls.Config{} 28 | } 29 | 30 | return cfg.Clone() 31 | } 32 | -------------------------------------------------------------------------------- /gmcredentials/testdata/ca.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDCDCCAq6gAwIBAgIB/zAKBggqgRzPVQGDdTBIMQ0wCwYDVQQKEwRURVNUMRkw 3 | FwYDVQQDExB0ZXN0LmV4YW1wbGUuY29tMQ8wDQYDVQQqEwZHb3BoZXIxCzAJBgNV 4 | BAYTAk5MMB4XDTE3MTAxMzA3MzM1NFoXDTE4MTAxMzA3MzM1NFowSDENMAsGA1UE 5 | ChMEVEVTVDEZMBcGA1UEAxMQdGVzdC5leGFtcGxlLmNvbTEPMA0GA1UEKhMGR29w 6 | aGVyMQswCQYDVQQGEwJOTDBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABI2Stg/U 7 | uXWlAqgvXE5CcPJKFUbFaUBMN9iOJjGwjp/UejMm4xtDTHY7DcuTmuCg80w0gVlT 8 | rU3px5HjQjFbAyejggGHMIIBgzAOBgNVHQ8BAf8EBAMCAgQwJgYDVR0lBB8wHQYI 9 | KwYBBQUHAwIGCCsGAQUFBwMBBgIqAwYDgQsBMA8GA1UdEwEB/wQFMAMBAf8wXwYI 10 | KwYBBQUHAQEEUzBRMCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5leGFtcGxlLmNv 11 | bTAqBggrBgEFBQcwAoYeaHR0cDovL2NydC5leGFtcGxlLmNvbS9jYTEuY3J0MEYG 12 | A1UdEQQ/MD2CEHRlc3QuZXhhbXBsZS5jb22BEWdvcGhlckBnb2xhbmcub3JnhwR/ 13 | AAABhxAgAUhgAAAgAQAAAAAAAABoMA8GA1UdIAQIMAYwBAYCKgMwVwYDVR0fBFAw 14 | TjAloCOgIYYfaHR0cDovL2NybDEuZXhhbXBsZS5jb20vY2ExLmNybDAloCOgIYYf 15 | aHR0cDovL2NybDIuZXhhbXBsZS5jb20vY2ExLmNybDAWBgMqAwQED2V4dHJhIGV4 16 | dGVuc2lvbjANBgNVHQ4EBgQEBAMCATAKBggqgRzPVQGDdQNIADBFAiEAi8alhmBr 17 | blbGkPQKqayWZ/Qw23Vs8XQr0Ds0hZpgXkgCIDWkb3Cax1uDM9/7KewnBwNzxSah 18 | Ajx4KZlq2KAhPUr5 19 | -----END CERTIFICATE----- 20 | -------------------------------------------------------------------------------- /gmcredentials/testdata/admin.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDBzCCAq6gAwIBAgIB/zAKBggqgRzPVQGDdTBIMQ0wCwYDVQQKEwRURVNUMRkw 3 | FwYDVQQDExB0ZXN0LmV4YW1wbGUuY29tMQ8wDQYDVQQqEwZHb3BoZXIxCzAJBgNV 4 | BAYTAk5MMB4XDTE3MTAxMzA3MzM1NFoXDTE4MTAxMzA3MzM1NFowSDENMAsGA1UE 5 | ChMEVEVTVDEZMBcGA1UEAxMQdGVzdC5leGFtcGxlLmNvbTEPMA0GA1UEKhMGR29w 6 | aGVyMQswCQYDVQQGEwJOTDBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABGRMSifh 7 | 6N2NMu3ZzmQmr2tDqxOY0Eja2GeTG1ikhtY5VVepSIvtMqucwExsVQAJHUIuGXWA 8 | qbnKm5L/t0fjLBCjggGHMIIBgzAOBgNVHQ8BAf8EBAMCAgQwJgYDVR0lBB8wHQYI 9 | KwYBBQUHAwIGCCsGAQUFBwMBBgIqAwYDgQsBMA8GA1UdEwEB/wQFMAMBAf8wXwYI 10 | KwYBBQUHAQEEUzBRMCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5leGFtcGxlLmNv 11 | bTAqBggrBgEFBQcwAoYeaHR0cDovL2NydC5leGFtcGxlLmNvbS9jYTEuY3J0MEYG 12 | A1UdEQQ/MD2CEHRlc3QuZXhhbXBsZS5jb22BEWdvcGhlckBnb2xhbmcub3JnhwR/ 13 | AAABhxAgAUhgAAAgAQAAAAAAAABoMA8GA1UdIAQIMAYwBAYCKgMwVwYDVR0fBFAw 14 | TjAloCOgIYYfaHR0cDovL2NybDEuZXhhbXBsZS5jb20vY2ExLmNybDAloCOgIYYf 15 | aHR0cDovL2NybDIuZXhhbXBsZS5jb20vY2ExLmNybDAWBgMqAwQED2V4dHJhIGV4 16 | dGVuc2lvbjANBgNVHQ4EBgQEBAMCATAKBggqgRzPVQGDdQNHADBEAiAudzJoMUtv 17 | 7gP7fOa+7Ny7o+AgllpECYrluYPBZPKP4AIgW5b7ml8y9qYGp0x4q3w4OQwbAe5f 18 | w81HhjB58+eZyZA= 19 | -----END CERTIFICATE----- 20 | -------------------------------------------------------------------------------- /gmcredentials/credentials_test.go: -------------------------------------------------------------------------------- 1 | /* credentials test */ 2 | package gmcredentials 3 | 4 | import ( 5 | "fmt" 6 | "io/ioutil" 7 | "log" 8 | "net" 9 | "testing" 10 | 11 | "github.com/tjfoc/gmsm/sm2" 12 | "github.com/tjfoc/gmtls" 13 | "github.com/tjfoc/gmtls/gmcredentials/echo" 14 | "golang.org/x/net/context" 15 | "google.golang.org/grpc" 16 | ) 17 | 18 | const ( 19 | port = ":50051" 20 | address = "localhost:50051" 21 | ) 22 | 23 | var end chan bool 24 | 25 | type server struct{} 26 | 27 | func (s *server) Echo(ctx context.Context, req *echo.EchoRequest) (*echo.EchoResponse, error) { 28 | return &echo.EchoResponse{Result: req.Req}, nil 29 | } 30 | 31 | const ca = "testdata/ca.pem" 32 | const cakey = "testdata/cakey.pem" 33 | 34 | const admin = "testdata/admin.pem" 35 | const adminkey = "testdata/adminkey.pem" 36 | 37 | func serverRun() { 38 | cert, err := gmtls.LoadX509KeyPair(ca, cakey) 39 | if err != nil { 40 | log.Fatal(err) 41 | } 42 | certPool := sm2.NewCertPool() 43 | cacert, err := ioutil.ReadFile(ca) 44 | if err != nil { 45 | log.Fatal(err) 46 | } 47 | certPool.AppendCertsFromPEM(cacert) 48 | 49 | lis, err := net.Listen("tcp", port) 50 | if err != nil { 51 | log.Fatalf("fail to listen: %v", err) 52 | } 53 | creds := NewTLS(&gmtls.Config{ 54 | ClientAuth: gmtls.RequireAndVerifyClientCert, 55 | Certificates: []gmtls.Certificate{cert}, 56 | ClientCAs: certPool, 57 | }) 58 | s := grpc.NewServer(grpc.Creds(creds)) 59 | echo.RegisterEchoServer(s, &server{}) 60 | err = s.Serve(lis) 61 | if err != nil { 62 | log.Fatalf("Serve: %v", err) 63 | } 64 | } 65 | 66 | func clientRun() { 67 | cert, err := gmtls.LoadX509KeyPair(admin, adminkey) 68 | if err != nil { 69 | log.Fatal(err) 70 | } 71 | certPool := sm2.NewCertPool() 72 | cacert, err := ioutil.ReadFile(ca) 73 | if err != nil { 74 | log.Fatal(err) 75 | } 76 | certPool.AppendCertsFromPEM(cacert) 77 | creds := NewTLS(&gmtls.Config{ 78 | ServerName: "test.example.com", 79 | Certificates: []gmtls.Certificate{cert}, 80 | RootCAs: certPool, 81 | }) 82 | conn, err := grpc.Dial(address, grpc.WithTransportCredentials(creds)) 83 | if err != nil { 84 | log.Fatalf("cannot to connect: %v", err) 85 | } 86 | defer conn.Close() 87 | c := echo.NewEchoClient(conn) 88 | echoTest(c) 89 | end <- true 90 | } 91 | 92 | func echoTest(c echo.EchoClient) { 93 | r, err := c.Echo(context.Background(), &echo.EchoRequest{Req: "hello"}) 94 | if err != nil { 95 | log.Fatalf("failed to echo: %v", err) 96 | } 97 | fmt.Printf("%s\n", r.Result) 98 | } 99 | 100 | func Test(t *testing.T) { 101 | end = make(chan bool, 64) 102 | go serverRun() 103 | go clientRun() 104 | <-end 105 | } 106 | -------------------------------------------------------------------------------- /alert.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | 16 | package gmtls 17 | 18 | import "strconv" 19 | 20 | type alert uint8 21 | 22 | const ( 23 | // alert level 24 | alertLevelWarning = 1 25 | alertLevelError = 2 26 | ) 27 | 28 | const ( 29 | alertCloseNotify alert = 0 30 | alertUnexpectedMessage alert = 10 31 | alertBadRecordMAC alert = 20 32 | alertDecryptionFailed alert = 21 33 | alertRecordOverflow alert = 22 34 | alertDecompressionFailure alert = 30 35 | alertHandshakeFailure alert = 40 36 | alertBadCertificate alert = 42 37 | alertUnsupportedCertificate alert = 43 38 | alertCertificateRevoked alert = 44 39 | alertCertificateExpired alert = 45 40 | alertCertificateUnknown alert = 46 41 | alertIllegalParameter alert = 47 42 | alertUnknownCA alert = 48 43 | alertAccessDenied alert = 49 44 | alertDecodeError alert = 50 45 | alertDecryptError alert = 51 46 | alertProtocolVersion alert = 70 47 | alertInsufficientSecurity alert = 71 48 | alertInternalError alert = 80 49 | alertInappropriateFallback alert = 86 50 | alertUserCanceled alert = 90 51 | alertNoRenegotiation alert = 100 52 | alertNoApplicationProtocol alert = 120 53 | ) 54 | 55 | var alertText = map[alert]string{ 56 | alertCloseNotify: "close notify", 57 | alertUnexpectedMessage: "unexpected message", 58 | alertBadRecordMAC: "bad record MAC", 59 | alertDecryptionFailed: "decryption failed", 60 | alertRecordOverflow: "record overflow", 61 | alertDecompressionFailure: "decompression failure", 62 | alertHandshakeFailure: "handshake failure", 63 | alertBadCertificate: "bad certificate", 64 | alertUnsupportedCertificate: "unsupported certificate", 65 | alertCertificateRevoked: "revoked certificate", 66 | alertCertificateExpired: "expired certificate", 67 | alertCertificateUnknown: "unknown certificate", 68 | alertIllegalParameter: "illegal parameter", 69 | alertUnknownCA: "unknown certificate authority", 70 | alertAccessDenied: "access denied", 71 | alertDecodeError: "error decoding message", 72 | alertDecryptError: "error decrypting message", 73 | alertProtocolVersion: "protocol version not supported", 74 | alertInsufficientSecurity: "insufficient security level", 75 | alertInternalError: "internal error", 76 | alertInappropriateFallback: "inappropriate fallback", 77 | alertUserCanceled: "user canceled", 78 | alertNoRenegotiation: "no renegotiation", 79 | alertNoApplicationProtocol: "no application protocol", 80 | } 81 | 82 | func (e alert) String() string { 83 | s, ok := alertText[e] 84 | if ok { 85 | return "tls: " + s 86 | } 87 | return "tls: alert(" + strconv.Itoa(int(e)) + ")" 88 | } 89 | 90 | func (e alert) Error() string { 91 | return e.String() 92 | } 93 | -------------------------------------------------------------------------------- /gmcredentials/echo/echo.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // source: echo.proto 3 | 4 | /* 5 | Package echo is a generated protocol buffer package. 6 | 7 | It is generated from these files: 8 | echo.proto 9 | 10 | It has these top-level messages: 11 | EchoRequest 12 | EchoResponse 13 | */ 14 | package echo 15 | 16 | import proto "github.com/golang/protobuf/proto" 17 | import fmt "fmt" 18 | import math "math" 19 | 20 | import ( 21 | context "golang.org/x/net/context" 22 | grpc "google.golang.org/grpc" 23 | ) 24 | 25 | // Reference imports to suppress errors if they are not otherwise used. 26 | var _ = proto.Marshal 27 | var _ = fmt.Errorf 28 | var _ = math.Inf 29 | 30 | // This is a compile-time assertion to ensure that this generated file 31 | // is compatible with the proto package it is being compiled against. 32 | // A compilation error at this line likely means your copy of the 33 | // proto package needs to be updated. 34 | const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package 35 | 36 | type EchoRequest struct { 37 | Req string `protobuf:"bytes,1,opt,name=req" json:"req,omitempty"` 38 | } 39 | 40 | func (m *EchoRequest) Reset() { *m = EchoRequest{} } 41 | func (m *EchoRequest) String() string { return proto.CompactTextString(m) } 42 | func (*EchoRequest) ProtoMessage() {} 43 | func (*EchoRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } 44 | 45 | func (m *EchoRequest) GetReq() string { 46 | if m != nil { 47 | return m.Req 48 | } 49 | return "" 50 | } 51 | 52 | type EchoResponse struct { 53 | Result string `protobuf:"bytes,1,opt,name=result" json:"result,omitempty"` 54 | } 55 | 56 | func (m *EchoResponse) Reset() { *m = EchoResponse{} } 57 | func (m *EchoResponse) String() string { return proto.CompactTextString(m) } 58 | func (*EchoResponse) ProtoMessage() {} 59 | func (*EchoResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } 60 | 61 | func (m *EchoResponse) GetResult() string { 62 | if m != nil { 63 | return m.Result 64 | } 65 | return "" 66 | } 67 | 68 | func init() { 69 | proto.RegisterType((*EchoRequest)(nil), "echo.EchoRequest") 70 | proto.RegisterType((*EchoResponse)(nil), "echo.EchoResponse") 71 | } 72 | 73 | // Reference imports to suppress errors if they are not otherwise used. 74 | var _ context.Context 75 | var _ grpc.ClientConn 76 | 77 | // This is a compile-time assertion to ensure that this generated file 78 | // is compatible with the grpc package it is being compiled against. 79 | const _ = grpc.SupportPackageIsVersion4 80 | 81 | // Client API for Echo service 82 | 83 | type EchoClient interface { 84 | Echo(ctx context.Context, in *EchoRequest, opts ...grpc.CallOption) (*EchoResponse, error) 85 | } 86 | 87 | type echoClient struct { 88 | cc *grpc.ClientConn 89 | } 90 | 91 | func NewEchoClient(cc *grpc.ClientConn) EchoClient { 92 | return &echoClient{cc} 93 | } 94 | 95 | type echoClient_NEW struct { 96 | cc *grpc.ClientConn 97 | } 98 | 99 | func (c *echoClient) Echo(ctx context.Context, in *EchoRequest, opts ...grpc.CallOption) (*EchoResponse, error) { 100 | out := new(EchoResponse) 101 | err := grpc.Invoke(ctx, "/echo.Echo/Echo", in, out, c.cc, opts...) 102 | if err != nil { 103 | return nil, err 104 | } 105 | return out, nil 106 | } 107 | 108 | // Server API for Echo service 109 | 110 | type EchoServer interface { 111 | Echo(context.Context, *EchoRequest) (*EchoResponse, error) 112 | } 113 | 114 | func RegisterEchoServer(s *grpc.Server, srv EchoServer) { 115 | s.RegisterService(&_Echo_serviceDesc, srv) 116 | } 117 | 118 | func _Echo_Echo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 119 | in := new(EchoRequest) 120 | if err := dec(in); err != nil { 121 | return nil, err 122 | } 123 | if interceptor == nil { 124 | return srv.(EchoServer).Echo(ctx, in) 125 | } 126 | info := &grpc.UnaryServerInfo{ 127 | Server: srv, 128 | FullMethod: "/echo.Echo/Echo", 129 | } 130 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 131 | return srv.(EchoServer).Echo(ctx, req.(*EchoRequest)) 132 | } 133 | return interceptor(ctx, in, info, handler) 134 | } 135 | 136 | var _Echo_serviceDesc = grpc.ServiceDesc{ 137 | ServiceName: "echo.Echo", 138 | HandlerType: (*EchoServer)(nil), 139 | Methods: []grpc.MethodDesc{ 140 | { 141 | MethodName: "Echo", 142 | Handler: _Echo_Echo_Handler, 143 | }, 144 | }, 145 | Streams: []grpc.StreamDesc{}, 146 | Metadata: "echo.proto", 147 | } 148 | 149 | func init() { proto.RegisterFile("echo.proto", fileDescriptor0) } 150 | 151 | var fileDescriptor0 = []byte{ 152 | // 126 bytes of a gzipped FileDescriptorProto 153 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4a, 0x4d, 0xce, 0xc8, 154 | 0xd7, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x01, 0xb1, 0x95, 0xe4, 0xb9, 0xb8, 0x5d, 0x93, 155 | 0x33, 0xf2, 0x83, 0x52, 0x0b, 0x4b, 0x53, 0x8b, 0x4b, 0x84, 0x04, 0xb8, 0x98, 0x8b, 0x52, 0x0b, 156 | 0x25, 0x18, 0x15, 0x18, 0x35, 0x38, 0x83, 0x40, 0x4c, 0x25, 0x35, 0x2e, 0x1e, 0x88, 0x82, 0xe2, 157 | 0x82, 0xfc, 0xbc, 0xe2, 0x54, 0x21, 0x31, 0x2e, 0xb6, 0xa2, 0xd4, 0xe2, 0xd2, 0x9c, 0x12, 0xa8, 158 | 0x22, 0x28, 0xcf, 0xc8, 0x9c, 0x8b, 0x05, 0xa4, 0x4e, 0x48, 0x1f, 0x4a, 0x0b, 0xea, 0x81, 0xed, 159 | 0x42, 0x32, 0x5c, 0x4a, 0x08, 0x59, 0x08, 0x62, 0x9c, 0x12, 0x43, 0x12, 0x1b, 0xd8, 0x39, 0xc6, 160 | 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x1b, 0x48, 0x20, 0x0f, 0x9c, 0x00, 0x00, 0x00, 161 | } 162 | -------------------------------------------------------------------------------- /ticket.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | 16 | package gmtls 17 | 18 | import ( 19 | "bytes" 20 | "crypto/aes" 21 | "crypto/cipher" 22 | "crypto/hmac" 23 | "crypto/sha256" 24 | "crypto/subtle" 25 | "errors" 26 | "io" 27 | ) 28 | 29 | // sessionState contains the information that is serialized into a session 30 | // ticket in order to later resume a connection. 31 | type sessionState struct { 32 | vers uint16 33 | cipherSuite uint16 34 | masterSecret []byte 35 | certificates [][]byte 36 | // usedOldKey is true if the ticket from which this session came from 37 | // was encrypted with an older key and thus should be refreshed. 38 | usedOldKey bool 39 | } 40 | 41 | func (s *sessionState) equal(i interface{}) bool { 42 | s1, ok := i.(*sessionState) 43 | if !ok { 44 | return false 45 | } 46 | 47 | if s.vers != s1.vers || 48 | s.cipherSuite != s1.cipherSuite || 49 | !bytes.Equal(s.masterSecret, s1.masterSecret) { 50 | return false 51 | } 52 | 53 | if len(s.certificates) != len(s1.certificates) { 54 | return false 55 | } 56 | 57 | for i := range s.certificates { 58 | if !bytes.Equal(s.certificates[i], s1.certificates[i]) { 59 | return false 60 | } 61 | } 62 | 63 | return true 64 | } 65 | 66 | func (s *sessionState) marshal() []byte { 67 | length := 2 + 2 + 2 + len(s.masterSecret) + 2 68 | for _, cert := range s.certificates { 69 | length += 4 + len(cert) 70 | } 71 | 72 | ret := make([]byte, length) 73 | x := ret 74 | x[0] = byte(s.vers >> 8) 75 | x[1] = byte(s.vers) 76 | x[2] = byte(s.cipherSuite >> 8) 77 | x[3] = byte(s.cipherSuite) 78 | x[4] = byte(len(s.masterSecret) >> 8) 79 | x[5] = byte(len(s.masterSecret)) 80 | x = x[6:] 81 | copy(x, s.masterSecret) 82 | x = x[len(s.masterSecret):] 83 | 84 | x[0] = byte(len(s.certificates) >> 8) 85 | x[1] = byte(len(s.certificates)) 86 | x = x[2:] 87 | 88 | for _, cert := range s.certificates { 89 | x[0] = byte(len(cert) >> 24) 90 | x[1] = byte(len(cert) >> 16) 91 | x[2] = byte(len(cert) >> 8) 92 | x[3] = byte(len(cert)) 93 | copy(x[4:], cert) 94 | x = x[4+len(cert):] 95 | } 96 | 97 | return ret 98 | } 99 | 100 | func (s *sessionState) unmarshal(data []byte) bool { 101 | if len(data) < 8 { 102 | return false 103 | } 104 | 105 | s.vers = uint16(data[0])<<8 | uint16(data[1]) 106 | s.cipherSuite = uint16(data[2])<<8 | uint16(data[3]) 107 | masterSecretLen := int(data[4])<<8 | int(data[5]) 108 | data = data[6:] 109 | if len(data) < masterSecretLen { 110 | return false 111 | } 112 | 113 | s.masterSecret = data[:masterSecretLen] 114 | data = data[masterSecretLen:] 115 | 116 | if len(data) < 2 { 117 | return false 118 | } 119 | 120 | numCerts := int(data[0])<<8 | int(data[1]) 121 | data = data[2:] 122 | 123 | s.certificates = make([][]byte, numCerts) 124 | for i := range s.certificates { 125 | if len(data) < 4 { 126 | return false 127 | } 128 | certLen := int(data[0])<<24 | int(data[1])<<16 | int(data[2])<<8 | int(data[3]) 129 | data = data[4:] 130 | if certLen < 0 { 131 | return false 132 | } 133 | if len(data) < certLen { 134 | return false 135 | } 136 | s.certificates[i] = data[:certLen] 137 | data = data[certLen:] 138 | } 139 | 140 | return len(data) == 0 141 | } 142 | 143 | func (c *Conn) encryptTicket(state *sessionState) ([]byte, error) { 144 | serialized := state.marshal() 145 | encrypted := make([]byte, ticketKeyNameLen+aes.BlockSize+len(serialized)+sha256.Size) 146 | keyName := encrypted[:ticketKeyNameLen] 147 | iv := encrypted[ticketKeyNameLen : ticketKeyNameLen+aes.BlockSize] 148 | macBytes := encrypted[len(encrypted)-sha256.Size:] 149 | 150 | if _, err := io.ReadFull(c.config.rand(), iv); err != nil { 151 | return nil, err 152 | } 153 | key := c.config.ticketKeys()[0] 154 | copy(keyName, key.keyName[:]) 155 | block, err := aes.NewCipher(key.aesKey[:]) 156 | if err != nil { 157 | return nil, errors.New("tls: failed to create cipher while encrypting ticket: " + err.Error()) 158 | } 159 | cipher.NewCTR(block, iv).XORKeyStream(encrypted[ticketKeyNameLen+aes.BlockSize:], serialized) 160 | 161 | mac := hmac.New(sha256.New, key.hmacKey[:]) 162 | mac.Write(encrypted[:len(encrypted)-sha256.Size]) 163 | mac.Sum(macBytes[:0]) 164 | 165 | return encrypted, nil 166 | } 167 | 168 | func (c *Conn) decryptTicket(encrypted []byte) (*sessionState, bool) { 169 | if c.config.SessionTicketsDisabled || 170 | len(encrypted) < ticketKeyNameLen+aes.BlockSize+sha256.Size { 171 | return nil, false 172 | } 173 | 174 | keyName := encrypted[:ticketKeyNameLen] 175 | iv := encrypted[ticketKeyNameLen : ticketKeyNameLen+aes.BlockSize] 176 | macBytes := encrypted[len(encrypted)-sha256.Size:] 177 | 178 | keys := c.config.ticketKeys() 179 | keyIndex := -1 180 | for i, candidateKey := range keys { 181 | if bytes.Equal(keyName, candidateKey.keyName[:]) { 182 | keyIndex = i 183 | break 184 | } 185 | } 186 | 187 | if keyIndex == -1 { 188 | return nil, false 189 | } 190 | key := &keys[keyIndex] 191 | 192 | mac := hmac.New(sha256.New, key.hmacKey[:]) 193 | mac.Write(encrypted[:len(encrypted)-sha256.Size]) 194 | expected := mac.Sum(nil) 195 | 196 | if subtle.ConstantTimeCompare(macBytes, expected) != 1 { 197 | return nil, false 198 | } 199 | 200 | block, err := aes.NewCipher(key.aesKey[:]) 201 | if err != nil { 202 | return nil, false 203 | } 204 | ciphertext := encrypted[ticketKeyNameLen+aes.BlockSize : len(encrypted)-sha256.Size] 205 | plaintext := ciphertext 206 | cipher.NewCTR(block, iv).XORKeyStream(plaintext, ciphertext) 207 | 208 | state := &sessionState{usedOldKey: keyIndex > 0} 209 | ok := state.unmarshal(plaintext) 210 | return state, ok 211 | } 212 | -------------------------------------------------------------------------------- /gmcredentials/credentials.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | 16 | package gmcredentials 17 | 18 | import ( 19 | "errors" 20 | "fmt" 21 | "io/ioutil" 22 | "net" 23 | "strings" 24 | 25 | "github.com/tjfoc/gmsm/sm2" 26 | "github.com/tjfoc/gmtls" 27 | 28 | "google.golang.org/grpc/credentials" 29 | 30 | "golang.org/x/net/context" 31 | ) 32 | 33 | var ( 34 | // alpnProtoStr are the specified application level protocols for gRPC. 35 | alpnProtoStr = []string{"h2"} 36 | ) 37 | 38 | // PerRPCCredentials defines the common interface for the credentials which need to 39 | // attach security information to every RPC (e.g., oauth2). 40 | type PerRPCCredentials interface { 41 | // GetRequestMetadata gets the current request metadata, refreshing 42 | // tokens if required. This should be called by the transport layer on 43 | // each request, and the data should be populated in headers or other 44 | // context. uri is the URI of the entry point for the request. When 45 | // supported by the underlying implementation, ctx can be used for 46 | // timeout and cancellation. 47 | // TODO(zhaoq): Define the set of the qualified keys instead of leaving 48 | // it as an arbitrary string. 49 | GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) 50 | // RequireTransportSecurity indicates whether the credentials requires 51 | // transport security. 52 | RequireTransportSecurity() bool 53 | } 54 | 55 | // ProtocolInfo provides information regarding the gRPC wire protocol version, 56 | // security protocol, security protocol version in use, server name, etc. 57 | type ProtocolInfo struct { 58 | // ProtocolVersion is the gRPC wire protocol version. 59 | ProtocolVersion string 60 | // SecurityProtocol is the security protocol in use. 61 | SecurityProtocol string 62 | // SecurityVersion is the security protocol version. 63 | SecurityVersion string 64 | // ServerName is the user-configured server name. 65 | ServerName string 66 | } 67 | 68 | // AuthInfo defines the common interface for the auth information the users are interested in. 69 | type AuthInfo interface { 70 | AuthType() string 71 | } 72 | 73 | var ( 74 | // ErrConnDispatched indicates that rawConn has been dispatched out of gRPC 75 | // and the caller should not close rawConn. 76 | ErrConnDispatched = errors.New("credentials: rawConn is dispatched out of gRPC") 77 | ) 78 | 79 | // TLSInfo contains the auth information for a TLS authenticated connection. 80 | // It implements the AuthInfo interface. 81 | type TLSInfo struct { 82 | State gmtls.ConnectionState 83 | } 84 | 85 | // AuthType returns the type of TLSInfo as a string. 86 | func (t TLSInfo) AuthType() string { 87 | return "tls" 88 | } 89 | 90 | // tlsCreds is the credentials required for authenticating a connection using TLS. 91 | type tlsCreds struct { 92 | // TLS configuration 93 | config *gmtls.Config 94 | } 95 | 96 | // server info 97 | func (c tlsCreds) Info() credentials.ProtocolInfo { 98 | return credentials.ProtocolInfo{ 99 | SecurityProtocol: "tls", 100 | SecurityVersion: "1.2", 101 | ServerName: c.config.ServerName, 102 | } 103 | } 104 | 105 | func (c *tlsCreds) ClientHandshake(ctx context.Context, addr string, rawConn net.Conn) (_ net.Conn, _ credentials.AuthInfo, err error) { 106 | // use local cfg to avoid clobbering ServerName if using multiple endpoints 107 | cfg := cloneTLSConfig(c.config) 108 | if cfg.ServerName == "" { 109 | colonPos := strings.LastIndex(addr, ":") 110 | if colonPos == -1 { 111 | colonPos = len(addr) 112 | } 113 | cfg.ServerName = addr[:colonPos] 114 | } 115 | conn := gmtls.Client(rawConn, cfg) 116 | errChannel := make(chan error, 1) 117 | go func() { 118 | errChannel <- conn.Handshake() 119 | }() 120 | select { 121 | case err := <-errChannel: 122 | if err != nil { 123 | return nil, nil, err 124 | } 125 | case <-ctx.Done(): 126 | return nil, nil, ctx.Err() 127 | } 128 | return conn, TLSInfo{conn.ConnectionState()}, nil 129 | } 130 | 131 | func (c *tlsCreds) ServerHandshake(rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) { 132 | conn := gmtls.Server(rawConn, c.config) 133 | if err := conn.Handshake(); err != nil { 134 | return nil, nil, err 135 | } 136 | return conn, TLSInfo{conn.ConnectionState()}, nil 137 | } 138 | 139 | func (c *tlsCreds) Clone() credentials.TransportCredentials { 140 | return NewTLS(c.config) 141 | } 142 | 143 | func (c *tlsCreds) OverrideServerName(serverNameOverride string) error { 144 | c.config.ServerName = serverNameOverride 145 | return nil 146 | } 147 | 148 | // NewTLS uses c to construct a TransportCredentials based on TLS. 149 | func NewTLS(c *gmtls.Config) credentials.TransportCredentials { 150 | tc := &tlsCreds{cloneTLSConfig(c)} 151 | tc.config.NextProtos = alpnProtoStr 152 | return tc 153 | } 154 | 155 | // NewClientTLSFromCert constructs TLS credentials from the input certificate for client. 156 | // serverNameOverride is for testing only. If set to a non empty string, 157 | // it will override the virtual host name of authority (e.g. :authority header field) in requests. 158 | func NewClientTLSFromCert(cp *sm2.CertPool, serverNameOverride string) credentials.TransportCredentials { 159 | return NewTLS(&gmtls.Config{ServerName: serverNameOverride, RootCAs: cp}) 160 | } 161 | 162 | // NewClientTLSFromFile constructs TLS credentials from the input certificate file for client. 163 | // serverNameOverride is for testing only. If set to a non empty string, 164 | // it will override the virtual host name of authority (e.g. :authority header field) in requests. 165 | func NewClientTLSFromFile(certFile, serverNameOverride string) (credentials.TransportCredentials, error) { 166 | b, err := ioutil.ReadFile(certFile) 167 | if err != nil { 168 | return nil, err 169 | } 170 | cp := sm2.NewCertPool() 171 | if !cp.AppendCertsFromPEM(b) { 172 | return nil, fmt.Errorf("credentials: failed to append certificates") 173 | } 174 | return NewTLS(&gmtls.Config{ServerName: serverNameOverride, RootCAs: cp}), nil 175 | } 176 | 177 | // NewServerTLSFromCert constructs TLS credentials from the input certificate for server. 178 | func NewServerTLSFromCert(cert *gmtls.Certificate) credentials.TransportCredentials { 179 | return NewTLS(&gmtls.Config{Certificates: []gmtls.Certificate{*cert}}) 180 | } 181 | 182 | // NewServerTLSFromFile constructs TLS credentials from the input certificate file and key 183 | // file for server. 184 | func NewServerTLSFromFile(certFile, keyFile string) (credentials.TransportCredentials, error) { 185 | cert, err := gmtls.LoadX509KeyPair(certFile, keyFile) 186 | if err != nil { 187 | return nil, err 188 | } 189 | return NewTLS(&gmtls.Config{Certificates: []gmtls.Certificate{cert}}), nil 190 | } 191 | -------------------------------------------------------------------------------- /tls.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | 16 | // add sm2 support 17 | package gmtls 18 | 19 | import ( 20 | "crypto" 21 | "crypto/ecdsa" 22 | "crypto/rsa" 23 | "crypto/x509" 24 | "encoding/pem" 25 | "errors" 26 | "fmt" 27 | "io/ioutil" 28 | "net" 29 | "strings" 30 | "time" 31 | 32 | "github.com/tjfoc/gmsm/sm2" 33 | ) 34 | 35 | // Server returns a new TLS server side connection 36 | // using conn as the underlying transport. 37 | // The configuration config must be non-nil and must include 38 | // at least one certificate or else set GetCertificate. 39 | func Server(conn net.Conn, config *Config) *Conn { 40 | return &Conn{conn: conn, config: config} 41 | } 42 | 43 | // Client returns a new TLS client side connection 44 | // using conn as the underlying transport. 45 | // The config cannot be nil: users must set either ServerName or 46 | // InsecureSkipVerify in the config. 47 | func Client(conn net.Conn, config *Config) *Conn { 48 | return &Conn{conn: conn, config: config, isClient: true} 49 | } 50 | 51 | // A listener implements a network listener (net.Listener) for TLS connections. 52 | type listener struct { 53 | net.Listener 54 | config *Config 55 | } 56 | 57 | // Accept waits for and returns the next incoming TLS connection. 58 | // The returned connection is of type *Conn. 59 | func (l *listener) Accept() (net.Conn, error) { 60 | c, err := l.Listener.Accept() 61 | if err != nil { 62 | return nil, err 63 | } 64 | return Server(c, l.config), nil 65 | } 66 | 67 | // NewListener creates a Listener which accepts connections from an inner 68 | // Listener and wraps each connection with Server. 69 | // The configuration config must be non-nil and must include 70 | // at least one certificate or else set GetCertificate. 71 | func NewListener(inner net.Listener, config *Config) net.Listener { 72 | l := new(listener) 73 | l.Listener = inner 74 | l.config = config 75 | return l 76 | } 77 | 78 | // Listen creates a TLS listener accepting connections on the 79 | // given network address using net.Listen. 80 | // The configuration config must be non-nil and must include 81 | // at least one certificate or else set GetCertificate. 82 | func Listen(network, laddr string, config *Config) (net.Listener, error) { 83 | if config == nil || (len(config.Certificates) == 0 && config.GetCertificate == nil) { 84 | return nil, errors.New("tls: neither Certificates nor GetCertificate set in Config") 85 | } 86 | l, err := net.Listen(network, laddr) 87 | if err != nil { 88 | return nil, err 89 | } 90 | return NewListener(l, config), nil 91 | } 92 | 93 | type timeoutError struct{} 94 | 95 | func (timeoutError) Error() string { return "tls: DialWithDialer timed out" } 96 | func (timeoutError) Timeout() bool { return true } 97 | func (timeoutError) Temporary() bool { return true } 98 | 99 | // DialWithDialer connects to the given network address using dialer.Dial and 100 | // then initiates a TLS handshake, returning the resulting TLS connection. Any 101 | // timeout or deadline given in the dialer apply to connection and TLS 102 | // handshake as a whole. 103 | // 104 | // DialWithDialer interprets a nil configuration as equivalent to the zero 105 | // configuration; see the documentation of Config for the defaults. 106 | func DialWithDialer(dialer *net.Dialer, network, addr string, config *Config) (*Conn, error) { 107 | // We want the Timeout and Deadline values from dialer to cover the 108 | // whole process: TCP connection and TLS handshake. This means that we 109 | // also need to start our own timers now. 110 | timeout := dialer.Timeout 111 | 112 | if !dialer.Deadline.IsZero() { 113 | deadlineTimeout := time.Until(dialer.Deadline) 114 | if timeout == 0 || deadlineTimeout < timeout { 115 | timeout = deadlineTimeout 116 | } 117 | } 118 | 119 | var errChannel chan error 120 | 121 | if timeout != 0 { 122 | errChannel = make(chan error, 2) 123 | time.AfterFunc(timeout, func() { 124 | errChannel <- timeoutError{} 125 | }) 126 | } 127 | 128 | rawConn, err := dialer.Dial(network, addr) 129 | if err != nil { 130 | return nil, err 131 | } 132 | 133 | colonPos := strings.LastIndex(addr, ":") 134 | if colonPos == -1 { 135 | colonPos = len(addr) 136 | } 137 | hostname := addr[:colonPos] 138 | 139 | if config == nil { 140 | config = defaultConfig() 141 | } 142 | // If no ServerName is set, infer the ServerName 143 | // from the hostname we're connecting to. 144 | if config.ServerName == "" { 145 | // Make a copy to avoid polluting argument or default. 146 | c := config.Clone() 147 | c.ServerName = hostname 148 | config = c 149 | } 150 | 151 | conn := Client(rawConn, config) 152 | 153 | if timeout == 0 { 154 | err = conn.Handshake() 155 | } else { 156 | go func() { 157 | errChannel <- conn.Handshake() 158 | }() 159 | 160 | err = <-errChannel 161 | } 162 | 163 | if err != nil { 164 | rawConn.Close() 165 | return nil, err 166 | } 167 | 168 | return conn, nil 169 | } 170 | 171 | // Dial connects to the given network address using net.Dial 172 | // and then initiates a TLS handshake, returning the resulting 173 | // TLS connection. 174 | // Dial interprets a nil configuration as equivalent to 175 | // the zero configuration; see the documentation of Config 176 | // for the defaults. 177 | func Dial(network, addr string, config *Config) (*Conn, error) { 178 | return DialWithDialer(new(net.Dialer), network, addr, config) 179 | } 180 | 181 | // LoadX509KeyPair reads and parses a public/private key pair from a pair 182 | // of files. The files must contain PEM encoded data. The certificate file 183 | // may contain intermediate certificates following the leaf certificate to 184 | // form a certificate chain. On successful return, Certificate.Leaf will 185 | // be nil because the parsed form of the certificate is not retained. 186 | func LoadX509KeyPair(certFile, keyFile string) (Certificate, error) { 187 | certPEMBlock, err := ioutil.ReadFile(certFile) 188 | if err != nil { 189 | return Certificate{}, err 190 | } 191 | keyPEMBlock, err := ioutil.ReadFile(keyFile) 192 | if err != nil { 193 | return Certificate{}, err 194 | } 195 | return X509KeyPair(certPEMBlock, keyPEMBlock) 196 | } 197 | 198 | // X509KeyPair parses a public/private key pair from a pair of 199 | // PEM encoded data. On successful return, Certificate.Leaf will be nil because 200 | // the parsed form of the certificate is not retained. 201 | func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (Certificate, error) { 202 | fail := func(err error) (Certificate, error) { return Certificate{}, err } 203 | 204 | var cert Certificate 205 | var skippedBlockTypes []string 206 | for { 207 | var certDERBlock *pem.Block 208 | certDERBlock, certPEMBlock = pem.Decode(certPEMBlock) 209 | if certDERBlock == nil { 210 | break 211 | } 212 | if certDERBlock.Type == "CERTIFICATE" { 213 | cert.Certificate = append(cert.Certificate, certDERBlock.Bytes) 214 | } else { 215 | skippedBlockTypes = append(skippedBlockTypes, certDERBlock.Type) 216 | } 217 | } 218 | 219 | if len(cert.Certificate) == 0 { 220 | if len(skippedBlockTypes) == 0 { 221 | return fail(errors.New("tls: failed to find any PEM data in certificate input")) 222 | } 223 | if len(skippedBlockTypes) == 1 && strings.HasSuffix(skippedBlockTypes[0], "PRIVATE KEY") { 224 | return fail(errors.New("tls: failed to find certificate PEM data in certificate input, but did find a private key; PEM inputs may have been switched")) 225 | } 226 | return fail(fmt.Errorf("tls: failed to find \"CERTIFICATE\" PEM block in certificate input after skipping PEM blocks of the following types: %v", skippedBlockTypes)) 227 | } 228 | 229 | skippedBlockTypes = skippedBlockTypes[:0] 230 | var keyDERBlock *pem.Block 231 | for { 232 | keyDERBlock, keyPEMBlock = pem.Decode(keyPEMBlock) 233 | if keyDERBlock == nil { 234 | if len(skippedBlockTypes) == 0 { 235 | return fail(errors.New("tls: failed to find any PEM data in key input")) 236 | } 237 | if len(skippedBlockTypes) == 1 && skippedBlockTypes[0] == "CERTIFICATE" { 238 | return fail(errors.New("tls: found a certificate rather than a key in the PEM for the private key")) 239 | } 240 | return fail(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)) 241 | } 242 | if keyDERBlock.Type == "PRIVATE KEY" || strings.HasSuffix(keyDERBlock.Type, " PRIVATE KEY") { 243 | break 244 | } 245 | skippedBlockTypes = append(skippedBlockTypes, keyDERBlock.Type) 246 | } 247 | 248 | var err error 249 | cert.PrivateKey, err = parsePrivateKey(keyDERBlock.Bytes) 250 | if err != nil { 251 | return fail(err) 252 | } 253 | 254 | // We don't need to parse the public key for TLS, but we so do anyway 255 | // to check that it looks sane and matches the private key. 256 | x509Cert, err := sm2.ParseCertificate(cert.Certificate[0]) 257 | if err != nil { 258 | return fail(err) 259 | } 260 | 261 | switch pub := x509Cert.PublicKey.(type) { 262 | case *rsa.PublicKey: 263 | priv, ok := cert.PrivateKey.(*rsa.PrivateKey) 264 | if !ok { 265 | return fail(errors.New("tls: private key type does not match public key type")) 266 | } 267 | if pub.N.Cmp(priv.N) != 0 { 268 | return fail(errors.New("tls: private key does not match public key")) 269 | } 270 | case *ecdsa.PublicKey: 271 | pub, _ = x509Cert.PublicKey.(*ecdsa.PublicKey) 272 | switch pub.Curve { 273 | case sm2.P256Sm2(): 274 | priv, ok := cert.PrivateKey.(*sm2.PrivateKey) 275 | if !ok { 276 | return fail(errors.New("tls: sm2 private key type does not match public key type")) 277 | } 278 | if pub.X.Cmp(priv.X) != 0 || pub.Y.Cmp(priv.Y) != 0 { 279 | return fail(errors.New("tls: sm2 private key does not match public key")) 280 | } 281 | default: 282 | priv, ok := cert.PrivateKey.(*ecdsa.PrivateKey) 283 | if !ok { 284 | return fail(errors.New("tls: private key type does not match public key type")) 285 | } 286 | if pub.X.Cmp(priv.X) != 0 || pub.Y.Cmp(priv.Y) != 0 { 287 | return fail(errors.New("tls: private key does not match public key")) 288 | } 289 | } 290 | default: 291 | return fail(errors.New("tls: unknown public key algorithm")) 292 | } 293 | return cert, nil 294 | } 295 | 296 | func parsePrivateKey(der []byte) (crypto.PrivateKey, error) { 297 | if key, err := x509.ParsePKCS1PrivateKey(der); err == nil { 298 | return key, nil 299 | } 300 | if key, err := x509.ParsePKCS8PrivateKey(der); err == nil { 301 | switch key := key.(type) { 302 | case *rsa.PrivateKey, *ecdsa.PrivateKey: 303 | return key, nil 304 | default: 305 | return nil, errors.New("tls: found unknown private key type in PKCS#8 wrapping") 306 | } 307 | } 308 | if key, err := sm2.ParsePKCS8UnecryptedPrivateKey(der); err == nil { 309 | return key, nil 310 | } 311 | return nil, errors.New("tls: failed to parse private key") 312 | } 313 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /prf.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | 16 | package gmtls 17 | 18 | import ( 19 | "crypto" 20 | "crypto/hmac" 21 | "crypto/md5" 22 | "crypto/sha1" 23 | "crypto/sha256" 24 | "crypto/sha512" 25 | "errors" 26 | "hash" 27 | ) 28 | 29 | // Split a premaster secret in two as specified in RFC 4346, section 5. 30 | func splitPreMasterSecret(secret []byte) (s1, s2 []byte) { 31 | s1 = secret[0 : (len(secret)+1)/2] 32 | s2 = secret[len(secret)/2:] 33 | return 34 | } 35 | 36 | // pHash implements the P_hash function, as defined in RFC 4346, section 5. 37 | func pHash(result, secret, seed []byte, hash func() hash.Hash) { 38 | h := hmac.New(hash, secret) 39 | h.Write(seed) 40 | a := h.Sum(nil) 41 | 42 | j := 0 43 | for j < len(result) { 44 | h.Reset() 45 | h.Write(a) 46 | h.Write(seed) 47 | b := h.Sum(nil) 48 | todo := len(b) 49 | if j+todo > len(result) { 50 | todo = len(result) - j 51 | } 52 | copy(result[j:j+todo], b) 53 | j += todo 54 | 55 | h.Reset() 56 | h.Write(a) 57 | a = h.Sum(nil) 58 | } 59 | } 60 | 61 | // prf10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, section 5. 62 | func prf10(result, secret, label, seed []byte) { 63 | hashSHA1 := sha1.New 64 | hashMD5 := md5.New 65 | 66 | labelAndSeed := make([]byte, len(label)+len(seed)) 67 | copy(labelAndSeed, label) 68 | copy(labelAndSeed[len(label):], seed) 69 | 70 | s1, s2 := splitPreMasterSecret(secret) 71 | pHash(result, s1, labelAndSeed, hashMD5) 72 | result2 := make([]byte, len(result)) 73 | pHash(result2, s2, labelAndSeed, hashSHA1) 74 | 75 | for i, b := range result2 { 76 | result[i] ^= b 77 | } 78 | } 79 | 80 | // prf12 implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, section 5. 81 | func prf12(hashFunc func() hash.Hash) func(result, secret, label, seed []byte) { 82 | return func(result, secret, label, seed []byte) { 83 | labelAndSeed := make([]byte, len(label)+len(seed)) 84 | copy(labelAndSeed, label) 85 | copy(labelAndSeed[len(label):], seed) 86 | 87 | pHash(result, secret, labelAndSeed, hashFunc) 88 | } 89 | } 90 | 91 | // prf30 implements the SSL 3.0 pseudo-random function, as defined in 92 | // www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt section 6. 93 | func prf30(result, secret, label, seed []byte) { 94 | hashSHA1 := sha1.New() 95 | hashMD5 := md5.New() 96 | 97 | done := 0 98 | i := 0 99 | // RFC 5246 section 6.3 says that the largest PRF output needed is 128 100 | // bytes. Since no more ciphersuites will be added to SSLv3, this will 101 | // remain true. Each iteration gives us 16 bytes so 10 iterations will 102 | // be sufficient. 103 | var b [11]byte 104 | for done < len(result) { 105 | for j := 0; j <= i; j++ { 106 | b[j] = 'A' + byte(i) 107 | } 108 | 109 | hashSHA1.Reset() 110 | hashSHA1.Write(b[:i+1]) 111 | hashSHA1.Write(secret) 112 | hashSHA1.Write(seed) 113 | digest := hashSHA1.Sum(nil) 114 | 115 | hashMD5.Reset() 116 | hashMD5.Write(secret) 117 | hashMD5.Write(digest) 118 | 119 | done += copy(result[done:], hashMD5.Sum(nil)) 120 | i++ 121 | } 122 | } 123 | 124 | const ( 125 | tlsRandomLength = 32 // Length of a random nonce in TLS 1.1. 126 | masterSecretLength = 48 // Length of a master secret in TLS 1.1. 127 | finishedVerifyLength = 12 // Length of verify_data in a Finished message. 128 | ) 129 | 130 | var masterSecretLabel = []byte("master secret") 131 | var keyExpansionLabel = []byte("key expansion") 132 | var clientFinishedLabel = []byte("client finished") 133 | var serverFinishedLabel = []byte("server finished") 134 | 135 | func prfAndHashForVersion(version uint16, suite *cipherSuite) (func(result, secret, label, seed []byte), crypto.Hash) { 136 | switch version { 137 | case VersionSSL30: 138 | return prf30, crypto.Hash(0) 139 | case VersionTLS10, VersionTLS11: 140 | return prf10, crypto.Hash(0) 141 | case VersionTLS12: 142 | if suite.flags&suiteSHA384 != 0 { 143 | return prf12(sha512.New384), crypto.SHA384 144 | } 145 | return prf12(sha256.New), crypto.SHA256 146 | default: 147 | panic("unknown version") 148 | } 149 | } 150 | 151 | func prfForVersion(version uint16, suite *cipherSuite) func(result, secret, label, seed []byte) { 152 | prf, _ := prfAndHashForVersion(version, suite) 153 | return prf 154 | } 155 | 156 | // masterFromPreMasterSecret generates the master secret from the pre-master 157 | // secret. See http://tools.ietf.org/html/rfc5246#section-8.1 158 | func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, clientRandom, serverRandom []byte) []byte { 159 | seed := make([]byte, 0, len(clientRandom)+len(serverRandom)) 160 | seed = append(seed, clientRandom...) 161 | seed = append(seed, serverRandom...) 162 | 163 | masterSecret := make([]byte, masterSecretLength) 164 | prfForVersion(version, suite)(masterSecret, preMasterSecret, masterSecretLabel, seed) 165 | return masterSecret 166 | } 167 | 168 | // keysFromMasterSecret generates the connection keys from the master 169 | // secret, given the lengths of the MAC key, cipher key and IV, as defined in 170 | // RFC 2246, section 6.3. 171 | func keysFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) { 172 | seed := make([]byte, 0, len(serverRandom)+len(clientRandom)) 173 | seed = append(seed, serverRandom...) 174 | seed = append(seed, clientRandom...) 175 | 176 | n := 2*macLen + 2*keyLen + 2*ivLen 177 | keyMaterial := make([]byte, n) 178 | prfForVersion(version, suite)(keyMaterial, masterSecret, keyExpansionLabel, seed) 179 | clientMAC = keyMaterial[:macLen] 180 | keyMaterial = keyMaterial[macLen:] 181 | serverMAC = keyMaterial[:macLen] 182 | keyMaterial = keyMaterial[macLen:] 183 | clientKey = keyMaterial[:keyLen] 184 | keyMaterial = keyMaterial[keyLen:] 185 | serverKey = keyMaterial[:keyLen] 186 | keyMaterial = keyMaterial[keyLen:] 187 | clientIV = keyMaterial[:ivLen] 188 | keyMaterial = keyMaterial[ivLen:] 189 | serverIV = keyMaterial[:ivLen] 190 | return 191 | } 192 | 193 | // lookupTLSHash looks up the corresponding crypto.Hash for a given 194 | // TLS hash identifier. 195 | func lookupTLSHash(hash uint8) (crypto.Hash, error) { 196 | switch hash { 197 | case hashSHA1: 198 | return crypto.SHA1, nil 199 | case hashSHA256: 200 | return crypto.SHA256, nil 201 | case hashSHA384: 202 | return crypto.SHA384, nil 203 | default: 204 | return 0, errors.New("tls: unsupported hash algorithm") 205 | } 206 | } 207 | 208 | func newFinishedHash(version uint16, cipherSuite *cipherSuite) finishedHash { 209 | var buffer []byte 210 | if version == VersionSSL30 || version >= VersionTLS12 { 211 | buffer = []byte{} 212 | } 213 | 214 | prf, hash := prfAndHashForVersion(version, cipherSuite) 215 | if hash != 0 { 216 | return finishedHash{hash.New(), hash.New(), nil, nil, buffer, version, prf} 217 | } 218 | 219 | return finishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), buffer, version, prf} 220 | } 221 | 222 | // A finishedHash calculates the hash of a set of handshake messages suitable 223 | // for including in a Finished message. 224 | type finishedHash struct { 225 | client hash.Hash 226 | server hash.Hash 227 | 228 | // Prior to TLS 1.2, an additional MD5 hash is required. 229 | clientMD5 hash.Hash 230 | serverMD5 hash.Hash 231 | 232 | // In TLS 1.2, a full buffer is sadly required. 233 | buffer []byte 234 | 235 | version uint16 236 | prf func(result, secret, label, seed []byte) 237 | } 238 | 239 | func (h *finishedHash) Write(msg []byte) (n int, err error) { 240 | h.client.Write(msg) 241 | h.server.Write(msg) 242 | 243 | if h.version < VersionTLS12 { 244 | h.clientMD5.Write(msg) 245 | h.serverMD5.Write(msg) 246 | } 247 | 248 | if h.buffer != nil { 249 | h.buffer = append(h.buffer, msg...) 250 | } 251 | 252 | return len(msg), nil 253 | } 254 | 255 | func (h finishedHash) Sum() []byte { 256 | if h.version >= VersionTLS12 { 257 | return h.client.Sum(nil) 258 | } 259 | 260 | out := make([]byte, 0, md5.Size+sha1.Size) 261 | out = h.clientMD5.Sum(out) 262 | return h.client.Sum(out) 263 | } 264 | 265 | // finishedSum30 calculates the contents of the verify_data member of a SSLv3 266 | // Finished message given the MD5 and SHA1 hashes of a set of handshake 267 | // messages. 268 | func finishedSum30(md5, sha1 hash.Hash, masterSecret []byte, magic []byte) []byte { 269 | md5.Write(magic) 270 | md5.Write(masterSecret) 271 | md5.Write(ssl30Pad1[:]) 272 | md5Digest := md5.Sum(nil) 273 | 274 | md5.Reset() 275 | md5.Write(masterSecret) 276 | md5.Write(ssl30Pad2[:]) 277 | md5.Write(md5Digest) 278 | md5Digest = md5.Sum(nil) 279 | 280 | sha1.Write(magic) 281 | sha1.Write(masterSecret) 282 | sha1.Write(ssl30Pad1[:40]) 283 | sha1Digest := sha1.Sum(nil) 284 | 285 | sha1.Reset() 286 | sha1.Write(masterSecret) 287 | sha1.Write(ssl30Pad2[:40]) 288 | sha1.Write(sha1Digest) 289 | sha1Digest = sha1.Sum(nil) 290 | 291 | ret := make([]byte, len(md5Digest)+len(sha1Digest)) 292 | copy(ret, md5Digest) 293 | copy(ret[len(md5Digest):], sha1Digest) 294 | return ret 295 | } 296 | 297 | var ssl3ClientFinishedMagic = [4]byte{0x43, 0x4c, 0x4e, 0x54} 298 | var ssl3ServerFinishedMagic = [4]byte{0x53, 0x52, 0x56, 0x52} 299 | 300 | // clientSum returns the contents of the verify_data member of a client's 301 | // Finished message. 302 | func (h finishedHash) clientSum(masterSecret []byte) []byte { 303 | if h.version == VersionSSL30 { 304 | return finishedSum30(h.clientMD5, h.client, masterSecret, ssl3ClientFinishedMagic[:]) 305 | } 306 | 307 | out := make([]byte, finishedVerifyLength) 308 | h.prf(out, masterSecret, clientFinishedLabel, h.Sum()) 309 | return out 310 | } 311 | 312 | // serverSum returns the contents of the verify_data member of a server's 313 | // Finished message. 314 | func (h finishedHash) serverSum(masterSecret []byte) []byte { 315 | if h.version == VersionSSL30 { 316 | return finishedSum30(h.serverMD5, h.server, masterSecret, ssl3ServerFinishedMagic[:]) 317 | } 318 | 319 | out := make([]byte, finishedVerifyLength) 320 | h.prf(out, masterSecret, serverFinishedLabel, h.Sum()) 321 | return out 322 | } 323 | 324 | // selectClientCertSignatureAlgorithm returns a signatureAndHash to sign a 325 | // client's CertificateVerify with, or an error if none can be found. 326 | func (h finishedHash) selectClientCertSignatureAlgorithm(serverList []signatureAndHash, sigType uint8) (signatureAndHash, error) { 327 | if h.version < VersionTLS12 { 328 | // Nothing to negotiate before TLS 1.2. 329 | return signatureAndHash{signature: sigType}, nil 330 | } 331 | 332 | for _, v := range serverList { 333 | if v.signature == sigType && isSupportedSignatureAndHash(v, supportedSignatureAlgorithms) { 334 | return v, nil 335 | } 336 | } 337 | return signatureAndHash{}, errors.New("tls: no supported signature algorithm found for signing client certificate") 338 | } 339 | 340 | // hashForClientCertificate returns a digest, hash function, and TLS 1.2 hash 341 | // id suitable for signing by a TLS client certificate. 342 | func (h finishedHash) hashForClientCertificate(signatureAndHash signatureAndHash, masterSecret []byte) ([]byte, crypto.Hash, error) { 343 | if (h.version == VersionSSL30 || h.version >= VersionTLS12) && h.buffer == nil { 344 | panic("a handshake hash for a client-certificate was requested after discarding the handshake buffer") 345 | } 346 | 347 | if h.version == VersionSSL30 { 348 | if signatureAndHash.signature != signatureRSA { 349 | return nil, 0, errors.New("tls: unsupported signature type for client certificate") 350 | } 351 | 352 | md5Hash := md5.New() 353 | md5Hash.Write(h.buffer) 354 | sha1Hash := sha1.New() 355 | sha1Hash.Write(h.buffer) 356 | return finishedSum30(md5Hash, sha1Hash, masterSecret, nil), crypto.MD5SHA1, nil 357 | } 358 | if h.version >= VersionTLS12 { 359 | hashAlg, err := lookupTLSHash(signatureAndHash.hash) 360 | if err != nil { 361 | return nil, 0, err 362 | } 363 | hash := hashAlg.New() 364 | hash.Write(h.buffer) 365 | return hash.Sum(nil), hashAlg, nil 366 | } 367 | 368 | if signatureAndHash.signature == signatureECDSA { 369 | return h.server.Sum(nil), crypto.SHA1, nil 370 | } 371 | 372 | return h.Sum(), crypto.MD5SHA1, nil 373 | } 374 | 375 | // discardHandshakeBuffer is called when there is no more need to 376 | // buffer the entirety of the handshake messages. 377 | func (h *finishedHash) discardHandshakeBuffer() { 378 | h.buffer = nil 379 | } 380 | -------------------------------------------------------------------------------- /cipher_suites.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | 16 | package gmtls 17 | 18 | import ( 19 | "crypto/aes" 20 | "crypto/cipher" 21 | "crypto/des" 22 | "crypto/hmac" 23 | "crypto/rc4" 24 | "crypto/sha1" 25 | "crypto/sha256" 26 | "hash" 27 | 28 | "github.com/tjfoc/gmsm/sm2" 29 | 30 | "golang.org/x/crypto/chacha20poly1305" 31 | ) 32 | 33 | // a keyAgreement implements the client and server side of a TLS key agreement 34 | // protocol by generating and processing key exchange messages. 35 | type keyAgreement interface { 36 | // On the server side, the first two methods are called in order. 37 | 38 | // In the case that the key agreement protocol doesn't use a 39 | // ServerKeyExchange message, generateServerKeyExchange can return nil, 40 | // nil. 41 | generateServerKeyExchange(*Config, *Certificate, *clientHelloMsg, *serverHelloMsg) (*serverKeyExchangeMsg, error) 42 | processClientKeyExchange(*Config, *Certificate, *clientKeyExchangeMsg, uint16) ([]byte, error) 43 | 44 | // On the client side, the next two methods are called in order. 45 | 46 | // This method may not be called if the server doesn't send a 47 | // ServerKeyExchange message. 48 | processServerKeyExchange(*Config, *clientHelloMsg, *serverHelloMsg, *sm2.Certificate, *serverKeyExchangeMsg) error 49 | generateClientKeyExchange(*Config, *clientHelloMsg, *sm2.Certificate) ([]byte, *clientKeyExchangeMsg, error) 50 | } 51 | 52 | const ( 53 | // suiteECDH indicates that the cipher suite involves elliptic curve 54 | // Diffie-Hellman. This means that it should only be selected when the 55 | // client indicates that it supports ECC with a curve and point format 56 | // that we're happy with. 57 | suiteECDHE = 1 << iota 58 | // suiteECDSA indicates that the cipher suite involves an ECDSA 59 | // signature and therefore may only be selected when the server's 60 | // certificate is ECDSA. If this is not set then the cipher suite is 61 | // RSA based. 62 | suiteECDSA 63 | // suiteTLS12 indicates that the cipher suite should only be advertised 64 | // and accepted when using TLS 1.2. 65 | suiteTLS12 66 | // suiteSHA384 indicates that the cipher suite uses SHA384 as the 67 | // handshake hash. 68 | suiteSHA384 69 | // suiteDefaultOff indicates that this cipher suite is not included by 70 | // default. 71 | suiteDefaultOff 72 | ) 73 | 74 | // A cipherSuite is a specific combination of key agreement, cipher and MAC 75 | // function. All cipher suites currently assume RSA key agreement. 76 | type cipherSuite struct { 77 | id uint16 78 | // the lengths, in bytes, of the key material needed for each component. 79 | keyLen int 80 | macLen int 81 | ivLen int 82 | ka func(version uint16) keyAgreement 83 | // flags is a bitmask of the suite* values, above. 84 | flags int 85 | cipher func(key, iv []byte, isRead bool) interface{} 86 | mac func(version uint16, macKey []byte) macFunction 87 | aead func(key, fixedNonce []byte) cipher.AEAD 88 | } 89 | 90 | var cipherSuites = []*cipherSuite{ 91 | // Ciphersuite order is chosen so that ECDHE comes before plain RSA and 92 | // AEADs are the top preference. 93 | {TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, 32, 0, 12, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadChaCha20Poly1305}, 94 | {TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, 32, 0, 12, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadChaCha20Poly1305}, 95 | {TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadAESGCM}, 96 | {TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadAESGCM}, 97 | {TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM}, 98 | {TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM}, 99 | {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteDefaultOff, cipherAES, macSHA256, nil}, 100 | {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil}, 101 | {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12 | suiteDefaultOff, cipherAES, macSHA256, nil}, 102 | {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil}, 103 | {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil}, 104 | {TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil}, 105 | {TLS_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, rsaKA, suiteTLS12, nil, nil, aeadAESGCM}, 106 | {TLS_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, rsaKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM}, 107 | {TLS_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, rsaKA, suiteTLS12 | suiteDefaultOff, cipherAES, macSHA256, nil}, 108 | {TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil}, 109 | {TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil}, 110 | {TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, suiteECDHE, cipher3DES, macSHA1, nil}, 111 | {TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, 0, cipher3DES, macSHA1, nil}, 112 | 113 | // RC4-based cipher suites are disabled by default. 114 | {TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, suiteDefaultOff, cipherRC4, macSHA1, nil}, 115 | {TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, suiteECDHE | suiteDefaultOff, cipherRC4, macSHA1, nil}, 116 | {TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteDefaultOff, cipherRC4, macSHA1, nil}, 117 | } 118 | 119 | func cipherRC4(key, iv []byte, isRead bool) interface{} { 120 | cipher, _ := rc4.NewCipher(key) 121 | return cipher 122 | } 123 | 124 | func cipher3DES(key, iv []byte, isRead bool) interface{} { 125 | block, _ := des.NewTripleDESCipher(key) 126 | if isRead { 127 | return cipher.NewCBCDecrypter(block, iv) 128 | } 129 | return cipher.NewCBCEncrypter(block, iv) 130 | } 131 | 132 | func cipherAES(key, iv []byte, isRead bool) interface{} { 133 | block, _ := aes.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 macSHA1(version uint16, key []byte) macFunction { 142 | if version == VersionSSL30 { 143 | mac := ssl30MAC{ 144 | h: sha1.New(), 145 | key: make([]byte, len(key)), 146 | } 147 | copy(mac.key, key) 148 | return mac 149 | } 150 | return tls10MAC{hmac.New(newConstantTimeHash(sha1.New), key)} 151 | } 152 | 153 | // macSHA256 returns a SHA-256 based MAC. These are only supported in TLS 1.2 154 | // so the given version is ignored. 155 | func macSHA256(version uint16, key []byte) macFunction { 156 | return tls10MAC{hmac.New(sha256.New, key)} 157 | } 158 | 159 | type macFunction interface { 160 | Size() int 161 | MAC(digestBuf, seq, header, data, extra []byte) []byte 162 | } 163 | 164 | type aead interface { 165 | cipher.AEAD 166 | 167 | // explicitIVLen returns the number of bytes used by the explicit nonce 168 | // that is included in the record. This is eight for older AEADs and 169 | // zero for modern ones. 170 | explicitNonceLen() int 171 | } 172 | 173 | // fixedNonceAEAD wraps an AEAD and prefixes a fixed portion of the nonce to 174 | // each call. 175 | type fixedNonceAEAD struct { 176 | // nonce contains the fixed part of the nonce in the first four bytes. 177 | nonce [12]byte 178 | aead cipher.AEAD 179 | } 180 | 181 | func (f *fixedNonceAEAD) NonceSize() int { return 8 } 182 | func (f *fixedNonceAEAD) Overhead() int { return f.aead.Overhead() } 183 | func (f *fixedNonceAEAD) explicitNonceLen() int { return 8 } 184 | 185 | func (f *fixedNonceAEAD) Seal(out, nonce, plaintext, additionalData []byte) []byte { 186 | copy(f.nonce[4:], nonce) 187 | return f.aead.Seal(out, f.nonce[:], plaintext, additionalData) 188 | } 189 | 190 | func (f *fixedNonceAEAD) Open(out, nonce, plaintext, additionalData []byte) ([]byte, error) { 191 | copy(f.nonce[4:], nonce) 192 | return f.aead.Open(out, f.nonce[:], plaintext, additionalData) 193 | } 194 | 195 | // xoredNonceAEAD wraps an AEAD by XORing in a fixed pattern to the nonce 196 | // before each call. 197 | type xorNonceAEAD struct { 198 | nonceMask [12]byte 199 | aead cipher.AEAD 200 | } 201 | 202 | func (f *xorNonceAEAD) NonceSize() int { return 8 } 203 | func (f *xorNonceAEAD) Overhead() int { return f.aead.Overhead() } 204 | func (f *xorNonceAEAD) explicitNonceLen() int { return 0 } 205 | 206 | func (f *xorNonceAEAD) Seal(out, nonce, plaintext, additionalData []byte) []byte { 207 | for i, b := range nonce { 208 | f.nonceMask[4+i] ^= b 209 | } 210 | result := f.aead.Seal(out, f.nonceMask[:], plaintext, additionalData) 211 | for i, b := range nonce { 212 | f.nonceMask[4+i] ^= b 213 | } 214 | 215 | return result 216 | } 217 | 218 | func (f *xorNonceAEAD) Open(out, nonce, plaintext, additionalData []byte) ([]byte, error) { 219 | for i, b := range nonce { 220 | f.nonceMask[4+i] ^= b 221 | } 222 | result, err := f.aead.Open(out, f.nonceMask[:], plaintext, additionalData) 223 | for i, b := range nonce { 224 | f.nonceMask[4+i] ^= b 225 | } 226 | 227 | return result, err 228 | } 229 | 230 | func aeadAESGCM(key, fixedNonce []byte) cipher.AEAD { 231 | aes, err := aes.NewCipher(key) 232 | if err != nil { 233 | panic(err) 234 | } 235 | aead, err := cipher.NewGCM(aes) 236 | if err != nil { 237 | panic(err) 238 | } 239 | 240 | ret := &fixedNonceAEAD{aead: aead} 241 | copy(ret.nonce[:], fixedNonce) 242 | return ret 243 | } 244 | 245 | func aeadChaCha20Poly1305(key, fixedNonce []byte) cipher.AEAD { 246 | aead, err := chacha20poly1305.New(key) 247 | if err != nil { 248 | panic(err) 249 | } 250 | 251 | ret := &xorNonceAEAD{aead: aead} 252 | copy(ret.nonceMask[:], fixedNonce) 253 | return ret 254 | } 255 | 256 | // ssl30MAC implements the SSLv3 MAC function, as defined in 257 | // www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt section 5.2.3.1 258 | type ssl30MAC struct { 259 | h hash.Hash 260 | key []byte 261 | } 262 | 263 | func (s ssl30MAC) Size() int { 264 | return s.h.Size() 265 | } 266 | 267 | var ssl30Pad1 = [48]byte{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36} 268 | 269 | var ssl30Pad2 = [48]byte{0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c} 270 | 271 | // MAC does not offer constant timing guarantees for SSL v3.0, since it's deemed 272 | // useless considering the similar, protocol-level POODLE vulnerability. 273 | func (s ssl30MAC) MAC(digestBuf, seq, header, data, extra []byte) []byte { 274 | padLength := 48 275 | if s.h.Size() == 20 { 276 | padLength = 40 277 | } 278 | 279 | s.h.Reset() 280 | s.h.Write(s.key) 281 | s.h.Write(ssl30Pad1[:padLength]) 282 | s.h.Write(seq) 283 | s.h.Write(header[:1]) 284 | s.h.Write(header[3:5]) 285 | s.h.Write(data) 286 | digestBuf = s.h.Sum(digestBuf[:0]) 287 | 288 | s.h.Reset() 289 | s.h.Write(s.key) 290 | s.h.Write(ssl30Pad2[:padLength]) 291 | s.h.Write(digestBuf) 292 | return s.h.Sum(digestBuf[:0]) 293 | } 294 | 295 | type constantTimeHash interface { 296 | hash.Hash 297 | ConstantTimeSum(b []byte) []byte 298 | } 299 | 300 | // cthWrapper wraps any hash.Hash that implements ConstantTimeSum, and replaces 301 | // with that all calls to Sum. It's used to obtain a ConstantTimeSum-based HMAC. 302 | type cthWrapper struct { 303 | h constantTimeHash 304 | } 305 | 306 | func (c *cthWrapper) Size() int { return c.h.Size() } 307 | func (c *cthWrapper) BlockSize() int { return c.h.BlockSize() } 308 | func (c *cthWrapper) Reset() { c.h.Reset() } 309 | func (c *cthWrapper) Write(p []byte) (int, error) { return c.h.Write(p) } 310 | func (c *cthWrapper) Sum(b []byte) []byte { return c.h.ConstantTimeSum(b) } 311 | 312 | func newConstantTimeHash(h func() hash.Hash) func() hash.Hash { 313 | return func() hash.Hash { 314 | return &cthWrapper{h().(constantTimeHash)} 315 | } 316 | } 317 | 318 | // tls10MAC implements the TLS 1.0 MAC function. RFC 2246, section 6.2.3. 319 | type tls10MAC struct { 320 | h hash.Hash 321 | } 322 | 323 | func (s tls10MAC) Size() int { 324 | return s.h.Size() 325 | } 326 | 327 | // MAC is guaranteed to take constant time, as long as 328 | // len(seq)+len(header)+len(data)+len(extra) is constant. extra is not fed into 329 | // the MAC, but is only provided to make the timing profile constant. 330 | func (s tls10MAC) MAC(digestBuf, seq, header, data, extra []byte) []byte { 331 | s.h.Reset() 332 | s.h.Write(seq) 333 | s.h.Write(header) 334 | s.h.Write(data) 335 | res := s.h.Sum(digestBuf[:0]) 336 | if extra != nil { 337 | s.h.Write(extra) 338 | } 339 | return res 340 | } 341 | 342 | func rsaKA(version uint16) keyAgreement { 343 | return rsaKeyAgreement{} 344 | } 345 | 346 | func ecdheECDSAKA(version uint16) keyAgreement { 347 | return &ecdheKeyAgreement{ 348 | sigType: signatureECDSA, 349 | version: version, 350 | } 351 | } 352 | 353 | func ecdheRSAKA(version uint16) keyAgreement { 354 | return &ecdheKeyAgreement{ 355 | sigType: signatureRSA, 356 | version: version, 357 | } 358 | } 359 | 360 | // mutualCipherSuite returns a cipherSuite given a list of supported 361 | // ciphersuites and the id requested by the peer. 362 | func mutualCipherSuite(have []uint16, want uint16) *cipherSuite { 363 | for _, id := range have { 364 | if id == want { 365 | for _, suite := range cipherSuites { 366 | if suite.id == want { 367 | return suite 368 | } 369 | } 370 | return nil 371 | } 372 | } 373 | return nil 374 | } 375 | 376 | // A list of cipher suite IDs that are, or have been, implemented by this 377 | // package. 378 | // 379 | // Taken from http://www.iana.org/assignments/tls-parameters/tls-parameters.xml 380 | const ( 381 | TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005 382 | TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000a 383 | TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002f 384 | TLS_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0035 385 | TLS_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x003c 386 | TLS_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009c 387 | TLS_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009d 388 | TLS_ECDHE_ECDSA_WITH_RC4_128_SHA uint16 = 0xc007 389 | TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA uint16 = 0xc009 390 | TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA uint16 = 0xc00a 391 | TLS_ECDHE_RSA_WITH_RC4_128_SHA uint16 = 0xc011 392 | TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xc012 393 | TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xc013 394 | TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0xc014 395 | TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 uint16 = 0xc023 396 | TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0xc027 397 | TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02f 398 | TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02b 399 | TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xc030 400 | TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xc02c 401 | TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 uint16 = 0xcca8 402 | TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 uint16 = 0xcca9 403 | 404 | // TLS_FALLBACK_SCSV isn't a standard cipher suite but an indicator 405 | // that the client is doing version fallback. See 406 | // https://tools.ietf.org/html/rfc7507. 407 | TLS_FALLBACK_SCSV uint16 = 0x5600 408 | ) 409 | -------------------------------------------------------------------------------- /key_agreement.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | 16 | package gmtls 17 | 18 | import ( 19 | "crypto" 20 | "crypto/ecdsa" 21 | "crypto/elliptic" 22 | "crypto/md5" 23 | "crypto/rsa" 24 | "crypto/sha1" 25 | "encoding/asn1" 26 | "errors" 27 | "io" 28 | "math/big" 29 | 30 | "github.com/tjfoc/gmsm/sm2" 31 | 32 | "golang.org/x/crypto/curve25519" 33 | ) 34 | 35 | var errClientKeyExchange = errors.New("tls: invalid ClientKeyExchange message") 36 | var errServerKeyExchange = errors.New("tls: invalid ServerKeyExchange message") 37 | 38 | // rsaKeyAgreement implements the standard TLS key agreement where the client 39 | // encrypts the pre-master secret to the server's public key. 40 | type rsaKeyAgreement struct{} 41 | 42 | func (ka rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) { 43 | return nil, nil 44 | } 45 | 46 | func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) { 47 | if len(ckx.ciphertext) < 2 { 48 | return nil, errClientKeyExchange 49 | } 50 | 51 | ciphertext := ckx.ciphertext 52 | if version != VersionSSL30 { 53 | ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1]) 54 | if ciphertextLen != len(ckx.ciphertext)-2 { 55 | return nil, errClientKeyExchange 56 | } 57 | ciphertext = ckx.ciphertext[2:] 58 | } 59 | priv, ok := cert.PrivateKey.(crypto.Decrypter) 60 | if !ok { 61 | return nil, errors.New("tls: certificate private key does not implement crypto.Decrypter") 62 | } 63 | // Perform constant time RSA PKCS#1 v1.5 decryption 64 | preMasterSecret, err := priv.Decrypt(config.rand(), ciphertext, &rsa.PKCS1v15DecryptOptions{SessionKeyLen: 48}) 65 | if err != nil { 66 | return nil, err 67 | } 68 | // We don't check the version number in the premaster secret. For one, 69 | // by checking it, we would leak information about the validity of the 70 | // encrypted pre-master secret. Secondly, it provides only a small 71 | // benefit against a downgrade attack and some implementations send the 72 | // wrong version anyway. See the discussion at the end of section 73 | // 7.4.7.1 of RFC 4346. 74 | return preMasterSecret, nil 75 | } 76 | 77 | func (ka rsaKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *sm2.Certificate, skx *serverKeyExchangeMsg) error { 78 | return errors.New("tls: unexpected ServerKeyExchange") 79 | } 80 | 81 | func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *sm2.Certificate) ([]byte, *clientKeyExchangeMsg, error) { 82 | preMasterSecret := make([]byte, 48) 83 | preMasterSecret[0] = byte(clientHello.vers >> 8) 84 | preMasterSecret[1] = byte(clientHello.vers) 85 | _, err := io.ReadFull(config.rand(), preMasterSecret[2:]) 86 | if err != nil { 87 | return nil, nil, err 88 | } 89 | 90 | encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), preMasterSecret) 91 | if err != nil { 92 | return nil, nil, err 93 | } 94 | ckx := new(clientKeyExchangeMsg) 95 | ckx.ciphertext = make([]byte, len(encrypted)+2) 96 | ckx.ciphertext[0] = byte(len(encrypted) >> 8) 97 | ckx.ciphertext[1] = byte(len(encrypted)) 98 | copy(ckx.ciphertext[2:], encrypted) 99 | return preMasterSecret, ckx, nil 100 | } 101 | 102 | // sha1Hash calculates a SHA1 hash over the given byte slices. 103 | func sha1Hash(slices [][]byte) []byte { 104 | hsha1 := sha1.New() 105 | for _, slice := range slices { 106 | hsha1.Write(slice) 107 | } 108 | return hsha1.Sum(nil) 109 | } 110 | 111 | // md5SHA1Hash implements TLS 1.0's hybrid hash function which consists of the 112 | // concatenation of an MD5 and SHA1 hash. 113 | func md5SHA1Hash(slices [][]byte) []byte { 114 | md5sha1 := make([]byte, md5.Size+sha1.Size) 115 | hmd5 := md5.New() 116 | for _, slice := range slices { 117 | hmd5.Write(slice) 118 | } 119 | copy(md5sha1, hmd5.Sum(nil)) 120 | copy(md5sha1[md5.Size:], sha1Hash(slices)) 121 | return md5sha1 122 | } 123 | 124 | // hashForServerKeyExchange hashes the given slices and returns their digest 125 | // and the identifier of the hash function used. The sigAndHash argument is 126 | // only used for >= TLS 1.2 and precisely identifies the hash function to use. 127 | func hashForServerKeyExchange(sigAndHash signatureAndHash, version uint16, slices ...[]byte) ([]byte, crypto.Hash, error) { 128 | if version >= VersionTLS12 { 129 | if !isSupportedSignatureAndHash(sigAndHash, supportedSignatureAlgorithms) { 130 | return nil, crypto.Hash(0), errors.New("tls: unsupported hash function used by peer") 131 | } 132 | hashFunc, err := lookupTLSHash(sigAndHash.hash) 133 | if err != nil { 134 | return nil, crypto.Hash(0), err 135 | } 136 | h := hashFunc.New() 137 | for _, slice := range slices { 138 | h.Write(slice) 139 | } 140 | digest := h.Sum(nil) 141 | return digest, hashFunc, nil 142 | } 143 | if sigAndHash.signature == signatureECDSA { 144 | return sha1Hash(slices), crypto.SHA1, nil 145 | } 146 | return md5SHA1Hash(slices), crypto.MD5SHA1, nil 147 | } 148 | 149 | // pickTLS12HashForSignature returns a TLS 1.2 hash identifier for signing a 150 | // ServerKeyExchange given the signature type being used and the client's 151 | // advertised list of supported signature and hash combinations. 152 | func pickTLS12HashForSignature(sigType uint8, clientList []signatureAndHash) (uint8, error) { 153 | if len(clientList) == 0 { 154 | // If the client didn't specify any signature_algorithms 155 | // extension then we can assume that it supports SHA1. See 156 | // http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 157 | return hashSHA1, nil 158 | } 159 | 160 | for _, sigAndHash := range clientList { 161 | if sigAndHash.signature != sigType { 162 | continue 163 | } 164 | if isSupportedSignatureAndHash(sigAndHash, supportedSignatureAlgorithms) { 165 | return sigAndHash.hash, nil 166 | } 167 | } 168 | 169 | return 0, errors.New("tls: client doesn't support any common hash functions") 170 | } 171 | 172 | func curveForCurveID(id CurveID) (elliptic.Curve, bool) { 173 | switch id { 174 | case CurveP256: 175 | return elliptic.P256(), true 176 | case CurveP384: 177 | return elliptic.P384(), true 178 | case CurveP521: 179 | return elliptic.P521(), true 180 | case CureP256SM2: 181 | return sm2.P256Sm2(), true 182 | default: 183 | return nil, false 184 | } 185 | 186 | } 187 | 188 | // ecdheRSAKeyAgreement implements a TLS key agreement where the server 189 | // generates a ephemeral EC public/private key pair and signs it. The 190 | // pre-master secret is then calculated using ECDH. The signature may 191 | // either be ECDSA or RSA. 192 | type ecdheKeyAgreement struct { 193 | version uint16 194 | sigType uint8 195 | privateKey []byte 196 | curveid CurveID 197 | 198 | // publicKey is used to store the peer's public value when X25519 is 199 | // being used. 200 | publicKey []byte 201 | // x and y are used to store the peer's public value when one of the 202 | // NIST curves is being used. 203 | x, y *big.Int 204 | } 205 | 206 | func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) { 207 | preferredCurves := config.curvePreferences() 208 | 209 | NextCandidate: 210 | for _, candidate := range preferredCurves { 211 | for _, c := range clientHello.supportedCurves { 212 | if candidate == c { 213 | ka.curveid = c 214 | break NextCandidate 215 | } 216 | } 217 | } 218 | 219 | if ka.curveid == 0 { 220 | return nil, errors.New("tls: no supported elliptic curves offered") 221 | } 222 | 223 | var ecdhePublic []byte 224 | 225 | if ka.curveid == X25519 { 226 | var scalar, public [32]byte 227 | if _, err := io.ReadFull(config.rand(), scalar[:]); err != nil { 228 | return nil, err 229 | } 230 | 231 | curve25519.ScalarBaseMult(&public, &scalar) 232 | ka.privateKey = scalar[:] 233 | ecdhePublic = public[:] 234 | } else { 235 | curve, ok := curveForCurveID(ka.curveid) 236 | if !ok { 237 | return nil, errors.New("tls: preferredCurves includes unsupported curve") 238 | } 239 | 240 | var x, y *big.Int 241 | var err error 242 | ka.privateKey, x, y, err = elliptic.GenerateKey(curve, config.rand()) 243 | if err != nil { 244 | return nil, err 245 | } 246 | ecdhePublic = elliptic.Marshal(curve, x, y) 247 | } 248 | 249 | // http://tools.ietf.org/html/rfc4492#section-5.4 250 | serverECDHParams := make([]byte, 1+2+1+len(ecdhePublic)) 251 | serverECDHParams[0] = 3 // named curve 252 | serverECDHParams[1] = byte(ka.curveid >> 8) 253 | serverECDHParams[2] = byte(ka.curveid) 254 | serverECDHParams[3] = byte(len(ecdhePublic)) 255 | copy(serverECDHParams[4:], ecdhePublic) 256 | 257 | sigAndHash := signatureAndHash{signature: ka.sigType} 258 | 259 | if ka.version >= VersionTLS12 { 260 | var err error 261 | if sigAndHash.hash, err = pickTLS12HashForSignature(ka.sigType, clientHello.signatureAndHashes); err != nil { 262 | return nil, err 263 | } 264 | } 265 | 266 | digest, hashFunc, err := hashForServerKeyExchange(sigAndHash, ka.version, clientHello.random, hello.random, serverECDHParams) 267 | if err != nil { 268 | return nil, err 269 | } 270 | 271 | priv, ok := cert.PrivateKey.(crypto.Signer) 272 | if !ok { 273 | return nil, errors.New("tls: certificate private key does not implement crypto.Signer") 274 | } 275 | var sig []byte 276 | switch ka.sigType { 277 | case signatureECDSA: 278 | _, ok1 := priv.Public().(*sm2.PublicKey) 279 | _, ok2 := priv.Public().(*ecdsa.PublicKey) 280 | if !ok1 && !ok2 { 281 | return nil, errors.New("tls: ECDHE ECDSA requires an ECDSA server key") 282 | } 283 | case signatureRSA: 284 | _, ok := priv.Public().(*rsa.PublicKey) 285 | if !ok { 286 | return nil, errors.New("tls: ECDHE RSA requires a RSA server key") 287 | } 288 | default: 289 | return nil, errors.New("tls: unknown ECDHE signature algorithm") 290 | } 291 | sig, err = priv.Sign(config.rand(), digest, hashFunc) 292 | if err != nil { 293 | return nil, errors.New("tls: failed to sign ECDHE parameters: " + err.Error()) 294 | } 295 | 296 | skx := new(serverKeyExchangeMsg) 297 | sigAndHashLen := 0 298 | if ka.version >= VersionTLS12 { 299 | sigAndHashLen = 2 300 | } 301 | skx.key = make([]byte, len(serverECDHParams)+sigAndHashLen+2+len(sig)) 302 | copy(skx.key, serverECDHParams) 303 | k := skx.key[len(serverECDHParams):] 304 | if ka.version >= VersionTLS12 { 305 | k[0] = sigAndHash.hash 306 | k[1] = sigAndHash.signature 307 | k = k[2:] 308 | } 309 | k[0] = byte(len(sig) >> 8) 310 | k[1] = byte(len(sig)) 311 | copy(k[2:], sig) 312 | 313 | return skx, nil 314 | } 315 | 316 | func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) { 317 | if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 { 318 | return nil, errClientKeyExchange 319 | } 320 | 321 | if ka.curveid == X25519 { 322 | if len(ckx.ciphertext) != 1+32 { 323 | return nil, errClientKeyExchange 324 | } 325 | 326 | var theirPublic, sharedKey, scalar [32]byte 327 | copy(theirPublic[:], ckx.ciphertext[1:]) 328 | copy(scalar[:], ka.privateKey) 329 | curve25519.ScalarMult(&sharedKey, &scalar, &theirPublic) 330 | return sharedKey[:], nil 331 | } 332 | 333 | curve, ok := curveForCurveID(ka.curveid) 334 | if !ok { 335 | panic("internal error") 336 | } 337 | x, y := elliptic.Unmarshal(curve, ckx.ciphertext[1:]) 338 | if x == nil { 339 | return nil, errClientKeyExchange 340 | } 341 | if !curve.IsOnCurve(x, y) { 342 | return nil, errClientKeyExchange 343 | } 344 | x, _ = curve.ScalarMult(x, y, ka.privateKey) 345 | preMasterSecret := make([]byte, (curve.Params().BitSize+7)>>3) 346 | xBytes := x.Bytes() 347 | copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes) 348 | 349 | return preMasterSecret, nil 350 | } 351 | 352 | func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *sm2.Certificate, skx *serverKeyExchangeMsg) error { 353 | if len(skx.key) < 4 { 354 | return errServerKeyExchange 355 | } 356 | if skx.key[0] != 3 { // named curve 357 | return errors.New("tls: server selected unsupported curve") 358 | } 359 | ka.curveid = CurveID(skx.key[1])<<8 | CurveID(skx.key[2]) 360 | 361 | publicLen := int(skx.key[3]) 362 | if publicLen+4 > len(skx.key) { 363 | return errServerKeyExchange 364 | } 365 | serverECDHParams := skx.key[:4+publicLen] 366 | publicKey := serverECDHParams[4:] 367 | 368 | sig := skx.key[4+publicLen:] 369 | if len(sig) < 2 { 370 | return errServerKeyExchange 371 | } 372 | 373 | if ka.curveid == X25519 { 374 | if len(publicKey) != 32 { 375 | return errors.New("tls: bad X25519 public value") 376 | } 377 | ka.publicKey = publicKey 378 | } else { 379 | curve, ok := curveForCurveID(ka.curveid) 380 | if !ok { 381 | return errors.New("tls: server selected unsupported curve") 382 | } 383 | 384 | ka.x, ka.y = elliptic.Unmarshal(curve, publicKey) 385 | if ka.x == nil { 386 | return errServerKeyExchange 387 | } 388 | if !curve.IsOnCurve(ka.x, ka.y) { 389 | return errServerKeyExchange 390 | } 391 | } 392 | 393 | sigAndHash := signatureAndHash{signature: ka.sigType} 394 | if ka.version >= VersionTLS12 { 395 | // handle SignatureAndHashAlgorithm 396 | sigAndHash = signatureAndHash{hash: sig[0], signature: sig[1]} 397 | if sigAndHash.signature != ka.sigType { 398 | return errServerKeyExchange 399 | } 400 | sig = sig[2:] 401 | if len(sig) < 2 { 402 | return errServerKeyExchange 403 | } 404 | } 405 | sigLen := int(sig[0])<<8 | int(sig[1]) 406 | if sigLen+2 != len(sig) { 407 | return errServerKeyExchange 408 | } 409 | sig = sig[2:] 410 | 411 | digest, hashFunc, err := hashForServerKeyExchange(sigAndHash, ka.version, clientHello.random, serverHello.random, serverECDHParams) 412 | if err != nil { 413 | return err 414 | } 415 | switch ka.sigType { 416 | case signatureECDSA: 417 | pubKey, ok := cert.PublicKey.(*ecdsa.PublicKey) 418 | if !ok { 419 | return errors.New("tls: ECDHE ECDSA requires a ECDSA server public key") 420 | } 421 | ecdsaSig := new(ecdsaSignature) 422 | if _, err := asn1.Unmarshal(sig, ecdsaSig); err != nil { 423 | return err 424 | } 425 | if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 { 426 | return errors.New("tls: ECDSA signature contained zero or negative values") 427 | } 428 | switch pubKey.Curve { 429 | case sm2.P256Sm2(): 430 | if !sm2.Verify(&sm2.PublicKey{ 431 | X: pubKey.X, 432 | Y: pubKey.Y, 433 | Curve: pubKey.Curve, 434 | }, digest, ecdsaSig.R, ecdsaSig.S) { 435 | return errors.New("tls: SM2 verification failure") 436 | } 437 | default: 438 | if !ecdsa.Verify(pubKey, digest, ecdsaSig.R, ecdsaSig.S) { 439 | return errors.New("tls: ECDSA verification failure") 440 | } 441 | } 442 | case signatureRSA: 443 | pubKey, ok := cert.PublicKey.(*rsa.PublicKey) 444 | if !ok { 445 | return errors.New("tls: ECDHE RSA requires a RSA server public key") 446 | } 447 | if err := rsa.VerifyPKCS1v15(pubKey, hashFunc, digest, sig); err != nil { 448 | return err 449 | } 450 | default: 451 | return errors.New("tls: unknown ECDHE signature algorithm") 452 | } 453 | 454 | return nil 455 | } 456 | 457 | func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *sm2.Certificate) ([]byte, *clientKeyExchangeMsg, error) { 458 | if ka.curveid == 0 { 459 | return nil, nil, errors.New("tls: missing ServerKeyExchange message") 460 | } 461 | 462 | var serialized, preMasterSecret []byte 463 | 464 | if ka.curveid == X25519 { 465 | var ourPublic, theirPublic, sharedKey, scalar [32]byte 466 | 467 | if _, err := io.ReadFull(config.rand(), scalar[:]); err != nil { 468 | return nil, nil, err 469 | } 470 | 471 | copy(theirPublic[:], ka.publicKey) 472 | curve25519.ScalarBaseMult(&ourPublic, &scalar) 473 | curve25519.ScalarMult(&sharedKey, &scalar, &theirPublic) 474 | serialized = ourPublic[:] 475 | preMasterSecret = sharedKey[:] 476 | } else { 477 | curve, ok := curveForCurveID(ka.curveid) 478 | if !ok { 479 | panic("internal error") 480 | } 481 | priv, mx, my, err := elliptic.GenerateKey(curve, config.rand()) 482 | if err != nil { 483 | return nil, nil, err 484 | } 485 | x, _ := curve.ScalarMult(ka.x, ka.y, priv) 486 | preMasterSecret = make([]byte, (curve.Params().BitSize+7)>>3) 487 | xBytes := x.Bytes() 488 | copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes) 489 | 490 | serialized = elliptic.Marshal(curve, mx, my) 491 | } 492 | 493 | ckx := new(clientKeyExchangeMsg) 494 | ckx.ciphertext = make([]byte, 1+len(serialized)) 495 | ckx.ciphertext[0] = byte(len(serialized)) 496 | copy(ckx.ciphertext[1:], serialized) 497 | 498 | return preMasterSecret, ckx, nil 499 | } 500 | -------------------------------------------------------------------------------- /handshake_client.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | 16 | package gmtls 17 | 18 | import ( 19 | "bytes" 20 | "crypto" 21 | "crypto/ecdsa" 22 | "crypto/rsa" 23 | "crypto/subtle" 24 | "errors" 25 | "fmt" 26 | "io" 27 | "net" 28 | "strconv" 29 | "strings" 30 | 31 | "github.com/tjfoc/gmsm/sm2" 32 | ) 33 | 34 | type clientHandshakeState struct { 35 | c *Conn 36 | serverHello *serverHelloMsg 37 | hello *clientHelloMsg 38 | suite *cipherSuite 39 | finishedHash finishedHash 40 | masterSecret []byte 41 | session *ClientSessionState 42 | } 43 | 44 | // c.out.Mutex <= L; c.handshakeMutex <= L. 45 | func (c *Conn) clientHandshake() error { 46 | if c.config == nil { 47 | c.config = defaultConfig() 48 | } 49 | 50 | // This may be a renegotiation handshake, in which case some fields 51 | // need to be reset. 52 | c.didResume = false 53 | 54 | if len(c.config.ServerName) == 0 && !c.config.InsecureSkipVerify { 55 | return errors.New("tls: either ServerName or InsecureSkipVerify must be specified in the tls.Config") 56 | } 57 | 58 | nextProtosLength := 0 59 | for _, proto := range c.config.NextProtos { 60 | if l := len(proto); l == 0 || l > 255 { 61 | return errors.New("tls: invalid NextProtos value") 62 | } else { 63 | nextProtosLength += 1 + l 64 | } 65 | } 66 | if nextProtosLength > 0xffff { 67 | return errors.New("tls: NextProtos values too large") 68 | } 69 | 70 | hello := &clientHelloMsg{ 71 | vers: c.config.maxVersion(), 72 | compressionMethods: []uint8{compressionNone}, 73 | random: make([]byte, 32), 74 | ocspStapling: true, 75 | scts: true, 76 | serverName: hostnameInSNI(c.config.ServerName), 77 | supportedCurves: c.config.curvePreferences(), 78 | supportedPoints: []uint8{pointFormatUncompressed}, 79 | nextProtoNeg: len(c.config.NextProtos) > 0, 80 | secureRenegotiationSupported: true, 81 | alpnProtocols: c.config.NextProtos, 82 | } 83 | 84 | if c.handshakes > 0 { 85 | hello.secureRenegotiation = c.clientFinished[:] 86 | } 87 | 88 | possibleCipherSuites := c.config.cipherSuites() 89 | hello.cipherSuites = make([]uint16, 0, len(possibleCipherSuites)) 90 | 91 | NextCipherSuite: 92 | for _, suiteId := range possibleCipherSuites { 93 | for _, suite := range cipherSuites { 94 | if suite.id != suiteId { 95 | continue 96 | } 97 | // Don't advertise TLS 1.2-only cipher suites unless 98 | // we're attempting TLS 1.2. 99 | if hello.vers < VersionTLS12 && suite.flags&suiteTLS12 != 0 { 100 | continue 101 | } 102 | hello.cipherSuites = append(hello.cipherSuites, suiteId) 103 | continue NextCipherSuite 104 | } 105 | } 106 | 107 | _, err := io.ReadFull(c.config.rand(), hello.random) 108 | if err != nil { 109 | c.sendAlert(alertInternalError) 110 | return errors.New("tls: short read from Rand: " + err.Error()) 111 | } 112 | 113 | if hello.vers >= VersionTLS12 { 114 | hello.signatureAndHashes = supportedSignatureAlgorithms 115 | } 116 | 117 | var session *ClientSessionState 118 | var cacheKey string 119 | sessionCache := c.config.ClientSessionCache 120 | if c.config.SessionTicketsDisabled { 121 | sessionCache = nil 122 | } 123 | 124 | if sessionCache != nil { 125 | hello.ticketSupported = true 126 | } 127 | 128 | // Session resumption is not allowed if renegotiating because 129 | // renegotiation is primarily used to allow a client to send a client 130 | // certificate, which would be skipped if session resumption occurred. 131 | if sessionCache != nil && c.handshakes == 0 { 132 | // Try to resume a previously negotiated TLS session, if 133 | // available. 134 | cacheKey = clientSessionCacheKey(c.conn.RemoteAddr(), c.config) 135 | candidateSession, ok := sessionCache.Get(cacheKey) 136 | if ok { 137 | // Check that the ciphersuite/version used for the 138 | // previous session are still valid. 139 | cipherSuiteOk := false 140 | for _, id := range hello.cipherSuites { 141 | if id == candidateSession.cipherSuite { 142 | cipherSuiteOk = true 143 | break 144 | } 145 | } 146 | 147 | versOk := candidateSession.vers >= c.config.minVersion() && 148 | candidateSession.vers <= c.config.maxVersion() 149 | if versOk && cipherSuiteOk { 150 | session = candidateSession 151 | } 152 | } 153 | } 154 | 155 | if session != nil { 156 | hello.sessionTicket = session.sessionTicket 157 | // A random session ID is used to detect when the 158 | // server accepted the ticket and is resuming a session 159 | // (see RFC 5077). 160 | hello.sessionId = make([]byte, 16) 161 | if _, err := io.ReadFull(c.config.rand(), hello.sessionId); err != nil { 162 | c.sendAlert(alertInternalError) 163 | return errors.New("tls: short read from Rand: " + err.Error()) 164 | } 165 | } 166 | 167 | if _, err := c.writeRecord(recordTypeHandshake, hello.marshal()); err != nil { 168 | return err 169 | } 170 | 171 | msg, err := c.readHandshake() 172 | if err != nil { 173 | return err 174 | } 175 | serverHello, ok := msg.(*serverHelloMsg) 176 | if !ok { 177 | c.sendAlert(alertUnexpectedMessage) 178 | return unexpectedMessageError(serverHello, msg) 179 | } 180 | 181 | vers, ok := c.config.mutualVersion(serverHello.vers) 182 | if !ok || vers < VersionTLS10 { 183 | // TLS 1.0 is the minimum version supported as a client. 184 | c.sendAlert(alertProtocolVersion) 185 | return fmt.Errorf("tls: server selected unsupported protocol version %x", serverHello.vers) 186 | } 187 | c.vers = vers 188 | c.haveVers = true 189 | 190 | suite := mutualCipherSuite(hello.cipherSuites, serverHello.cipherSuite) 191 | if suite == nil { 192 | c.sendAlert(alertHandshakeFailure) 193 | return errors.New("tls: server chose an unconfigured cipher suite") 194 | } 195 | 196 | hs := &clientHandshakeState{ 197 | c: c, 198 | serverHello: serverHello, 199 | hello: hello, 200 | suite: suite, 201 | finishedHash: newFinishedHash(c.vers, suite), 202 | session: session, 203 | } 204 | 205 | isResume, err := hs.processServerHello() 206 | if err != nil { 207 | return err 208 | } 209 | 210 | // No signatures of the handshake are needed in a resumption. 211 | // Otherwise, in a full handshake, if we don't have any certificates 212 | // configured then we will never send a CertificateVerify message and 213 | // thus no signatures are needed in that case either. 214 | if isResume || (len(c.config.Certificates) == 0 && c.config.GetClientCertificate == nil) { 215 | hs.finishedHash.discardHandshakeBuffer() 216 | } 217 | 218 | hs.finishedHash.Write(hs.hello.marshal()) 219 | hs.finishedHash.Write(hs.serverHello.marshal()) 220 | 221 | c.buffering = true 222 | if isResume { 223 | if err := hs.establishKeys(); err != nil { 224 | return err 225 | } 226 | if err := hs.readSessionTicket(); err != nil { 227 | return err 228 | } 229 | if err := hs.readFinished(c.serverFinished[:]); err != nil { 230 | return err 231 | } 232 | c.clientFinishedIsFirst = false 233 | if err := hs.sendFinished(c.clientFinished[:]); err != nil { 234 | return err 235 | } 236 | if _, err := c.flush(); err != nil { 237 | return err 238 | } 239 | } else { 240 | if err := hs.doFullHandshake(); err != nil { 241 | return err 242 | } 243 | if err := hs.establishKeys(); err != nil { 244 | return err 245 | } 246 | if err := hs.sendFinished(c.clientFinished[:]); err != nil { 247 | return err 248 | } 249 | if _, err := c.flush(); err != nil { 250 | return err 251 | } 252 | c.clientFinishedIsFirst = true 253 | if err := hs.readSessionTicket(); err != nil { 254 | return err 255 | } 256 | if err := hs.readFinished(c.serverFinished[:]); err != nil { 257 | return err 258 | } 259 | } 260 | 261 | if sessionCache != nil && hs.session != nil && session != hs.session { 262 | sessionCache.Put(cacheKey, hs.session) 263 | } 264 | 265 | c.didResume = isResume 266 | c.handshakeComplete = true 267 | c.cipherSuite = suite.id 268 | return nil 269 | } 270 | 271 | func (hs *clientHandshakeState) doFullHandshake() error { 272 | c := hs.c 273 | 274 | msg, err := c.readHandshake() 275 | if err != nil { 276 | return err 277 | } 278 | certMsg, ok := msg.(*certificateMsg) 279 | if !ok || len(certMsg.certificates) == 0 { 280 | c.sendAlert(alertUnexpectedMessage) 281 | return unexpectedMessageError(certMsg, msg) 282 | } 283 | hs.finishedHash.Write(certMsg.marshal()) 284 | 285 | if c.handshakes == 0 { 286 | // If this is the first handshake on a connection, process and 287 | // (optionally) verify the server's certificates. 288 | certs := make([]*sm2.Certificate, len(certMsg.certificates)) 289 | for i, asn1Data := range certMsg.certificates { 290 | cert, err := sm2.ParseCertificate(asn1Data) 291 | if err != nil { 292 | c.sendAlert(alertBadCertificate) 293 | return errors.New("tls: failed to parse certificate from server: " + err.Error()) 294 | } 295 | certs[i] = cert 296 | } 297 | 298 | if !c.config.InsecureSkipVerify { 299 | opts := sm2.VerifyOptions{ 300 | Roots: c.config.RootCAs, 301 | CurrentTime: c.config.time(), 302 | DNSName: c.config.ServerName, 303 | Intermediates: sm2.NewCertPool(), 304 | } 305 | 306 | for i, cert := range certs { 307 | if i == 0 { 308 | continue 309 | } 310 | opts.Intermediates.AddCert(cert) 311 | } 312 | c.verifiedChains, err = certs[0].Verify(opts) 313 | if err != nil { 314 | c.sendAlert(alertBadCertificate) 315 | return err 316 | } 317 | } 318 | 319 | if c.config.VerifyPeerCertificate != nil { 320 | if err := c.config.VerifyPeerCertificate(certMsg.certificates, c.verifiedChains); err != nil { 321 | c.sendAlert(alertBadCertificate) 322 | return err 323 | } 324 | } 325 | 326 | switch certs[0].PublicKey.(type) { 327 | case *rsa.PublicKey, *ecdsa.PublicKey, *sm2.PublicKey: 328 | break 329 | default: 330 | c.sendAlert(alertUnsupportedCertificate) 331 | return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", certs[0].PublicKey) 332 | } 333 | 334 | c.peerCertificates = certs 335 | } else { 336 | // This is a renegotiation handshake. We require that the 337 | // server's identity (i.e. leaf certificate) is unchanged and 338 | // thus any previous trust decision is still valid. 339 | // 340 | // See https://mitls.org/pages/attacks/3SHAKE for the 341 | // motivation behind this requirement. 342 | if !bytes.Equal(c.peerCertificates[0].Raw, certMsg.certificates[0]) { 343 | c.sendAlert(alertBadCertificate) 344 | return errors.New("tls: server's identity changed during renegotiation") 345 | } 346 | } 347 | 348 | if hs.serverHello.ocspStapling { 349 | msg, err = c.readHandshake() 350 | if err != nil { 351 | return err 352 | } 353 | cs, ok := msg.(*certificateStatusMsg) 354 | if !ok { 355 | c.sendAlert(alertUnexpectedMessage) 356 | return unexpectedMessageError(cs, msg) 357 | } 358 | hs.finishedHash.Write(cs.marshal()) 359 | 360 | if cs.statusType == statusTypeOCSP { 361 | c.ocspResponse = cs.response 362 | } 363 | } 364 | 365 | msg, err = c.readHandshake() 366 | if err != nil { 367 | return err 368 | } 369 | 370 | keyAgreement := hs.suite.ka(c.vers) 371 | 372 | skx, ok := msg.(*serverKeyExchangeMsg) 373 | if ok { 374 | hs.finishedHash.Write(skx.marshal()) 375 | err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, c.peerCertificates[0], skx) 376 | if err != nil { 377 | c.sendAlert(alertUnexpectedMessage) 378 | return err 379 | } 380 | 381 | msg, err = c.readHandshake() 382 | if err != nil { 383 | return err 384 | } 385 | } 386 | 387 | var chainToSend *Certificate 388 | var certRequested bool 389 | certReq, ok := msg.(*certificateRequestMsg) 390 | if ok { 391 | certRequested = true 392 | hs.finishedHash.Write(certReq.marshal()) 393 | 394 | if chainToSend, err = hs.getCertificate(certReq); err != nil { 395 | c.sendAlert(alertInternalError) 396 | return err 397 | } 398 | 399 | msg, err = c.readHandshake() 400 | if err != nil { 401 | return err 402 | } 403 | } 404 | 405 | shd, ok := msg.(*serverHelloDoneMsg) 406 | if !ok { 407 | c.sendAlert(alertUnexpectedMessage) 408 | return unexpectedMessageError(shd, msg) 409 | } 410 | hs.finishedHash.Write(shd.marshal()) 411 | 412 | // If the server requested a certificate then we have to send a 413 | // Certificate message, even if it's empty because we don't have a 414 | // certificate to send. 415 | if certRequested { 416 | certMsg = new(certificateMsg) 417 | certMsg.certificates = chainToSend.Certificate 418 | hs.finishedHash.Write(certMsg.marshal()) 419 | if _, err := c.writeRecord(recordTypeHandshake, certMsg.marshal()); err != nil { 420 | return err 421 | } 422 | } 423 | 424 | preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, c.peerCertificates[0]) 425 | if err != nil { 426 | c.sendAlert(alertInternalError) 427 | return err 428 | } 429 | if ckx != nil { 430 | hs.finishedHash.Write(ckx.marshal()) 431 | if _, err := c.writeRecord(recordTypeHandshake, ckx.marshal()); err != nil { 432 | return err 433 | } 434 | } 435 | 436 | if chainToSend != nil && len(chainToSend.Certificate) > 0 { 437 | certVerify := &certificateVerifyMsg{ 438 | hasSignatureAndHash: c.vers >= VersionTLS12, 439 | } 440 | 441 | key, ok := chainToSend.PrivateKey.(crypto.Signer) 442 | if !ok { 443 | c.sendAlert(alertInternalError) 444 | return fmt.Errorf("tls: client certificate private key of type %T does not implement crypto.Signer", chainToSend.PrivateKey) 445 | } 446 | 447 | var signatureType uint8 448 | switch key.Public().(type) { 449 | case *ecdsa.PublicKey, *sm2.PublicKey: 450 | signatureType = signatureECDSA 451 | case *rsa.PublicKey: 452 | signatureType = signatureRSA 453 | default: 454 | c.sendAlert(alertInternalError) 455 | return fmt.Errorf("tls: failed to sign handshake with client certificate: unknown client certificate key type: %T", key) 456 | } 457 | 458 | certVerify.signatureAndHash, err = hs.finishedHash.selectClientCertSignatureAlgorithm(certReq.signatureAndHashes, signatureType) 459 | if err != nil { 460 | c.sendAlert(alertInternalError) 461 | return err 462 | } 463 | digest, hashFunc, err := hs.finishedHash.hashForClientCertificate(certVerify.signatureAndHash, hs.masterSecret) 464 | if err != nil { 465 | c.sendAlert(alertInternalError) 466 | return err 467 | } 468 | certVerify.signature, err = key.Sign(c.config.rand(), digest, hashFunc) 469 | if err != nil { 470 | c.sendAlert(alertInternalError) 471 | return err 472 | } 473 | 474 | hs.finishedHash.Write(certVerify.marshal()) 475 | if _, err := c.writeRecord(recordTypeHandshake, certVerify.marshal()); err != nil { 476 | return err 477 | } 478 | } 479 | 480 | hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random) 481 | if err := c.config.writeKeyLog(hs.hello.random, hs.masterSecret); err != nil { 482 | c.sendAlert(alertInternalError) 483 | return errors.New("tls: failed to write to key log: " + err.Error()) 484 | } 485 | 486 | hs.finishedHash.discardHandshakeBuffer() 487 | 488 | return nil 489 | } 490 | 491 | func (hs *clientHandshakeState) establishKeys() error { 492 | c := hs.c 493 | 494 | clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV := 495 | keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.hello.random, hs.serverHello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen) 496 | var clientCipher, serverCipher interface{} 497 | var clientHash, serverHash macFunction 498 | if hs.suite.cipher != nil { 499 | clientCipher = hs.suite.cipher(clientKey, clientIV, false /* not for reading */) 500 | clientHash = hs.suite.mac(c.vers, clientMAC) 501 | serverCipher = hs.suite.cipher(serverKey, serverIV, true /* for reading */) 502 | serverHash = hs.suite.mac(c.vers, serverMAC) 503 | } else { 504 | clientCipher = hs.suite.aead(clientKey, clientIV) 505 | serverCipher = hs.suite.aead(serverKey, serverIV) 506 | } 507 | 508 | c.in.prepareCipherSpec(c.vers, serverCipher, serverHash) 509 | c.out.prepareCipherSpec(c.vers, clientCipher, clientHash) 510 | return nil 511 | } 512 | 513 | func (hs *clientHandshakeState) serverResumedSession() bool { 514 | // If the server responded with the same sessionId then it means the 515 | // sessionTicket is being used to resume a TLS session. 516 | return hs.session != nil && hs.hello.sessionId != nil && 517 | bytes.Equal(hs.serverHello.sessionId, hs.hello.sessionId) 518 | } 519 | 520 | func (hs *clientHandshakeState) processServerHello() (bool, error) { 521 | c := hs.c 522 | 523 | if hs.serverHello.compressionMethod != compressionNone { 524 | c.sendAlert(alertUnexpectedMessage) 525 | return false, errors.New("tls: server selected unsupported compression format") 526 | } 527 | 528 | if c.handshakes == 0 && hs.serverHello.secureRenegotiationSupported { 529 | c.secureRenegotiation = true 530 | if len(hs.serverHello.secureRenegotiation) != 0 { 531 | c.sendAlert(alertHandshakeFailure) 532 | return false, errors.New("tls: initial handshake had non-empty renegotiation extension") 533 | } 534 | } 535 | 536 | if c.handshakes > 0 && c.secureRenegotiation { 537 | var expectedSecureRenegotiation [24]byte 538 | copy(expectedSecureRenegotiation[:], c.clientFinished[:]) 539 | copy(expectedSecureRenegotiation[12:], c.serverFinished[:]) 540 | if !bytes.Equal(hs.serverHello.secureRenegotiation, expectedSecureRenegotiation[:]) { 541 | c.sendAlert(alertHandshakeFailure) 542 | return false, errors.New("tls: incorrect renegotiation extension contents") 543 | } 544 | } 545 | 546 | clientDidNPN := hs.hello.nextProtoNeg 547 | clientDidALPN := len(hs.hello.alpnProtocols) > 0 548 | serverHasNPN := hs.serverHello.nextProtoNeg 549 | serverHasALPN := len(hs.serverHello.alpnProtocol) > 0 550 | 551 | if !clientDidNPN && serverHasNPN { 552 | c.sendAlert(alertHandshakeFailure) 553 | return false, errors.New("tls: server advertised unrequested NPN extension") 554 | } 555 | 556 | if !clientDidALPN && serverHasALPN { 557 | c.sendAlert(alertHandshakeFailure) 558 | return false, errors.New("tls: server advertised unrequested ALPN extension") 559 | } 560 | 561 | if serverHasNPN && serverHasALPN { 562 | c.sendAlert(alertHandshakeFailure) 563 | return false, errors.New("tls: server advertised both NPN and ALPN extensions") 564 | } 565 | 566 | if serverHasALPN { 567 | c.clientProtocol = hs.serverHello.alpnProtocol 568 | c.clientProtocolFallback = false 569 | } 570 | c.scts = hs.serverHello.scts 571 | 572 | if !hs.serverResumedSession() { 573 | return false, nil 574 | } 575 | 576 | if hs.session.vers != c.vers { 577 | c.sendAlert(alertHandshakeFailure) 578 | return false, errors.New("tls: server resumed a session with a different version") 579 | } 580 | 581 | if hs.session.cipherSuite != hs.suite.id { 582 | c.sendAlert(alertHandshakeFailure) 583 | return false, errors.New("tls: server resumed a session with a different cipher suite") 584 | } 585 | 586 | // Restore masterSecret and peerCerts from previous state 587 | hs.masterSecret = hs.session.masterSecret 588 | c.peerCertificates = hs.session.serverCertificates 589 | c.verifiedChains = hs.session.verifiedChains 590 | return true, nil 591 | } 592 | 593 | func (hs *clientHandshakeState) readFinished(out []byte) error { 594 | c := hs.c 595 | 596 | c.readRecord(recordTypeChangeCipherSpec) 597 | if c.in.err != nil { 598 | return c.in.err 599 | } 600 | 601 | msg, err := c.readHandshake() 602 | if err != nil { 603 | return err 604 | } 605 | serverFinished, ok := msg.(*finishedMsg) 606 | if !ok { 607 | c.sendAlert(alertUnexpectedMessage) 608 | return unexpectedMessageError(serverFinished, msg) 609 | } 610 | 611 | verify := hs.finishedHash.serverSum(hs.masterSecret) 612 | if len(verify) != len(serverFinished.verifyData) || 613 | subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 { 614 | c.sendAlert(alertHandshakeFailure) 615 | return errors.New("tls: server's Finished message was incorrect") 616 | } 617 | hs.finishedHash.Write(serverFinished.marshal()) 618 | copy(out, verify) 619 | return nil 620 | } 621 | 622 | func (hs *clientHandshakeState) readSessionTicket() error { 623 | if !hs.serverHello.ticketSupported { 624 | return nil 625 | } 626 | 627 | c := hs.c 628 | msg, err := c.readHandshake() 629 | if err != nil { 630 | return err 631 | } 632 | sessionTicketMsg, ok := msg.(*newSessionTicketMsg) 633 | if !ok { 634 | c.sendAlert(alertUnexpectedMessage) 635 | return unexpectedMessageError(sessionTicketMsg, msg) 636 | } 637 | hs.finishedHash.Write(sessionTicketMsg.marshal()) 638 | 639 | hs.session = &ClientSessionState{ 640 | sessionTicket: sessionTicketMsg.ticket, 641 | vers: c.vers, 642 | cipherSuite: hs.suite.id, 643 | masterSecret: hs.masterSecret, 644 | serverCertificates: c.peerCertificates, 645 | verifiedChains: c.verifiedChains, 646 | } 647 | 648 | return nil 649 | } 650 | 651 | func (hs *clientHandshakeState) sendFinished(out []byte) error { 652 | c := hs.c 653 | 654 | if _, err := c.writeRecord(recordTypeChangeCipherSpec, []byte{1}); err != nil { 655 | return err 656 | } 657 | if hs.serverHello.nextProtoNeg { 658 | nextProto := new(nextProtoMsg) 659 | proto, fallback := mutualProtocol(c.config.NextProtos, hs.serverHello.nextProtos) 660 | nextProto.proto = proto 661 | c.clientProtocol = proto 662 | c.clientProtocolFallback = fallback 663 | 664 | hs.finishedHash.Write(nextProto.marshal()) 665 | if _, err := c.writeRecord(recordTypeHandshake, nextProto.marshal()); err != nil { 666 | return err 667 | } 668 | } 669 | 670 | finished := new(finishedMsg) 671 | finished.verifyData = hs.finishedHash.clientSum(hs.masterSecret) 672 | hs.finishedHash.Write(finished.marshal()) 673 | if _, err := c.writeRecord(recordTypeHandshake, finished.marshal()); err != nil { 674 | return err 675 | } 676 | copy(out, finished.verifyData) 677 | return nil 678 | } 679 | 680 | // tls11SignatureSchemes contains the signature schemes that we synthesise for 681 | // a TLS <= 1.1 connection, based on the supported certificate types. 682 | var tls11SignatureSchemes = []SignatureScheme{ECDSAWithP256AndSHA256, ECDSAWithP384AndSHA384, ECDSAWithP521AndSHA512, PKCS1WithSHA256, PKCS1WithSHA384, PKCS1WithSHA512, PKCS1WithSHA1} 683 | 684 | const ( 685 | // tls11SignatureSchemesNumECDSA is the number of initial elements of 686 | // tls11SignatureSchemes that use ECDSA. 687 | tls11SignatureSchemesNumECDSA = 3 688 | // tls11SignatureSchemesNumRSA is the number of trailing elements of 689 | // tls11SignatureSchemes that use RSA. 690 | tls11SignatureSchemesNumRSA = 4 691 | ) 692 | 693 | func (hs *clientHandshakeState) getCertificate(certReq *certificateRequestMsg) (*Certificate, error) { 694 | c := hs.c 695 | 696 | var rsaAvail, ecdsaAvail bool 697 | for _, certType := range certReq.certificateTypes { 698 | switch certType { 699 | case certTypeRSASign: 700 | rsaAvail = true 701 | case certTypeECDSASign: 702 | ecdsaAvail = true 703 | } 704 | } 705 | 706 | if c.config.GetClientCertificate != nil { 707 | var signatureSchemes []SignatureScheme 708 | 709 | if !certReq.hasSignatureAndHash { 710 | // Prior to TLS 1.2, the signature schemes were not 711 | // included in the certificate request message. In this 712 | // case we use a plausible list based on the acceptable 713 | // certificate types. 714 | signatureSchemes = tls11SignatureSchemes 715 | if !ecdsaAvail { 716 | signatureSchemes = signatureSchemes[tls11SignatureSchemesNumECDSA:] 717 | } 718 | if !rsaAvail { 719 | signatureSchemes = signatureSchemes[:len(signatureSchemes)-tls11SignatureSchemesNumRSA] 720 | } 721 | } else { 722 | signatureSchemes = make([]SignatureScheme, 0, len(certReq.signatureAndHashes)) 723 | for _, sah := range certReq.signatureAndHashes { 724 | signatureSchemes = append(signatureSchemes, SignatureScheme(sah.hash)<<8+SignatureScheme(sah.signature)) 725 | } 726 | } 727 | 728 | return c.config.GetClientCertificate(&CertificateRequestInfo{ 729 | AcceptableCAs: certReq.certificateAuthorities, 730 | SignatureSchemes: signatureSchemes, 731 | }) 732 | } 733 | 734 | // RFC 4346 on the certificateAuthorities field: A list of the 735 | // distinguished names of acceptable certificate authorities. 736 | // These distinguished names may specify a desired 737 | // distinguished name for a root CA or for a subordinate CA; 738 | // thus, this message can be used to describe both known roots 739 | // and a desired authorization space. If the 740 | // certificate_authorities list is empty then the client MAY 741 | // send any certificate of the appropriate 742 | // ClientCertificateType, unless there is some external 743 | // arrangement to the contrary. 744 | 745 | // We need to search our list of client certs for one 746 | // where SignatureAlgorithm is acceptable to the server and the 747 | // Issuer is in certReq.certificateAuthorities 748 | findCert: 749 | for i, chain := range c.config.Certificates { 750 | if !rsaAvail && !ecdsaAvail { 751 | continue 752 | } 753 | 754 | for j, cert := range chain.Certificate { 755 | x509Cert := chain.Leaf 756 | // parse the certificate if this isn't the leaf 757 | // node, or if chain.Leaf was nil 758 | if j != 0 || x509Cert == nil { 759 | var err error 760 | if x509Cert, err = sm2.ParseCertificate(cert); err != nil { 761 | c.sendAlert(alertInternalError) 762 | return nil, errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error()) 763 | } 764 | } 765 | 766 | switch { 767 | case rsaAvail && x509Cert.PublicKeyAlgorithm == sm2.RSA: 768 | case ecdsaAvail && x509Cert.PublicKeyAlgorithm == sm2.ECDSA: 769 | default: 770 | continue findCert 771 | } 772 | 773 | if len(certReq.certificateAuthorities) == 0 { 774 | // they gave us an empty list, so just take the 775 | // first cert from c.config.Certificates 776 | return &chain, nil 777 | } 778 | 779 | for _, ca := range certReq.certificateAuthorities { 780 | if bytes.Equal(x509Cert.RawIssuer, ca) { 781 | return &chain, nil 782 | } 783 | } 784 | } 785 | } 786 | 787 | // No acceptable certificate found. Don't send a certificate. 788 | return new(Certificate), nil 789 | } 790 | 791 | // clientSessionCacheKey returns a key used to cache sessionTickets that could 792 | // be used to resume previously negotiated TLS sessions with a server. 793 | func clientSessionCacheKey(serverAddr net.Addr, config *Config) string { 794 | if len(config.ServerName) > 0 { 795 | return config.ServerName 796 | } 797 | return serverAddr.String() 798 | } 799 | 800 | // mutualProtocol finds the mutual Next Protocol Negotiation or ALPN protocol 801 | // given list of possible protocols and a list of the preference order. The 802 | // first list must not be empty. It returns the resulting protocol and flag 803 | // indicating if the fallback case was reached. 804 | func mutualProtocol(protos, preferenceProtos []string) (string, bool) { 805 | for _, s := range preferenceProtos { 806 | for _, c := range protos { 807 | if s == c { 808 | return s, false 809 | } 810 | } 811 | } 812 | 813 | return protos[0], true 814 | } 815 | 816 | // hostnameInSNI converts name into an approriate hostname for SNI. 817 | // Literal IP addresses and absolute FQDNs are not permitted as SNI values. 818 | // See https://tools.ietf.org/html/rfc6066#section-3. 819 | func hostnameInSNI(name string) string { 820 | host := name 821 | if len(host) > 0 && host[0] == '[' && host[len(host)-1] == ']' { 822 | host = host[1 : len(host)-1] 823 | } 824 | if i := strings.LastIndex(host, "%"); i > 0 { 825 | host = host[:i] 826 | } 827 | if net.ParseIP(host) != nil { 828 | return "" 829 | } 830 | if len(name) > 0 && name[len(name)-1] == '.' { 831 | name = name[:len(name)-1] 832 | } 833 | return name 834 | } 835 | -------------------------------------------------------------------------------- /handshake_server.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | 16 | package gmtls 17 | 18 | import ( 19 | "crypto" 20 | "crypto/ecdsa" 21 | "crypto/rsa" 22 | "crypto/subtle" 23 | "encoding/asn1" 24 | "errors" 25 | "fmt" 26 | "io" 27 | 28 | "github.com/tjfoc/gmsm/sm2" 29 | ) 30 | 31 | // serverHandshakeState contains details of a server handshake in progress. 32 | // It's discarded once the handshake has completed. 33 | type serverHandshakeState struct { 34 | c *Conn 35 | clientHello *clientHelloMsg 36 | hello *serverHelloMsg 37 | suite *cipherSuite 38 | ellipticOk bool 39 | ecdsaOk bool 40 | rsaDecryptOk bool 41 | rsaSignOk bool 42 | sessionState *sessionState 43 | finishedHash finishedHash 44 | masterSecret []byte 45 | certsFromClient [][]byte 46 | cert *Certificate 47 | cachedClientHelloInfo *ClientHelloInfo 48 | } 49 | 50 | // serverHandshake performs a TLS handshake as a server. 51 | // c.out.Mutex <= L; c.handshakeMutex <= L. 52 | func (c *Conn) serverHandshake() error { 53 | // If this is the first server handshake, we generate a random key to 54 | // encrypt the tickets with. 55 | c.config.serverInitOnce.Do(c.config.serverInit) 56 | 57 | hs := serverHandshakeState{ 58 | c: c, 59 | } 60 | isResume, err := hs.readClientHello() 61 | if err != nil { 62 | return err 63 | } 64 | 65 | // For an overview of TLS handshaking, see https://tools.ietf.org/html/rfc5246#section-7.3 66 | c.buffering = true 67 | if isResume { 68 | // The client has included a session ticket and so we do an abbreviated handshake. 69 | if err := hs.doResumeHandshake(); err != nil { 70 | return err 71 | } 72 | if err := hs.establishKeys(); err != nil { 73 | return err 74 | } 75 | // ticketSupported is set in a resumption handshake if the 76 | // ticket from the client was encrypted with an old session 77 | // ticket key and thus a refreshed ticket should be sent. 78 | if hs.hello.ticketSupported { 79 | if err := hs.sendSessionTicket(); err != nil { 80 | return err 81 | } 82 | } 83 | if err := hs.sendFinished(c.serverFinished[:]); err != nil { 84 | return err 85 | } 86 | if _, err := c.flush(); err != nil { 87 | return err 88 | } 89 | c.clientFinishedIsFirst = false 90 | if err := hs.readFinished(nil); err != nil { 91 | return err 92 | } 93 | c.didResume = true 94 | } else { 95 | // The client didn't include a session ticket, or it wasn't 96 | // valid so we do a full handshake. 97 | if err := hs.doFullHandshake(); err != nil { 98 | return err 99 | } 100 | if err := hs.establishKeys(); err != nil { 101 | return err 102 | } 103 | if err := hs.readFinished(c.clientFinished[:]); err != nil { 104 | return err 105 | } 106 | c.clientFinishedIsFirst = true 107 | c.buffering = true 108 | if err := hs.sendSessionTicket(); err != nil { 109 | return err 110 | } 111 | if err := hs.sendFinished(nil); err != nil { 112 | return err 113 | } 114 | if _, err := c.flush(); err != nil { 115 | return err 116 | } 117 | } 118 | c.handshakeComplete = true 119 | 120 | return nil 121 | } 122 | 123 | // readClientHello reads a ClientHello message from the client and decides 124 | // whether we will perform session resumption. 125 | func (hs *serverHandshakeState) readClientHello() (isResume bool, err error) { 126 | c := hs.c 127 | 128 | msg, err := c.readHandshake() 129 | if err != nil { 130 | return false, err 131 | } 132 | var ok bool 133 | hs.clientHello, ok = msg.(*clientHelloMsg) 134 | if !ok { 135 | c.sendAlert(alertUnexpectedMessage) 136 | return false, unexpectedMessageError(hs.clientHello, msg) 137 | } 138 | 139 | if c.config.GetConfigForClient != nil { 140 | if newConfig, err := c.config.GetConfigForClient(hs.clientHelloInfo()); err != nil { 141 | c.sendAlert(alertInternalError) 142 | return false, err 143 | } else if newConfig != nil { 144 | newConfig.mutex.Lock() 145 | newConfig.originalConfig = c.config 146 | newConfig.mutex.Unlock() 147 | 148 | newConfig.serverInitOnce.Do(newConfig.serverInit) 149 | c.config = newConfig 150 | } 151 | } 152 | 153 | c.vers, ok = c.config.mutualVersion(hs.clientHello.vers) 154 | if !ok { 155 | c.sendAlert(alertProtocolVersion) 156 | return false, fmt.Errorf("tls: client offered an unsupported, maximum protocol version of %x", hs.clientHello.vers) 157 | } 158 | c.haveVers = true 159 | 160 | hs.hello = new(serverHelloMsg) 161 | 162 | supportedCurve := false 163 | preferredCurves := c.config.curvePreferences() 164 | Curves: 165 | for _, curve := range hs.clientHello.supportedCurves { 166 | for _, supported := range preferredCurves { 167 | if supported == curve { 168 | supportedCurve = true 169 | break Curves 170 | } 171 | } 172 | } 173 | 174 | supportedPointFormat := false 175 | for _, pointFormat := range hs.clientHello.supportedPoints { 176 | if pointFormat == pointFormatUncompressed { 177 | supportedPointFormat = true 178 | break 179 | } 180 | } 181 | hs.ellipticOk = supportedCurve && supportedPointFormat 182 | 183 | foundCompression := false 184 | // We only support null compression, so check that the client offered it. 185 | for _, compression := range hs.clientHello.compressionMethods { 186 | if compression == compressionNone { 187 | foundCompression = true 188 | break 189 | } 190 | } 191 | 192 | if !foundCompression { 193 | c.sendAlert(alertHandshakeFailure) 194 | return false, errors.New("tls: client does not support uncompressed connections") 195 | } 196 | 197 | hs.hello.vers = c.vers 198 | hs.hello.random = make([]byte, 32) 199 | _, err = io.ReadFull(c.config.rand(), hs.hello.random) 200 | if err != nil { 201 | c.sendAlert(alertInternalError) 202 | return false, err 203 | } 204 | 205 | if len(hs.clientHello.secureRenegotiation) != 0 { 206 | c.sendAlert(alertHandshakeFailure) 207 | return false, errors.New("tls: initial handshake had non-empty renegotiation extension") 208 | } 209 | 210 | hs.hello.secureRenegotiationSupported = hs.clientHello.secureRenegotiationSupported 211 | hs.hello.compressionMethod = compressionNone 212 | if len(hs.clientHello.serverName) > 0 { 213 | c.serverName = hs.clientHello.serverName 214 | } 215 | 216 | if len(hs.clientHello.alpnProtocols) > 0 { 217 | if selectedProto, fallback := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos); !fallback { 218 | hs.hello.alpnProtocol = selectedProto 219 | c.clientProtocol = selectedProto 220 | } 221 | } else { 222 | // Although sending an empty NPN extension is reasonable, Firefox has 223 | // had a bug around this. Best to send nothing at all if 224 | // c.config.NextProtos is empty. See 225 | // https://golang.org/issue/5445. 226 | if hs.clientHello.nextProtoNeg && len(c.config.NextProtos) > 0 { 227 | hs.hello.nextProtoNeg = true 228 | hs.hello.nextProtos = c.config.NextProtos 229 | } 230 | } 231 | 232 | hs.cert, err = c.config.getCertificate(hs.clientHelloInfo()) 233 | if err != nil { 234 | c.sendAlert(alertInternalError) 235 | return false, err 236 | } 237 | if hs.clientHello.scts { 238 | hs.hello.scts = hs.cert.SignedCertificateTimestamps 239 | } 240 | 241 | if priv, ok := hs.cert.PrivateKey.(crypto.Signer); ok { 242 | switch priv.Public().(type) { 243 | case *ecdsa.PublicKey: 244 | hs.ecdsaOk = true 245 | case *rsa.PublicKey: 246 | hs.rsaSignOk = true 247 | case *sm2.PublicKey: 248 | hs.ecdsaOk = true 249 | default: 250 | c.sendAlert(alertInternalError) 251 | return false, fmt.Errorf("tls: unsupported signing key type (%T)", priv.Public()) 252 | } 253 | } 254 | if priv, ok := hs.cert.PrivateKey.(crypto.Decrypter); ok { 255 | switch priv.Public().(type) { 256 | case *rsa.PublicKey: 257 | hs.rsaDecryptOk = true 258 | default: 259 | c.sendAlert(alertInternalError) 260 | return false, fmt.Errorf("tls: unsupported decryption key type (%T)", priv.Public()) 261 | } 262 | } 263 | 264 | if hs.checkForResumption() { 265 | return true, nil 266 | } 267 | 268 | var preferenceList, supportedList []uint16 269 | if c.config.PreferServerCipherSuites { 270 | preferenceList = c.config.cipherSuites() 271 | supportedList = hs.clientHello.cipherSuites 272 | } else { 273 | preferenceList = hs.clientHello.cipherSuites 274 | supportedList = c.config.cipherSuites() 275 | } 276 | 277 | for _, id := range preferenceList { 278 | if hs.setCipherSuite(id, supportedList, c.vers) { 279 | break 280 | } 281 | } 282 | 283 | if hs.suite == nil { 284 | c.sendAlert(alertHandshakeFailure) 285 | return false, errors.New("tls: no cipher suite supported by both client and server") 286 | } 287 | 288 | // See https://tools.ietf.org/html/rfc7507. 289 | for _, id := range hs.clientHello.cipherSuites { 290 | if id == TLS_FALLBACK_SCSV { 291 | // The client is doing a fallback connection. 292 | if hs.clientHello.vers < c.config.maxVersion() { 293 | c.sendAlert(alertInappropriateFallback) 294 | return false, errors.New("tls: client using inappropriate protocol fallback") 295 | } 296 | break 297 | } 298 | } 299 | 300 | return false, nil 301 | } 302 | 303 | // checkForResumption reports whether we should perform resumption on this connection. 304 | func (hs *serverHandshakeState) checkForResumption() bool { 305 | c := hs.c 306 | 307 | if c.config.SessionTicketsDisabled { 308 | return false 309 | } 310 | 311 | var ok bool 312 | var sessionTicket = append([]uint8{}, hs.clientHello.sessionTicket...) 313 | if hs.sessionState, ok = c.decryptTicket(sessionTicket); !ok { 314 | return false 315 | } 316 | 317 | // Never resume a session for a different TLS version. 318 | if c.vers != hs.sessionState.vers { 319 | return false 320 | } 321 | 322 | cipherSuiteOk := false 323 | // Check that the client is still offering the ciphersuite in the session. 324 | for _, id := range hs.clientHello.cipherSuites { 325 | if id == hs.sessionState.cipherSuite { 326 | cipherSuiteOk = true 327 | break 328 | } 329 | } 330 | if !cipherSuiteOk { 331 | return false 332 | } 333 | 334 | // Check that we also support the ciphersuite from the session. 335 | if !hs.setCipherSuite(hs.sessionState.cipherSuite, c.config.cipherSuites(), hs.sessionState.vers) { 336 | return false 337 | } 338 | 339 | sessionHasClientCerts := len(hs.sessionState.certificates) != 0 340 | needClientCerts := c.config.ClientAuth == RequireAnyClientCert || c.config.ClientAuth == RequireAndVerifyClientCert 341 | if needClientCerts && !sessionHasClientCerts { 342 | return false 343 | } 344 | if sessionHasClientCerts && c.config.ClientAuth == NoClientCert { 345 | return false 346 | } 347 | 348 | return true 349 | } 350 | 351 | func (hs *serverHandshakeState) doResumeHandshake() error { 352 | c := hs.c 353 | 354 | hs.hello.cipherSuite = hs.suite.id 355 | // We echo the client's session ID in the ServerHello to let it know 356 | // that we're doing a resumption. 357 | hs.hello.sessionId = hs.clientHello.sessionId 358 | hs.hello.ticketSupported = hs.sessionState.usedOldKey 359 | hs.finishedHash = newFinishedHash(c.vers, hs.suite) 360 | hs.finishedHash.discardHandshakeBuffer() 361 | hs.finishedHash.Write(hs.clientHello.marshal()) 362 | hs.finishedHash.Write(hs.hello.marshal()) 363 | if _, err := c.writeRecord(recordTypeHandshake, hs.hello.marshal()); err != nil { 364 | return err 365 | } 366 | 367 | if len(hs.sessionState.certificates) > 0 { 368 | if _, err := hs.processCertsFromClient(hs.sessionState.certificates); err != nil { 369 | return err 370 | } 371 | } 372 | 373 | hs.masterSecret = hs.sessionState.masterSecret 374 | 375 | return nil 376 | } 377 | 378 | func (hs *serverHandshakeState) doFullHandshake() error { 379 | c := hs.c 380 | 381 | if hs.clientHello.ocspStapling && len(hs.cert.OCSPStaple) > 0 { 382 | hs.hello.ocspStapling = true 383 | } 384 | 385 | hs.hello.ticketSupported = hs.clientHello.ticketSupported && !c.config.SessionTicketsDisabled 386 | hs.hello.cipherSuite = hs.suite.id 387 | 388 | hs.finishedHash = newFinishedHash(hs.c.vers, hs.suite) 389 | if c.config.ClientAuth == NoClientCert { 390 | // No need to keep a full record of the handshake if client 391 | // certificates won't be used. 392 | hs.finishedHash.discardHandshakeBuffer() 393 | } 394 | hs.finishedHash.Write(hs.clientHello.marshal()) 395 | hs.finishedHash.Write(hs.hello.marshal()) 396 | if _, err := c.writeRecord(recordTypeHandshake, hs.hello.marshal()); err != nil { 397 | return err 398 | } 399 | 400 | certMsg := new(certificateMsg) 401 | certMsg.certificates = hs.cert.Certificate 402 | hs.finishedHash.Write(certMsg.marshal()) 403 | if _, err := c.writeRecord(recordTypeHandshake, certMsg.marshal()); err != nil { 404 | return err 405 | } 406 | 407 | if hs.hello.ocspStapling { 408 | certStatus := new(certificateStatusMsg) 409 | certStatus.statusType = statusTypeOCSP 410 | certStatus.response = hs.cert.OCSPStaple 411 | hs.finishedHash.Write(certStatus.marshal()) 412 | if _, err := c.writeRecord(recordTypeHandshake, certStatus.marshal()); err != nil { 413 | return err 414 | } 415 | } 416 | 417 | keyAgreement := hs.suite.ka(c.vers) 418 | skx, err := keyAgreement.generateServerKeyExchange(c.config, hs.cert, hs.clientHello, hs.hello) 419 | if err != nil { 420 | c.sendAlert(alertHandshakeFailure) 421 | return err 422 | } 423 | if skx != nil { 424 | hs.finishedHash.Write(skx.marshal()) 425 | if _, err := c.writeRecord(recordTypeHandshake, skx.marshal()); err != nil { 426 | return err 427 | } 428 | } 429 | 430 | if c.config.ClientAuth >= RequestClientCert { 431 | // Request a client certificate 432 | certReq := new(certificateRequestMsg) 433 | certReq.certificateTypes = []byte{ 434 | byte(certTypeRSASign), 435 | byte(certTypeECDSASign), 436 | } 437 | if c.vers >= VersionTLS12 { 438 | certReq.hasSignatureAndHash = true 439 | certReq.signatureAndHashes = supportedSignatureAlgorithms 440 | } 441 | 442 | // An empty list of certificateAuthorities signals to 443 | // the client that it may send any certificate in response 444 | // to our request. When we know the CAs we trust, then 445 | // we can send them down, so that the client can choose 446 | // an appropriate certificate to give to us. 447 | if c.config.ClientCAs != nil { 448 | certReq.certificateAuthorities = c.config.ClientCAs.Subjects() 449 | } 450 | hs.finishedHash.Write(certReq.marshal()) 451 | if _, err := c.writeRecord(recordTypeHandshake, certReq.marshal()); err != nil { 452 | return err 453 | } 454 | } 455 | 456 | helloDone := new(serverHelloDoneMsg) 457 | hs.finishedHash.Write(helloDone.marshal()) 458 | if _, err := c.writeRecord(recordTypeHandshake, helloDone.marshal()); err != nil { 459 | return err 460 | } 461 | 462 | if _, err := c.flush(); err != nil { 463 | return err 464 | } 465 | 466 | var pub crypto.PublicKey // public key for client auth, if any 467 | 468 | msg, err := c.readHandshake() 469 | if err != nil { 470 | return err 471 | } 472 | 473 | var ok bool 474 | // If we requested a client certificate, then the client must send a 475 | // certificate message, even if it's empty. 476 | if c.config.ClientAuth >= RequestClientCert { 477 | if certMsg, ok = msg.(*certificateMsg); !ok { 478 | c.sendAlert(alertUnexpectedMessage) 479 | return unexpectedMessageError(certMsg, msg) 480 | } 481 | hs.finishedHash.Write(certMsg.marshal()) 482 | 483 | if len(certMsg.certificates) == 0 { 484 | // The client didn't actually send a certificate 485 | switch c.config.ClientAuth { 486 | case RequireAnyClientCert, RequireAndVerifyClientCert: 487 | c.sendAlert(alertBadCertificate) 488 | return errors.New("tls: client didn't provide a certificate") 489 | } 490 | } 491 | 492 | pub, err = hs.processCertsFromClient(certMsg.certificates) 493 | if err != nil { 494 | return err 495 | } 496 | 497 | msg, err = c.readHandshake() 498 | if err != nil { 499 | return err 500 | } 501 | } 502 | 503 | // Get client key exchange 504 | ckx, ok := msg.(*clientKeyExchangeMsg) 505 | if !ok { 506 | c.sendAlert(alertUnexpectedMessage) 507 | return unexpectedMessageError(ckx, msg) 508 | } 509 | hs.finishedHash.Write(ckx.marshal()) 510 | 511 | preMasterSecret, err := keyAgreement.processClientKeyExchange(c.config, hs.cert, ckx, c.vers) 512 | if err != nil { 513 | c.sendAlert(alertHandshakeFailure) 514 | return err 515 | } 516 | hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.clientHello.random, hs.hello.random) 517 | if err := c.config.writeKeyLog(hs.clientHello.random, hs.masterSecret); err != nil { 518 | c.sendAlert(alertInternalError) 519 | return err 520 | } 521 | 522 | // If we received a client cert in response to our certificate request message, 523 | // the client will send us a certificateVerifyMsg immediately after the 524 | // clientKeyExchangeMsg. This message is a digest of all preceding 525 | // handshake-layer messages that is signed using the private key corresponding 526 | // to the client's certificate. This allows us to verify that the client is in 527 | // possession of the private key of the certificate. 528 | if len(c.peerCertificates) > 0 { 529 | msg, err = c.readHandshake() 530 | if err != nil { 531 | return err 532 | } 533 | certVerify, ok := msg.(*certificateVerifyMsg) 534 | if !ok { 535 | c.sendAlert(alertUnexpectedMessage) 536 | return unexpectedMessageError(certVerify, msg) 537 | } 538 | 539 | // Determine the signature type. 540 | var signatureAndHash signatureAndHash 541 | if certVerify.hasSignatureAndHash { 542 | signatureAndHash = certVerify.signatureAndHash 543 | if !isSupportedSignatureAndHash(signatureAndHash, supportedSignatureAlgorithms) { 544 | return errors.New("tls: unsupported hash function for client certificate") 545 | } 546 | } else { 547 | // Before TLS 1.2 the signature algorithm was implicit 548 | // from the key type, and only one hash per signature 549 | // algorithm was possible. Leave the hash as zero. 550 | switch pub.(type) { 551 | case *ecdsa.PublicKey: 552 | signatureAndHash.signature = signatureECDSA 553 | case *rsa.PublicKey: 554 | signatureAndHash.signature = signatureRSA 555 | } 556 | } 557 | 558 | switch key := pub.(type) { 559 | case *ecdsa.PublicKey: 560 | if signatureAndHash.signature != signatureECDSA { 561 | err = errors.New("tls: bad signature type for client's ECDSA certificate") 562 | break 563 | } 564 | ecdsaSig := new(ecdsaSignature) 565 | if _, err = asn1.Unmarshal(certVerify.signature, ecdsaSig); err != nil { 566 | break 567 | } 568 | if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 { 569 | err = errors.New("tls: ECDSA signature contained zero or negative values") 570 | break 571 | } 572 | var digest []byte 573 | if digest, _, err = hs.finishedHash.hashForClientCertificate(signatureAndHash, hs.masterSecret); err != nil { 574 | break 575 | } 576 | switch key.Curve { 577 | case sm2.P256Sm2(): 578 | if !sm2.Verify(&sm2.PublicKey{ 579 | X: key.X, 580 | Y: key.Y, 581 | Curve: key.Curve, 582 | }, digest, ecdsaSig.R, ecdsaSig.S) { 583 | err = errors.New("tls: SM2 verification failure") 584 | } 585 | default: 586 | if !ecdsa.Verify(key, digest, ecdsaSig.R, ecdsaSig.S) { 587 | err = errors.New("tls: ECDSA verification failure") 588 | } 589 | } 590 | case *rsa.PublicKey: 591 | if signatureAndHash.signature != signatureRSA { 592 | err = errors.New("tls: bad signature type for client's RSA certificate") 593 | break 594 | } 595 | var digest []byte 596 | var hashFunc crypto.Hash 597 | if digest, hashFunc, err = hs.finishedHash.hashForClientCertificate(signatureAndHash, hs.masterSecret); err != nil { 598 | break 599 | } 600 | err = rsa.VerifyPKCS1v15(key, hashFunc, digest, certVerify.signature) 601 | } 602 | if err != nil { 603 | c.sendAlert(alertBadCertificate) 604 | return errors.New("tls: could not validate signature of connection nonces: " + err.Error()) 605 | } 606 | 607 | hs.finishedHash.Write(certVerify.marshal()) 608 | } 609 | 610 | hs.finishedHash.discardHandshakeBuffer() 611 | 612 | return nil 613 | } 614 | 615 | func (hs *serverHandshakeState) establishKeys() error { 616 | c := hs.c 617 | 618 | clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV := 619 | keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.clientHello.random, hs.hello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen) 620 | 621 | var clientCipher, serverCipher interface{} 622 | var clientHash, serverHash macFunction 623 | 624 | if hs.suite.aead == nil { 625 | clientCipher = hs.suite.cipher(clientKey, clientIV, true /* for reading */) 626 | clientHash = hs.suite.mac(c.vers, clientMAC) 627 | serverCipher = hs.suite.cipher(serverKey, serverIV, false /* not for reading */) 628 | serverHash = hs.suite.mac(c.vers, serverMAC) 629 | } else { 630 | clientCipher = hs.suite.aead(clientKey, clientIV) 631 | serverCipher = hs.suite.aead(serverKey, serverIV) 632 | } 633 | 634 | c.in.prepareCipherSpec(c.vers, clientCipher, clientHash) 635 | c.out.prepareCipherSpec(c.vers, serverCipher, serverHash) 636 | 637 | return nil 638 | } 639 | 640 | func (hs *serverHandshakeState) readFinished(out []byte) error { 641 | c := hs.c 642 | 643 | c.readRecord(recordTypeChangeCipherSpec) 644 | if c.in.err != nil { 645 | return c.in.err 646 | } 647 | 648 | if hs.hello.nextProtoNeg { 649 | msg, err := c.readHandshake() 650 | if err != nil { 651 | return err 652 | } 653 | nextProto, ok := msg.(*nextProtoMsg) 654 | if !ok { 655 | c.sendAlert(alertUnexpectedMessage) 656 | return unexpectedMessageError(nextProto, msg) 657 | } 658 | hs.finishedHash.Write(nextProto.marshal()) 659 | c.clientProtocol = nextProto.proto 660 | } 661 | 662 | msg, err := c.readHandshake() 663 | if err != nil { 664 | return err 665 | } 666 | clientFinished, ok := msg.(*finishedMsg) 667 | if !ok { 668 | c.sendAlert(alertUnexpectedMessage) 669 | return unexpectedMessageError(clientFinished, msg) 670 | } 671 | 672 | verify := hs.finishedHash.clientSum(hs.masterSecret) 673 | if len(verify) != len(clientFinished.verifyData) || 674 | subtle.ConstantTimeCompare(verify, clientFinished.verifyData) != 1 { 675 | c.sendAlert(alertHandshakeFailure) 676 | return errors.New("tls: client's Finished message is incorrect") 677 | } 678 | 679 | hs.finishedHash.Write(clientFinished.marshal()) 680 | copy(out, verify) 681 | return nil 682 | } 683 | 684 | func (hs *serverHandshakeState) sendSessionTicket() error { 685 | if !hs.hello.ticketSupported { 686 | return nil 687 | } 688 | 689 | c := hs.c 690 | m := new(newSessionTicketMsg) 691 | 692 | var err error 693 | state := sessionState{ 694 | vers: c.vers, 695 | cipherSuite: hs.suite.id, 696 | masterSecret: hs.masterSecret, 697 | certificates: hs.certsFromClient, 698 | } 699 | m.ticket, err = c.encryptTicket(&state) 700 | if err != nil { 701 | return err 702 | } 703 | 704 | hs.finishedHash.Write(m.marshal()) 705 | if _, err := c.writeRecord(recordTypeHandshake, m.marshal()); err != nil { 706 | return err 707 | } 708 | 709 | return nil 710 | } 711 | 712 | func (hs *serverHandshakeState) sendFinished(out []byte) error { 713 | c := hs.c 714 | 715 | if _, err := c.writeRecord(recordTypeChangeCipherSpec, []byte{1}); err != nil { 716 | return err 717 | } 718 | 719 | finished := new(finishedMsg) 720 | finished.verifyData = hs.finishedHash.serverSum(hs.masterSecret) 721 | hs.finishedHash.Write(finished.marshal()) 722 | if _, err := c.writeRecord(recordTypeHandshake, finished.marshal()); err != nil { 723 | return err 724 | } 725 | 726 | c.cipherSuite = hs.suite.id 727 | copy(out, finished.verifyData) 728 | 729 | return nil 730 | } 731 | 732 | // processCertsFromClient takes a chain of client certificates either from a 733 | // Certificates message or from a sessionState and verifies them. It returns 734 | // the public key of the leaf certificate. 735 | func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (crypto.PublicKey, error) { 736 | c := hs.c 737 | 738 | hs.certsFromClient = certificates 739 | certs := make([]*sm2.Certificate, len(certificates)) 740 | var err error 741 | for i, asn1Data := range certificates { 742 | if certs[i], err = sm2.ParseCertificate(asn1Data); err != nil { 743 | c.sendAlert(alertBadCertificate) 744 | return nil, errors.New("tls: failed to parse client certificate: " + err.Error()) 745 | } 746 | } 747 | 748 | if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 { 749 | opts := sm2.VerifyOptions{ 750 | Roots: c.config.ClientCAs, 751 | CurrentTime: c.config.time(), 752 | Intermediates: sm2.NewCertPool(), 753 | KeyUsages: []sm2.ExtKeyUsage{sm2.ExtKeyUsageClientAuth}, 754 | } 755 | 756 | for _, cert := range certs[1:] { 757 | opts.Intermediates.AddCert(cert) 758 | } 759 | 760 | chains, err := certs[0].Verify(opts) 761 | if err != nil { 762 | c.sendAlert(alertBadCertificate) 763 | return nil, errors.New("tls: failed to verify client's certificate: " + err.Error()) 764 | } 765 | 766 | c.verifiedChains = chains 767 | } 768 | 769 | if c.config.VerifyPeerCertificate != nil { 770 | if err := c.config.VerifyPeerCertificate(certificates, c.verifiedChains); err != nil { 771 | c.sendAlert(alertBadCertificate) 772 | return nil, err 773 | } 774 | } 775 | 776 | if len(certs) == 0 { 777 | return nil, nil 778 | } 779 | 780 | var pub crypto.PublicKey 781 | switch key := certs[0].PublicKey.(type) { 782 | case *ecdsa.PublicKey, *rsa.PublicKey: 783 | pub = key 784 | default: 785 | c.sendAlert(alertUnsupportedCertificate) 786 | return nil, fmt.Errorf("tls: client's certificate contains an unsupported public key of type %T", certs[0].PublicKey) 787 | } 788 | c.peerCertificates = certs 789 | return pub, nil 790 | } 791 | 792 | // setCipherSuite sets a cipherSuite with the given id as the serverHandshakeState 793 | // suite if that cipher suite is acceptable to use. 794 | // It returns a bool indicating if the suite was set. 795 | func (hs *serverHandshakeState) setCipherSuite(id uint16, supportedCipherSuites []uint16, version uint16) bool { 796 | for _, supported := range supportedCipherSuites { 797 | if id == supported { 798 | var candidate *cipherSuite 799 | 800 | for _, s := range cipherSuites { 801 | if s.id == id { 802 | candidate = s 803 | break 804 | } 805 | } 806 | if candidate == nil { 807 | continue 808 | } 809 | // Don't select a ciphersuite which we can't 810 | // support for this client. 811 | if candidate.flags&suiteECDHE != 0 { 812 | if !hs.ellipticOk { 813 | continue 814 | } 815 | if candidate.flags&suiteECDSA != 0 { 816 | if !hs.ecdsaOk { 817 | continue 818 | } 819 | } else if !hs.rsaSignOk { 820 | continue 821 | } 822 | } else if !hs.rsaDecryptOk { 823 | continue 824 | } 825 | if version < VersionTLS12 && candidate.flags&suiteTLS12 != 0 { 826 | continue 827 | } 828 | hs.suite = candidate 829 | return true 830 | } 831 | } 832 | return false 833 | } 834 | 835 | // suppVersArray is the backing array of ClientHelloInfo.SupportedVersions 836 | var suppVersArray = [...]uint16{VersionTLS12, VersionTLS11, VersionTLS10, VersionSSL30} 837 | 838 | func (hs *serverHandshakeState) clientHelloInfo() *ClientHelloInfo { 839 | if hs.cachedClientHelloInfo != nil { 840 | return hs.cachedClientHelloInfo 841 | } 842 | 843 | var supportedVersions []uint16 844 | if hs.clientHello.vers > VersionTLS12 { 845 | supportedVersions = suppVersArray[:] 846 | } else if hs.clientHello.vers >= VersionSSL30 { 847 | supportedVersions = suppVersArray[VersionTLS12-hs.clientHello.vers:] 848 | } 849 | 850 | signatureSchemes := make([]SignatureScheme, 0, len(hs.clientHello.signatureAndHashes)) 851 | for _, sah := range hs.clientHello.signatureAndHashes { 852 | signatureSchemes = append(signatureSchemes, SignatureScheme(sah.hash)<<8+SignatureScheme(sah.signature)) 853 | } 854 | 855 | hs.cachedClientHelloInfo = &ClientHelloInfo{ 856 | CipherSuites: hs.clientHello.cipherSuites, 857 | ServerName: hs.clientHello.serverName, 858 | SupportedCurves: hs.clientHello.supportedCurves, 859 | SupportedPoints: hs.clientHello.supportedPoints, 860 | SignatureSchemes: signatureSchemes, 861 | SupportedProtos: hs.clientHello.alpnProtocols, 862 | SupportedVersions: supportedVersions, 863 | Conn: hs.c.conn, 864 | } 865 | 866 | return hs.cachedClientHelloInfo 867 | } 868 | -------------------------------------------------------------------------------- /common.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | 16 | package gmtls 17 | 18 | import ( 19 | "container/list" 20 | "crypto" 21 | "crypto/rand" 22 | "crypto/sha512" 23 | "errors" 24 | "fmt" 25 | "io" 26 | "math/big" 27 | "net" 28 | "strings" 29 | "sync" 30 | "time" 31 | 32 | "github.com/tjfoc/gmsm/sm2" 33 | ) 34 | 35 | const ( 36 | VersionSSL30 = 0x0300 37 | VersionTLS10 = 0x0301 38 | VersionTLS11 = 0x0302 39 | VersionTLS12 = 0x0303 40 | ) 41 | 42 | const ( 43 | maxPlaintext = 16384 // maximum plaintext payload length 44 | maxCiphertext = 16384 + 2048 // maximum ciphertext payload length 45 | recordHeaderLen = 5 // record header length 46 | maxHandshake = 65536 // maximum handshake we support (protocol max is 16 MB) 47 | 48 | minVersion = VersionTLS10 49 | maxVersion = VersionTLS12 50 | ) 51 | 52 | // TLS record types. 53 | type recordType uint8 54 | 55 | const ( 56 | recordTypeChangeCipherSpec recordType = 20 57 | recordTypeAlert recordType = 21 58 | recordTypeHandshake recordType = 22 59 | recordTypeApplicationData recordType = 23 60 | ) 61 | 62 | // TLS handshake message types. 63 | const ( 64 | typeHelloRequest uint8 = 0 65 | typeClientHello uint8 = 1 66 | typeServerHello uint8 = 2 67 | typeNewSessionTicket uint8 = 4 68 | typeCertificate uint8 = 11 69 | typeServerKeyExchange uint8 = 12 70 | typeCertificateRequest uint8 = 13 71 | typeServerHelloDone uint8 = 14 72 | typeCertificateVerify uint8 = 15 73 | typeClientKeyExchange uint8 = 16 74 | typeFinished uint8 = 20 75 | typeCertificateStatus uint8 = 22 76 | typeNextProtocol uint8 = 67 // Not IANA assigned 77 | ) 78 | 79 | // TLS compression types. 80 | const ( 81 | compressionNone uint8 = 0 82 | ) 83 | 84 | // TLS extension numbers 85 | const ( 86 | extensionServerName uint16 = 0 87 | extensionStatusRequest uint16 = 5 88 | extensionSupportedCurves uint16 = 10 89 | extensionSupportedPoints uint16 = 11 90 | extensionSignatureAlgorithms uint16 = 13 91 | extensionALPN uint16 = 16 92 | extensionSCT uint16 = 18 // https://tools.ietf.org/html/rfc6962#section-6 93 | extensionSessionTicket uint16 = 35 94 | extensionNextProtoNeg uint16 = 13172 // not IANA assigned 95 | extensionRenegotiationInfo uint16 = 0xff01 96 | ) 97 | 98 | // TLS signaling cipher suite values 99 | const ( 100 | scsvRenegotiation uint16 = 0x00ff 101 | ) 102 | 103 | // CurveID is the type of a TLS identifier for an elliptic curve. See 104 | // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8 105 | type CurveID uint16 106 | 107 | const ( 108 | CurveP256 CurveID = 23 109 | CurveP384 CurveID = 24 110 | CurveP521 CurveID = 25 111 | X25519 CurveID = 29 112 | CureP256SM2 CurveID = 31 113 | ) 114 | 115 | // TLS Elliptic Curve Point Formats 116 | // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-9 117 | const ( 118 | pointFormatUncompressed uint8 = 0 119 | ) 120 | 121 | // TLS CertificateStatusType (RFC 3546) 122 | const ( 123 | statusTypeOCSP uint8 = 1 124 | ) 125 | 126 | // Certificate types (for certificateRequestMsg) 127 | const ( 128 | certTypeRSASign = 1 // A certificate containing an RSA key 129 | certTypeDSSSign = 2 // A certificate containing a DSA key 130 | certTypeRSAFixedDH = 3 // A certificate containing a static DH key 131 | certTypeDSSFixedDH = 4 // A certificate containing a static DH key 132 | 133 | // See RFC 4492 sections 3 and 5.5. 134 | certTypeECDSASign = 64 // A certificate containing an ECDSA-capable public key, signed with ECDSA. 135 | certTypeRSAFixedECDH = 65 // A certificate containing an ECDH-capable public key, signed with RSA. 136 | certTypeECDSAFixedECDH = 66 // A certificate containing an ECDH-capable public key, signed with ECDSA. 137 | 138 | // Rest of these are reserved by the TLS spec 139 | ) 140 | 141 | // Hash functions for TLS 1.2 (See RFC 5246, section A.4.1) 142 | const ( 143 | hashSHA1 uint8 = 2 144 | hashSHA256 uint8 = 4 145 | hashSHA384 uint8 = 5 146 | ) 147 | 148 | // Signature algorithms for TLS 1.2 (See RFC 5246, section A.4.1) 149 | const ( 150 | signatureRSA uint8 = 1 151 | signatureECDSA uint8 = 3 152 | ) 153 | 154 | // signatureAndHash mirrors the TLS 1.2, SignatureAndHashAlgorithm struct. See 155 | // RFC 5246, section A.4.1. 156 | type signatureAndHash struct { 157 | hash, signature uint8 158 | } 159 | 160 | // supportedSignatureAlgorithms contains the signature and hash algorithms that 161 | // the code advertises as supported in a TLS 1.2 ClientHello and in a TLS 1.2 162 | // CertificateRequest. 163 | var supportedSignatureAlgorithms = []signatureAndHash{ 164 | {hashSHA256, signatureRSA}, 165 | {hashSHA256, signatureECDSA}, 166 | {hashSHA384, signatureRSA}, 167 | {hashSHA384, signatureECDSA}, 168 | {hashSHA1, signatureRSA}, 169 | {hashSHA1, signatureECDSA}, 170 | } 171 | 172 | // ConnectionState records basic TLS details about the connection. 173 | type ConnectionState struct { 174 | Version uint16 // TLS version used by the connection (e.g. VersionTLS12) 175 | HandshakeComplete bool // TLS handshake is complete 176 | DidResume bool // connection resumes a previous TLS connection 177 | CipherSuite uint16 // cipher suite in use (TLS_RSA_WITH_RC4_128_SHA, ...) 178 | NegotiatedProtocol string // negotiated next protocol (from Config.NextProtos) 179 | NegotiatedProtocolIsMutual bool // negotiated protocol was advertised by server 180 | ServerName string // server name requested by client, if any (server side only) 181 | PeerCertificates []*sm2.Certificate // certificate chain presented by remote peer 182 | VerifiedChains [][]*sm2.Certificate // verified chains built from PeerCertificates 183 | SignedCertificateTimestamps [][]byte // SCTs from the server, if any 184 | OCSPResponse []byte // stapled OCSP response from server, if any 185 | 186 | // TLSUnique contains the "tls-unique" channel binding value (see RFC 187 | // 5929, section 3). For resumed sessions this value will be nil 188 | // because resumption does not include enough context (see 189 | // https://secure-resumption.com/#channelbindings). This will change in 190 | // future versions of Go once the TLS master-secret fix has been 191 | // standardized and implemented. 192 | TLSUnique []byte 193 | } 194 | 195 | // ClientAuthType declares the policy the server will follow for 196 | // TLS Client Authentication. 197 | type ClientAuthType int 198 | 199 | const ( 200 | NoClientCert ClientAuthType = iota 201 | RequestClientCert 202 | RequireAnyClientCert 203 | VerifyClientCertIfGiven 204 | RequireAndVerifyClientCert 205 | ) 206 | 207 | // ClientSessionState contains the state needed by clients to resume TLS 208 | // sessions. 209 | type ClientSessionState struct { 210 | sessionTicket []uint8 // Encrypted ticket used for session resumption with server 211 | vers uint16 // SSL/TLS version negotiated for the session 212 | cipherSuite uint16 // Ciphersuite negotiated for the session 213 | masterSecret []byte // MasterSecret generated by client on a full handshake 214 | serverCertificates []*sm2.Certificate // Certificate chain presented by the server 215 | verifiedChains [][]*sm2.Certificate // Certificate chains we built for verification 216 | } 217 | 218 | // ClientSessionCache is a cache of ClientSessionState objects that can be used 219 | // by a client to resume a TLS session with a given server. ClientSessionCache 220 | // implementations should expect to be called concurrently from different 221 | // goroutines. 222 | type ClientSessionCache interface { 223 | // Get searches for a ClientSessionState associated with the given key. 224 | // On return, ok is true if one was found. 225 | Get(sessionKey string) (session *ClientSessionState, ok bool) 226 | 227 | // Put adds the ClientSessionState to the cache with the given key. 228 | Put(sessionKey string, cs *ClientSessionState) 229 | } 230 | 231 | // SignatureScheme identifies a signature algorithm supported by TLS. See 232 | // https://tools.ietf.org/html/draft-ietf-tls-tls13-18#section-4.2.3. 233 | type SignatureScheme uint16 234 | 235 | const ( 236 | PKCS1WithSHA1 SignatureScheme = 0x0201 237 | PKCS1WithSHA256 SignatureScheme = 0x0401 238 | PKCS1WithSHA384 SignatureScheme = 0x0501 239 | PKCS1WithSHA512 SignatureScheme = 0x0601 240 | 241 | PSSWithSHA256 SignatureScheme = 0x0804 242 | PSSWithSHA384 SignatureScheme = 0x0805 243 | PSSWithSHA512 SignatureScheme = 0x0806 244 | 245 | ECDSAWithP256AndSHA256 SignatureScheme = 0x0403 246 | ECDSAWithP384AndSHA384 SignatureScheme = 0x0503 247 | ECDSAWithP521AndSHA512 SignatureScheme = 0x0603 248 | ) 249 | 250 | // ClientHelloInfo contains information from a ClientHello message in order to 251 | // guide certificate selection in the GetCertificate callback. 252 | type ClientHelloInfo struct { 253 | // CipherSuites lists the CipherSuites supported by the client (e.g. 254 | // TLS_RSA_WITH_RC4_128_SHA). 255 | CipherSuites []uint16 256 | 257 | // ServerName indicates the name of the server requested by the client 258 | // in order to support virtual hosting. ServerName is only set if the 259 | // client is using SNI (see 260 | // http://tools.ietf.org/html/rfc4366#section-3.1). 261 | ServerName string 262 | 263 | // SupportedCurves lists the elliptic curves supported by the client. 264 | // SupportedCurves is set only if the Supported Elliptic Curves 265 | // Extension is being used (see 266 | // http://tools.ietf.org/html/rfc4492#section-5.1.1). 267 | SupportedCurves []CurveID 268 | 269 | // SupportedPoints lists the point formats supported by the client. 270 | // SupportedPoints is set only if the Supported Point Formats Extension 271 | // is being used (see 272 | // http://tools.ietf.org/html/rfc4492#section-5.1.2). 273 | SupportedPoints []uint8 274 | 275 | // SignatureSchemes lists the signature and hash schemes that the client 276 | // is willing to verify. SignatureSchemes is set only if the Signature 277 | // Algorithms Extension is being used (see 278 | // https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1). 279 | SignatureSchemes []SignatureScheme 280 | 281 | // SupportedProtos lists the application protocols supported by the client. 282 | // SupportedProtos is set only if the Application-Layer Protocol 283 | // Negotiation Extension is being used (see 284 | // https://tools.ietf.org/html/rfc7301#section-3.1). 285 | // 286 | // Servers can select a protocol by setting Config.NextProtos in a 287 | // GetConfigForClient return value. 288 | SupportedProtos []string 289 | 290 | // SupportedVersions lists the TLS versions supported by the client. 291 | // For TLS versions less than 1.3, this is extrapolated from the max 292 | // version advertised by the client, so values other than the greatest 293 | // might be rejected if used. 294 | SupportedVersions []uint16 295 | 296 | // Conn is the underlying net.Conn for the connection. Do not read 297 | // from, or write to, this connection; that will cause the TLS 298 | // connection to fail. 299 | Conn net.Conn 300 | } 301 | 302 | // CertificateRequestInfo contains information from a server's 303 | // CertificateRequest message, which is used to demand a certificate and proof 304 | // of control from a client. 305 | type CertificateRequestInfo struct { 306 | // AcceptableCAs contains zero or more, DER-encoded, X.501 307 | // Distinguished Names. These are the names of root or intermediate CAs 308 | // that the server wishes the returned certificate to be signed by. An 309 | // empty slice indicates that the server has no preference. 310 | AcceptableCAs [][]byte 311 | 312 | // SignatureSchemes lists the signature schemes that the server is 313 | // willing to verify. 314 | SignatureSchemes []SignatureScheme 315 | } 316 | 317 | // RenegotiationSupport enumerates the different levels of support for TLS 318 | // renegotiation. TLS renegotiation is the act of performing subsequent 319 | // handshakes on a connection after the first. This significantly complicates 320 | // the state machine and has been the source of numerous, subtle security 321 | // issues. Initiating a renegotiation is not supported, but support for 322 | // accepting renegotiation requests may be enabled. 323 | // 324 | // Even when enabled, the server may not change its identity between handshakes 325 | // (i.e. the leaf certificate must be the same). Additionally, concurrent 326 | // handshake and application data flow is not permitted so renegotiation can 327 | // only be used with protocols that synchronise with the renegotiation, such as 328 | // HTTPS. 329 | type RenegotiationSupport int 330 | 331 | const ( 332 | // RenegotiateNever disables renegotiation. 333 | RenegotiateNever RenegotiationSupport = iota 334 | 335 | // RenegotiateOnceAsClient allows a remote server to request 336 | // renegotiation once per connection. 337 | RenegotiateOnceAsClient 338 | 339 | // RenegotiateFreelyAsClient allows a remote server to repeatedly 340 | // request renegotiation. 341 | RenegotiateFreelyAsClient 342 | ) 343 | 344 | // A Config structure is used to configure a TLS client or server. 345 | // After one has been passed to a TLS function it must not be 346 | // modified. A Config may be reused; the tls package will also not 347 | // modify it. 348 | type Config struct { 349 | // Rand provides the source of entropy for nonces and RSA blinding. 350 | // If Rand is nil, TLS uses the cryptographic random reader in package 351 | // crypto/rand. 352 | // The Reader must be safe for use by multiple goroutines. 353 | Rand io.Reader 354 | 355 | // Time returns the current time as the number of seconds since the epoch. 356 | // If Time is nil, TLS uses time.Now. 357 | Time func() time.Time 358 | 359 | // Certificates contains one or more certificate chains to present to 360 | // the other side of the connection. Server configurations must include 361 | // at least one certificate or else set GetCertificate. Clients doing 362 | // client-authentication may set either Certificates or 363 | // GetClientCertificate. 364 | Certificates []Certificate 365 | 366 | // NameToCertificate maps from a certificate name to an element of 367 | // Certificates. Note that a certificate name can be of the form 368 | // '*.example.com' and so doesn't have to be a domain name as such. 369 | // See Config.BuildNameToCertificate 370 | // The nil value causes the first element of Certificates to be used 371 | // for all connections. 372 | NameToCertificate map[string]*Certificate 373 | 374 | // GetCertificate returns a Certificate based on the given 375 | // ClientHelloInfo. It will only be called if the client supplies SNI 376 | // information or if Certificates is empty. 377 | // 378 | // If GetCertificate is nil or returns nil, then the certificate is 379 | // retrieved from NameToCertificate. If NameToCertificate is nil, the 380 | // first element of Certificates will be used. 381 | GetCertificate func(*ClientHelloInfo) (*Certificate, error) 382 | 383 | // GetClientCertificate, if not nil, is called when a server requests a 384 | // certificate from a client. If set, the contents of Certificates will 385 | // be ignored. 386 | // 387 | // If GetClientCertificate returns an error, the handshake will be 388 | // aborted and that error will be returned. Otherwise 389 | // GetClientCertificate must return a non-nil Certificate. If 390 | // Certificate.Certificate is empty then no certificate will be sent to 391 | // the server. If this is unacceptable to the server then it may abort 392 | // the handshake. 393 | // 394 | // GetClientCertificate may be called multiple times for the same 395 | // connection if renegotiation occurs or if TLS 1.3 is in use. 396 | GetClientCertificate func(*CertificateRequestInfo) (*Certificate, error) 397 | 398 | // GetConfigForClient, if not nil, is called after a ClientHello is 399 | // received from a client. It may return a non-nil Config in order to 400 | // change the Config that will be used to handle this connection. If 401 | // the returned Config is nil, the original Config will be used. The 402 | // Config returned by this callback may not be subsequently modified. 403 | // 404 | // If GetConfigForClient is nil, the Config passed to Server() will be 405 | // used for all connections. 406 | // 407 | // Uniquely for the fields in the returned Config, session ticket keys 408 | // will be duplicated from the original Config if not set. 409 | // Specifically, if SetSessionTicketKeys was called on the original 410 | // config but not on the returned config then the ticket keys from the 411 | // original config will be copied into the new config before use. 412 | // Otherwise, if SessionTicketKey was set in the original config but 413 | // not in the returned config then it will be copied into the returned 414 | // config before use. If neither of those cases applies then the key 415 | // material from the returned config will be used for session tickets. 416 | GetConfigForClient func(*ClientHelloInfo) (*Config, error) 417 | 418 | // VerifyPeerCertificate, if not nil, is called after normal 419 | // certificate verification by either a TLS client or server. It 420 | // receives the raw ASN.1 certificates provided by the peer and also 421 | // any verified chains that normal processing found. If it returns a 422 | // non-nil error, the handshake is aborted and that error results. 423 | // 424 | // If normal verification fails then the handshake will abort before 425 | // considering this callback. If normal verification is disabled by 426 | // setting InsecureSkipVerify then this callback will be considered but 427 | // the verifiedChains argument will always be nil. 428 | VerifyPeerCertificate func(rawCerts [][]byte, verifiedChains [][]*sm2.Certificate) error 429 | 430 | // RootCAs defines the set of root certificate authorities 431 | // that clients use when verifying server certificates. 432 | // If RootCAs is nil, TLS uses the host's root CA set. 433 | RootCAs *sm2.CertPool 434 | 435 | // NextProtos is a list of supported, application level protocols. 436 | NextProtos []string 437 | 438 | // ServerName is used to verify the hostname on the returned 439 | // certificates unless InsecureSkipVerify is given. It is also included 440 | // in the client's handshake to support virtual hosting unless it is 441 | // an IP address. 442 | ServerName string 443 | 444 | // ClientAuth determines the server's policy for 445 | // TLS Client Authentication. The default is NoClientCert. 446 | ClientAuth ClientAuthType 447 | 448 | // ClientCAs defines the set of root certificate authorities 449 | // that servers use if required to verify a client certificate 450 | // by the policy in ClientAuth. 451 | ClientCAs *sm2.CertPool 452 | 453 | // InsecureSkipVerify controls whether a client verifies the 454 | // server's certificate chain and host name. 455 | // If InsecureSkipVerify is true, TLS accepts any certificate 456 | // presented by the server and any host name in that certificate. 457 | // In this mode, TLS is susceptible to man-in-the-middle attacks. 458 | // This should be used only for testing. 459 | InsecureSkipVerify bool 460 | 461 | // CipherSuites is a list of supported cipher suites. If CipherSuites 462 | // is nil, TLS uses a list of suites supported by the implementation. 463 | CipherSuites []uint16 464 | 465 | // PreferServerCipherSuites controls whether the server selects the 466 | // client's most preferred ciphersuite, or the server's most preferred 467 | // ciphersuite. If true then the server's preference, as expressed in 468 | // the order of elements in CipherSuites, is used. 469 | PreferServerCipherSuites bool 470 | 471 | // SessionTicketsDisabled may be set to true to disable session ticket 472 | // (resumption) support. 473 | SessionTicketsDisabled bool 474 | 475 | // SessionTicketKey is used by TLS servers to provide session 476 | // resumption. See RFC 5077. If zero, it will be filled with 477 | // random data before the first server handshake. 478 | // 479 | // If multiple servers are terminating connections for the same host 480 | // they should all have the same SessionTicketKey. If the 481 | // SessionTicketKey leaks, previously recorded and future TLS 482 | // connections using that key are compromised. 483 | SessionTicketKey [32]byte 484 | 485 | // SessionCache is a cache of ClientSessionState entries for TLS session 486 | // resumption. 487 | ClientSessionCache ClientSessionCache 488 | 489 | // MinVersion contains the minimum SSL/TLS version that is acceptable. 490 | // If zero, then TLS 1.0 is taken as the minimum. 491 | MinVersion uint16 492 | 493 | // MaxVersion contains the maximum SSL/TLS version that is acceptable. 494 | // If zero, then the maximum version supported by this package is used, 495 | // which is currently TLS 1.2. 496 | MaxVersion uint16 497 | 498 | // CurvePreferences contains the elliptic curves that will be used in 499 | // an ECDHE handshake, in preference order. If empty, the default will 500 | // be used. 501 | CurvePreferences []CurveID 502 | 503 | // DynamicRecordSizingDisabled disables adaptive sizing of TLS records. 504 | // When true, the largest possible TLS record size is always used. When 505 | // false, the size of TLS records may be adjusted in an attempt to 506 | // improve latency. 507 | DynamicRecordSizingDisabled bool 508 | 509 | // Renegotiation controls what types of renegotiation are supported. 510 | // The default, none, is correct for the vast majority of applications. 511 | Renegotiation RenegotiationSupport 512 | 513 | // KeyLogWriter optionally specifies a destination for TLS master secrets 514 | // in NSS key log format that can be used to allow external programs 515 | // such as Wireshark to decrypt TLS connections. 516 | // See https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format. 517 | // Use of KeyLogWriter compromises security and should only be 518 | // used for debugging. 519 | KeyLogWriter io.Writer 520 | 521 | serverInitOnce sync.Once // guards calling (*Config).serverInit 522 | 523 | // mutex protects sessionTicketKeys and originalConfig. 524 | mutex sync.RWMutex 525 | // sessionTicketKeys contains zero or more ticket keys. If the length 526 | // is zero, SessionTicketsDisabled must be true. The first key is used 527 | // for new tickets and any subsequent keys can be used to decrypt old 528 | // tickets. 529 | sessionTicketKeys []ticketKey 530 | // originalConfig is set to the Config that was passed to Server if 531 | // this Config is returned by a GetConfigForClient callback. It's used 532 | // by serverInit in order to copy session ticket keys if needed. 533 | originalConfig *Config 534 | } 535 | 536 | // ticketKeyNameLen is the number of bytes of identifier that is prepended to 537 | // an encrypted session ticket in order to identify the key used to encrypt it. 538 | const ticketKeyNameLen = 16 539 | 540 | // ticketKey is the internal representation of a session ticket key. 541 | type ticketKey struct { 542 | // keyName is an opaque byte string that serves to identify the session 543 | // ticket key. It's exposed as plaintext in every session ticket. 544 | keyName [ticketKeyNameLen]byte 545 | aesKey [16]byte 546 | hmacKey [16]byte 547 | } 548 | 549 | // ticketKeyFromBytes converts from the external representation of a session 550 | // ticket key to a ticketKey. Externally, session ticket keys are 32 random 551 | // bytes and this function expands that into sufficient name and key material. 552 | func ticketKeyFromBytes(b [32]byte) (key ticketKey) { 553 | hashed := sha512.Sum512(b[:]) 554 | copy(key.keyName[:], hashed[:ticketKeyNameLen]) 555 | copy(key.aesKey[:], hashed[ticketKeyNameLen:ticketKeyNameLen+16]) 556 | copy(key.hmacKey[:], hashed[ticketKeyNameLen+16:ticketKeyNameLen+32]) 557 | return key 558 | } 559 | 560 | // Clone returns a shallow clone of c. It is safe to clone a Config that is 561 | // being used concurrently by a TLS client or server. 562 | func (c *Config) Clone() *Config { 563 | // Running serverInit ensures that it's safe to read 564 | // SessionTicketsDisabled. 565 | c.serverInitOnce.Do(c.serverInit) 566 | 567 | var sessionTicketKeys []ticketKey 568 | c.mutex.RLock() 569 | sessionTicketKeys = c.sessionTicketKeys 570 | c.mutex.RUnlock() 571 | 572 | return &Config{ 573 | Rand: c.Rand, 574 | Time: c.Time, 575 | Certificates: c.Certificates, 576 | NameToCertificate: c.NameToCertificate, 577 | GetCertificate: c.GetCertificate, 578 | GetConfigForClient: c.GetConfigForClient, 579 | VerifyPeerCertificate: c.VerifyPeerCertificate, 580 | RootCAs: c.RootCAs, 581 | NextProtos: c.NextProtos, 582 | ServerName: c.ServerName, 583 | ClientAuth: c.ClientAuth, 584 | ClientCAs: c.ClientCAs, 585 | InsecureSkipVerify: c.InsecureSkipVerify, 586 | CipherSuites: c.CipherSuites, 587 | PreferServerCipherSuites: c.PreferServerCipherSuites, 588 | SessionTicketsDisabled: c.SessionTicketsDisabled, 589 | SessionTicketKey: c.SessionTicketKey, 590 | ClientSessionCache: c.ClientSessionCache, 591 | MinVersion: c.MinVersion, 592 | MaxVersion: c.MaxVersion, 593 | CurvePreferences: c.CurvePreferences, 594 | DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled, 595 | Renegotiation: c.Renegotiation, 596 | KeyLogWriter: c.KeyLogWriter, 597 | sessionTicketKeys: sessionTicketKeys, 598 | // originalConfig is deliberately not duplicated. 599 | } 600 | } 601 | 602 | func (c *Config) serverInit() { 603 | if c.SessionTicketsDisabled || len(c.ticketKeys()) != 0 { 604 | return 605 | } 606 | 607 | var originalConfig *Config 608 | c.mutex.Lock() 609 | originalConfig, c.originalConfig = c.originalConfig, nil 610 | c.mutex.Unlock() 611 | 612 | alreadySet := false 613 | for _, b := range c.SessionTicketKey { 614 | if b != 0 { 615 | alreadySet = true 616 | break 617 | } 618 | } 619 | 620 | if !alreadySet { 621 | if originalConfig != nil { 622 | copy(c.SessionTicketKey[:], originalConfig.SessionTicketKey[:]) 623 | } else if _, err := io.ReadFull(c.rand(), c.SessionTicketKey[:]); err != nil { 624 | c.SessionTicketsDisabled = true 625 | return 626 | } 627 | } 628 | 629 | if originalConfig != nil { 630 | originalConfig.mutex.RLock() 631 | c.sessionTicketKeys = originalConfig.sessionTicketKeys 632 | originalConfig.mutex.RUnlock() 633 | } else { 634 | c.sessionTicketKeys = []ticketKey{ticketKeyFromBytes(c.SessionTicketKey)} 635 | } 636 | } 637 | 638 | func (c *Config) ticketKeys() []ticketKey { 639 | c.mutex.RLock() 640 | // c.sessionTicketKeys is constant once created. SetSessionTicketKeys 641 | // will only update it by replacing it with a new value. 642 | ret := c.sessionTicketKeys 643 | c.mutex.RUnlock() 644 | return ret 645 | } 646 | 647 | // SetSessionTicketKeys updates the session ticket keys for a server. The first 648 | // key will be used when creating new tickets, while all keys can be used for 649 | // decrypting tickets. It is safe to call this function while the server is 650 | // running in order to rotate the session ticket keys. The function will panic 651 | // if keys is empty. 652 | func (c *Config) SetSessionTicketKeys(keys [][32]byte) { 653 | if len(keys) == 0 { 654 | panic("tls: keys must have at least one key") 655 | } 656 | 657 | newKeys := make([]ticketKey, len(keys)) 658 | for i, bytes := range keys { 659 | newKeys[i] = ticketKeyFromBytes(bytes) 660 | } 661 | 662 | c.mutex.Lock() 663 | c.sessionTicketKeys = newKeys 664 | c.mutex.Unlock() 665 | } 666 | 667 | func (c *Config) rand() io.Reader { 668 | r := c.Rand 669 | if r == nil { 670 | return rand.Reader 671 | } 672 | return r 673 | } 674 | 675 | func (c *Config) time() time.Time { 676 | t := c.Time 677 | if t == nil { 678 | t = time.Now 679 | } 680 | return t() 681 | } 682 | 683 | func (c *Config) cipherSuites() []uint16 { 684 | s := c.CipherSuites 685 | if s == nil { 686 | s = defaultCipherSuites() 687 | } 688 | return s 689 | } 690 | 691 | func (c *Config) minVersion() uint16 { 692 | if c == nil || c.MinVersion == 0 { 693 | return minVersion 694 | } 695 | return c.MinVersion 696 | } 697 | 698 | func (c *Config) maxVersion() uint16 { 699 | if c == nil || c.MaxVersion == 0 { 700 | return maxVersion 701 | } 702 | return c.MaxVersion 703 | } 704 | 705 | var defaultCurvePreferences = []CurveID{X25519, CurveP256, CurveP384, CurveP521, CureP256SM2} 706 | 707 | func (c *Config) curvePreferences() []CurveID { 708 | if c == nil || len(c.CurvePreferences) == 0 { 709 | return defaultCurvePreferences 710 | } 711 | return c.CurvePreferences 712 | } 713 | 714 | // mutualVersion returns the protocol version to use given the advertised 715 | // version of the peer. 716 | func (c *Config) mutualVersion(vers uint16) (uint16, bool) { 717 | minVersion := c.minVersion() 718 | maxVersion := c.maxVersion() 719 | 720 | if vers < minVersion { 721 | return 0, false 722 | } 723 | if vers > maxVersion { 724 | vers = maxVersion 725 | } 726 | return vers, true 727 | } 728 | 729 | // getCertificate returns the best certificate for the given ClientHelloInfo, 730 | // defaulting to the first element of c.Certificates. 731 | func (c *Config) getCertificate(clientHello *ClientHelloInfo) (*Certificate, error) { 732 | if c.GetCertificate != nil && 733 | (len(c.Certificates) == 0 || len(clientHello.ServerName) > 0) { 734 | cert, err := c.GetCertificate(clientHello) 735 | if cert != nil || err != nil { 736 | return cert, err 737 | } 738 | } 739 | 740 | if len(c.Certificates) == 0 { 741 | return nil, errors.New("tls: no certificates configured") 742 | } 743 | 744 | if len(c.Certificates) == 1 || c.NameToCertificate == nil { 745 | // There's only one choice, so no point doing any work. 746 | return &c.Certificates[0], nil 747 | } 748 | 749 | name := strings.ToLower(clientHello.ServerName) 750 | for len(name) > 0 && name[len(name)-1] == '.' { 751 | name = name[:len(name)-1] 752 | } 753 | 754 | if cert, ok := c.NameToCertificate[name]; ok { 755 | return cert, nil 756 | } 757 | 758 | // try replacing labels in the name with wildcards until we get a 759 | // match. 760 | labels := strings.Split(name, ".") 761 | for i := range labels { 762 | labels[i] = "*" 763 | candidate := strings.Join(labels, ".") 764 | if cert, ok := c.NameToCertificate[candidate]; ok { 765 | return cert, nil 766 | } 767 | } 768 | 769 | // If nothing matches, return the first certificate. 770 | return &c.Certificates[0], nil 771 | } 772 | 773 | // BuildNameToCertificate parses c.Certificates and builds c.NameToCertificate 774 | // from the CommonName and SubjectAlternateName fields of each of the leaf 775 | // certificates. 776 | func (c *Config) BuildNameToCertificate() { 777 | c.NameToCertificate = make(map[string]*Certificate) 778 | for i := range c.Certificates { 779 | cert := &c.Certificates[i] 780 | x509Cert, err := sm2.ParseCertificate(cert.Certificate[0]) 781 | if err != nil { 782 | continue 783 | } 784 | if len(x509Cert.Subject.CommonName) > 0 { 785 | c.NameToCertificate[x509Cert.Subject.CommonName] = cert 786 | } 787 | for _, san := range x509Cert.DNSNames { 788 | c.NameToCertificate[san] = cert 789 | } 790 | } 791 | } 792 | 793 | // writeKeyLog logs client random and master secret if logging was enabled by 794 | // setting c.KeyLogWriter. 795 | func (c *Config) writeKeyLog(clientRandom, masterSecret []byte) error { 796 | if c.KeyLogWriter == nil { 797 | return nil 798 | } 799 | 800 | logLine := []byte(fmt.Sprintf("CLIENT_RANDOM %x %x\n", clientRandom, masterSecret)) 801 | 802 | writerMutex.Lock() 803 | _, err := c.KeyLogWriter.Write(logLine) 804 | writerMutex.Unlock() 805 | 806 | return err 807 | } 808 | 809 | // writerMutex protects all KeyLogWriters globally. It is rarely enabled, 810 | // and is only for debugging, so a global mutex saves space. 811 | var writerMutex sync.Mutex 812 | 813 | // A Certificate is a chain of one or more certificates, leaf first. 814 | type Certificate struct { 815 | Certificate [][]byte 816 | // PrivateKey contains the private key corresponding to the public key 817 | // in Leaf. For a server, this must implement crypto.Signer and/or 818 | // crypto.Decrypter, with an RSA or ECDSA PublicKey. For a client 819 | // (performing client authentication), this must be a crypto.Signer 820 | // with an RSA or ECDSA PublicKey. 821 | PrivateKey crypto.PrivateKey 822 | // OCSPStaple contains an optional OCSP response which will be served 823 | // to clients that request it. 824 | OCSPStaple []byte 825 | // SignedCertificateTimestamps contains an optional list of Signed 826 | // Certificate Timestamps which will be served to clients that request it. 827 | SignedCertificateTimestamps [][]byte 828 | // Leaf is the parsed form of the leaf certificate, which may be 829 | // initialized using x509.ParseCertificate to reduce per-handshake 830 | // processing for TLS clients doing client authentication. If nil, the 831 | // leaf certificate will be parsed as needed. 832 | Leaf *sm2.Certificate 833 | } 834 | 835 | type handshakeMessage interface { 836 | marshal() []byte 837 | unmarshal([]byte) bool 838 | } 839 | 840 | // lruSessionCache is a ClientSessionCache implementation that uses an LRU 841 | // caching strategy. 842 | type lruSessionCache struct { 843 | sync.Mutex 844 | 845 | m map[string]*list.Element 846 | q *list.List 847 | capacity int 848 | } 849 | 850 | type lruSessionCacheEntry struct { 851 | sessionKey string 852 | state *ClientSessionState 853 | } 854 | 855 | // NewLRUClientSessionCache returns a ClientSessionCache with the given 856 | // capacity that uses an LRU strategy. If capacity is < 1, a default capacity 857 | // is used instead. 858 | func NewLRUClientSessionCache(capacity int) ClientSessionCache { 859 | const defaultSessionCacheCapacity = 64 860 | 861 | if capacity < 1 { 862 | capacity = defaultSessionCacheCapacity 863 | } 864 | return &lruSessionCache{ 865 | m: make(map[string]*list.Element), 866 | q: list.New(), 867 | capacity: capacity, 868 | } 869 | } 870 | 871 | // Put adds the provided (sessionKey, cs) pair to the cache. 872 | func (c *lruSessionCache) Put(sessionKey string, cs *ClientSessionState) { 873 | c.Lock() 874 | defer c.Unlock() 875 | 876 | if elem, ok := c.m[sessionKey]; ok { 877 | entry := elem.Value.(*lruSessionCacheEntry) 878 | entry.state = cs 879 | c.q.MoveToFront(elem) 880 | return 881 | } 882 | 883 | if c.q.Len() < c.capacity { 884 | entry := &lruSessionCacheEntry{sessionKey, cs} 885 | c.m[sessionKey] = c.q.PushFront(entry) 886 | return 887 | } 888 | 889 | elem := c.q.Back() 890 | entry := elem.Value.(*lruSessionCacheEntry) 891 | delete(c.m, entry.sessionKey) 892 | entry.sessionKey = sessionKey 893 | entry.state = cs 894 | c.q.MoveToFront(elem) 895 | c.m[sessionKey] = elem 896 | } 897 | 898 | // Get returns the ClientSessionState value associated with a given key. It 899 | // returns (nil, false) if no value is found. 900 | func (c *lruSessionCache) Get(sessionKey string) (*ClientSessionState, bool) { 901 | c.Lock() 902 | defer c.Unlock() 903 | 904 | if elem, ok := c.m[sessionKey]; ok { 905 | c.q.MoveToFront(elem) 906 | return elem.Value.(*lruSessionCacheEntry).state, true 907 | } 908 | return nil, false 909 | } 910 | 911 | // TODO(jsing): Make these available to both crypto/x509 and crypto/tls. 912 | type dsaSignature struct { 913 | R, S *big.Int 914 | } 915 | 916 | type ecdsaSignature dsaSignature 917 | 918 | var emptyConfig Config 919 | 920 | func defaultConfig() *Config { 921 | return &emptyConfig 922 | } 923 | 924 | var ( 925 | once sync.Once 926 | varDefaultCipherSuites []uint16 927 | ) 928 | 929 | func defaultCipherSuites() []uint16 { 930 | once.Do(initDefaultCipherSuites) 931 | return varDefaultCipherSuites 932 | } 933 | 934 | func initDefaultCipherSuites() { 935 | var topCipherSuites []uint16 936 | /* 937 | if cipherhw.AESGCMSupport() { 938 | // If AES-GCM hardware is provided then prioritise AES-GCM 939 | // cipher suites. 940 | topCipherSuites = []uint16{ 941 | TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 942 | TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 943 | TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 944 | TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 945 | TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, 946 | TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, 947 | } 948 | } else { 949 | // Without AES-GCM hardware, we put the ChaCha20-Poly1305 950 | // cipher suites first. 951 | topCipherSuites = []uint16{ 952 | TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, 953 | TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, 954 | TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 955 | TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 956 | TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 957 | TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 958 | } 959 | } 960 | */ 961 | topCipherSuites = []uint16{ 962 | TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, 963 | TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, 964 | TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 965 | TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 966 | TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 967 | TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 968 | } 969 | 970 | varDefaultCipherSuites = make([]uint16, 0, len(cipherSuites)) 971 | for _, topCipher := range topCipherSuites { 972 | varDefaultCipherSuites = append(varDefaultCipherSuites, topCipher) 973 | } 974 | 975 | NextCipherSuite: 976 | for _, suite := range cipherSuites { 977 | if suite.flags&suiteDefaultOff != 0 { 978 | continue 979 | } 980 | for _, existing := range varDefaultCipherSuites { 981 | if existing == suite.id { 982 | continue NextCipherSuite 983 | } 984 | } 985 | varDefaultCipherSuites = append(varDefaultCipherSuites, suite.id) 986 | } 987 | } 988 | 989 | func unexpectedMessageError(wanted, got interface{}) error { 990 | return fmt.Errorf("tls: received unexpected handshake message of type %T when waiting for %T", got, wanted) 991 | } 992 | 993 | func isSupportedSignatureAndHash(sigHash signatureAndHash, sigHashes []signatureAndHash) bool { 994 | for _, s := range sigHashes { 995 | if s == sigHash { 996 | return true 997 | } 998 | } 999 | return false 1000 | } 1001 | --------------------------------------------------------------------------------