mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-10-30 21:30:16 +00:00 
			
		
		
		
	Bump cfssl to 56268a6
This commit is contained in:
		
							
								
								
									
										6
									
								
								vendor/github.com/cloudflare/cfssl/scan/BUILD
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/cloudflare/cfssl/scan/BUILD
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -18,6 +18,7 @@ go_library( | ||||
|         "//vendor/github.com/cloudflare/cfssl/helpers:go_default_library", | ||||
|         "//vendor/github.com/cloudflare/cfssl/log:go_default_library", | ||||
|         "//vendor/github.com/cloudflare/cfssl/revoke:go_default_library", | ||||
|         "//vendor/github.com/cloudflare/cfssl/scan/crypto/tls:go_default_library", | ||||
|     ], | ||||
| ) | ||||
|  | ||||
| @@ -30,7 +31,10 @@ filegroup( | ||||
|  | ||||
| filegroup( | ||||
|     name = "all-srcs", | ||||
|     srcs = [":package-srcs"], | ||||
|     srcs = [ | ||||
|         ":package-srcs", | ||||
|         "//vendor/github.com/cloudflare/cfssl/scan/crypto/tls:all-srcs", | ||||
|     ], | ||||
|     tags = ["automanaged"], | ||||
|     visibility = ["//visibility:public"], | ||||
| ) | ||||
|   | ||||
							
								
								
									
										5
									
								
								vendor/github.com/cloudflare/cfssl/scan/connectivity.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/cloudflare/cfssl/scan/connectivity.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -2,11 +2,12 @@ package scan | ||||
|  | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"crypto/tls" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"net" | ||||
|  | ||||
| 	"github.com/cloudflare/cfssl/scan/crypto/tls" | ||||
| ) | ||||
|  | ||||
| // Connectivity contains scanners testing basic connectivity to the host | ||||
| @@ -53,7 +54,7 @@ var ( | ||||
| ) | ||||
|  | ||||
| func initOnCloudFlareScan() ([]*net.IPNet, error) { | ||||
| 	// Propogate previous errors and don't attempt to re-download. | ||||
| 	// Propagate previous errors and don't attempt to re-download. | ||||
| 	if cfNetsErr != nil { | ||||
| 		return nil, cfNetsErr | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										37
									
								
								vendor/github.com/cloudflare/cfssl/scan/crypto/tls/BUILD
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								vendor/github.com/cloudflare/cfssl/scan/crypto/tls/BUILD
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| load("@io_bazel_rules_go//go:def.bzl", "go_library") | ||||
|  | ||||
| go_library( | ||||
|     name = "go_default_library", | ||||
|     srcs = [ | ||||
|         "alert.go", | ||||
|         "cfsslscan_common.go", | ||||
|         "cfsslscan_handshake.go", | ||||
|         "cipher_suites.go", | ||||
|         "common.go", | ||||
|         "conn.go", | ||||
|         "handshake_client.go", | ||||
|         "handshake_messages.go", | ||||
|         "handshake_server.go", | ||||
|         "key_agreement.go", | ||||
|         "prf.go", | ||||
|         "ticket.go", | ||||
|         "tls.go", | ||||
|     ], | ||||
|     importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/scan/crypto/tls", | ||||
|     importpath = "github.com/cloudflare/cfssl/scan/crypto/tls", | ||||
|     visibility = ["//visibility:public"], | ||||
| ) | ||||
|  | ||||
| filegroup( | ||||
|     name = "package-srcs", | ||||
|     srcs = glob(["**"]), | ||||
|     tags = ["automanaged"], | ||||
|     visibility = ["//visibility:private"], | ||||
| ) | ||||
|  | ||||
| filegroup( | ||||
|     name = "all-srcs", | ||||
|     srcs = [":package-srcs"], | ||||
|     tags = ["automanaged"], | ||||
|     visibility = ["//visibility:public"], | ||||
| ) | ||||
							
								
								
									
										79
									
								
								vendor/github.com/cloudflare/cfssl/scan/crypto/tls/alert.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								vendor/github.com/cloudflare/cfssl/scan/crypto/tls/alert.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | ||||
| // Copyright 2009 The Go Authors. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package tls | ||||
|  | ||||
| import "strconv" | ||||
|  | ||||
| type alert uint8 | ||||
|  | ||||
| const ( | ||||
| 	// alert level | ||||
| 	alertLevelWarning = 1 | ||||
| 	alertLevelError   = 2 | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	alertCloseNotify            alert = 0 | ||||
| 	alertUnexpectedMessage      alert = 10 | ||||
| 	alertBadRecordMAC           alert = 20 | ||||
| 	alertDecryptionFailed       alert = 21 | ||||
| 	alertRecordOverflow         alert = 22 | ||||
| 	alertDecompressionFailure   alert = 30 | ||||
| 	alertHandshakeFailure       alert = 40 | ||||
| 	alertBadCertificate         alert = 42 | ||||
| 	alertUnsupportedCertificate alert = 43 | ||||
| 	alertCertificateRevoked     alert = 44 | ||||
| 	alertCertificateExpired     alert = 45 | ||||
| 	alertCertificateUnknown     alert = 46 | ||||
| 	alertIllegalParameter       alert = 47 | ||||
| 	alertUnknownCA              alert = 48 | ||||
| 	alertAccessDenied           alert = 49 | ||||
| 	alertDecodeError            alert = 50 | ||||
| 	alertDecryptError           alert = 51 | ||||
| 	alertProtocolVersion        alert = 70 | ||||
| 	alertInsufficientSecurity   alert = 71 | ||||
| 	alertInternalError          alert = 80 | ||||
| 	alertInappropriateFallback  alert = 86 | ||||
| 	alertUserCanceled           alert = 90 | ||||
| 	alertNoRenegotiation        alert = 100 | ||||
| ) | ||||
|  | ||||
| var alertText = map[alert]string{ | ||||
| 	alertCloseNotify:            "close notify", | ||||
| 	alertUnexpectedMessage:      "unexpected message", | ||||
| 	alertBadRecordMAC:           "bad record MAC", | ||||
| 	alertDecryptionFailed:       "decryption failed", | ||||
| 	alertRecordOverflow:         "record overflow", | ||||
| 	alertDecompressionFailure:   "decompression failure", | ||||
| 	alertHandshakeFailure:       "handshake failure", | ||||
| 	alertBadCertificate:         "bad certificate", | ||||
| 	alertUnsupportedCertificate: "unsupported certificate", | ||||
| 	alertCertificateRevoked:     "revoked certificate", | ||||
| 	alertCertificateExpired:     "expired certificate", | ||||
| 	alertCertificateUnknown:     "unknown certificate", | ||||
| 	alertIllegalParameter:       "illegal parameter", | ||||
| 	alertUnknownCA:              "unknown certificate authority", | ||||
| 	alertAccessDenied:           "access denied", | ||||
| 	alertDecodeError:            "error decoding message", | ||||
| 	alertDecryptError:           "error decrypting message", | ||||
| 	alertProtocolVersion:        "protocol version not supported", | ||||
| 	alertInsufficientSecurity:   "insufficient security level", | ||||
| 	alertInternalError:          "internal error", | ||||
| 	alertInappropriateFallback:  "inappropriate fallback", | ||||
| 	alertUserCanceled:           "user canceled", | ||||
| 	alertNoRenegotiation:        "no renegotiation", | ||||
| } | ||||
|  | ||||
| func (e alert) String() string { | ||||
| 	s, ok := alertText[e] | ||||
| 	if ok { | ||||
| 		return s | ||||
| 	} | ||||
| 	return "alert(" + strconv.Itoa(int(e)) + ")" | ||||
| } | ||||
|  | ||||
| func (e alert) Error() string { | ||||
| 	return e.String() | ||||
| } | ||||
							
								
								
									
										486
									
								
								vendor/github.com/cloudflare/cfssl/scan/crypto/tls/cfsslscan_common.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										486
									
								
								vendor/github.com/cloudflare/cfssl/scan/crypto/tls/cfsslscan_common.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,486 @@ | ||||
| package tls | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| ) | ||||
|  | ||||
| type hashAlgID uint8 | ||||
|  | ||||
| const ( | ||||
| 	HashNone hashAlgID = iota | ||||
| 	HashMD5 | ||||
| 	HashSHA1 | ||||
| 	HashSHA224 | ||||
| 	HashSHA256 | ||||
| 	HashSHA384 | ||||
| 	HashSHA512 | ||||
| ) | ||||
|  | ||||
| func (h hashAlgID) String() string { | ||||
| 	switch h { | ||||
| 	case HashNone: | ||||
| 		return "None" | ||||
| 	case HashMD5: | ||||
| 		return "MD5" | ||||
| 	case HashSHA1: | ||||
| 		return "SHA1" | ||||
| 	case HashSHA224: | ||||
| 		return "SHA224" | ||||
| 	case HashSHA256: | ||||
| 		return "SHA256" | ||||
| 	case HashSHA384: | ||||
| 		return "SHA384" | ||||
| 	case HashSHA512: | ||||
| 		return "SHA512" | ||||
| 	default: | ||||
| 		return "Unknown" | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type sigAlgID uint8 | ||||
|  | ||||
| // Signature algorithms for TLS 1.2 (See RFC 5246, section A.4.1) | ||||
| const ( | ||||
| 	SigAnon sigAlgID = iota | ||||
| 	SigRSA | ||||
| 	SigDSA | ||||
| 	SigECDSA | ||||
| ) | ||||
|  | ||||
| func (sig sigAlgID) String() string { | ||||
| 	switch sig { | ||||
| 	case SigAnon: | ||||
| 		return "Anon" | ||||
| 	case SigRSA: | ||||
| 		return "RSA" | ||||
| 	case SigDSA: | ||||
| 		return "DSA" | ||||
| 	case SigECDSA: | ||||
| 		return "ECDSA" | ||||
| 	default: | ||||
| 		return "Unknown" | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // SignatureAndHash mirrors the TLS 1.2, SignatureAndHashAlgorithm struct. See | ||||
| // RFC 5246, section A.4.1. | ||||
| type SignatureAndHash struct { | ||||
| 	h hashAlgID | ||||
| 	s sigAlgID | ||||
| } | ||||
|  | ||||
| func (sigAlg SignatureAndHash) String() string { | ||||
| 	return fmt.Sprintf("{%s,%s}", sigAlg.s, sigAlg.h) | ||||
| } | ||||
|  | ||||
| func (sigAlg SignatureAndHash) MarshalJSON() ([]byte, error) { | ||||
| 	return []byte(fmt.Sprintf(`{"signature":"%s","hash":"%s"}`, sigAlg.s, sigAlg.h)), nil | ||||
| } | ||||
|  | ||||
| func (sigAlg SignatureAndHash) internal() signatureAndHash { | ||||
| 	return signatureAndHash{uint8(sigAlg.h), uint8(sigAlg.s)} | ||||
| } | ||||
|  | ||||
| // defaultSignatureAndHashAlgorithms contains the default signature and hash | ||||
| // algorithm paris supported by `crypto/tls` | ||||
| var defaultSignatureAndHashAlgorithms []signatureAndHash | ||||
|  | ||||
| // AllSignatureAndHashAlgorithms contains all possible signature and | ||||
| // hash algorithm pairs that the can be advertised in a TLS 1.2 ClientHello. | ||||
| var AllSignatureAndHashAlgorithms []SignatureAndHash | ||||
|  | ||||
| func init() { | ||||
| 	defaultSignatureAndHashAlgorithms = supportedSignatureAlgorithms | ||||
| 	for _, sighash := range supportedSignatureAlgorithms { | ||||
| 		AllSignatureAndHashAlgorithms = append(AllSignatureAndHashAlgorithms, | ||||
| 			SignatureAndHash{hashAlgID(sighash.hash), sigAlgID(sighash.signature)}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // TLSVersions is a list of the current SSL/TLS Versions implemented by Go | ||||
| var Versions = map[uint16]string{ | ||||
| 	VersionSSL30: "SSL 3.0", | ||||
| 	VersionTLS10: "TLS 1.0", | ||||
| 	VersionTLS11: "TLS 1.1", | ||||
| 	VersionTLS12: "TLS 1.2", | ||||
| } | ||||
|  | ||||
| // CipherSuite describes an individual cipher suite, with long and short names | ||||
| // and security properties. | ||||
| type CipherSuite struct { | ||||
| 	Name, ShortName string | ||||
| 	// ForwardSecret cipher suites negotiate ephemeral keys, allowing forward secrecy. | ||||
| 	ForwardSecret bool | ||||
| 	EllipticCurve bool | ||||
| } | ||||
|  | ||||
| // Returns the (short) name of the cipher suite. | ||||
| func (c CipherSuite) String() string { | ||||
| 	if c.ShortName != "" { | ||||
| 		return c.ShortName | ||||
| 	} | ||||
| 	return c.Name | ||||
| } | ||||
|  | ||||
| // CipherSuites contains all values in the TLS Cipher Suite Registry | ||||
| // https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml | ||||
| var CipherSuites = map[uint16]CipherSuite{ | ||||
| 	0X0000: {Name: "TLS_NULL_WITH_NULL_NULL"}, | ||||
| 	0X0001: {Name: "TLS_RSA_WITH_NULL_MD5"}, | ||||
| 	0X0002: {Name: "TLS_RSA_WITH_NULL_SHA"}, | ||||
| 	0X0003: {Name: "TLS_RSA_EXPORT_WITH_RC4_40_MD5", ShortName: "EXP-RC4-MD5"}, | ||||
| 	0X0004: {Name: "TLS_RSA_WITH_RC4_128_MD5", ShortName: "RC4-MD5"}, | ||||
| 	0X0005: {Name: "TLS_RSA_WITH_RC4_128_SHA", ShortName: "RC4-SHA"}, | ||||
| 	0X0006: {Name: "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5", ShortName: "EXP-RC2-CBC-MD5"}, | ||||
| 	0X0007: {Name: "TLS_RSA_WITH_IDEA_CBC_SHA", ShortName: "IDEA-CBC-SHA"}, | ||||
| 	0X0008: {Name: "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA", ShortName: "EXP-DES-CBC-SHA"}, | ||||
| 	0X0009: {Name: "TLS_RSA_WITH_DES_CBC_SHA", ShortName: "DES-CBC-SHA"}, | ||||
| 	0X000A: {Name: "TLS_RSA_WITH_3DES_EDE_CBC_SHA", ShortName: "DES-CBC3-SHA"}, | ||||
| 	0X000B: {Name: "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA", ShortName: "EXP-DH-DSS-DES-CBC-SHA"}, | ||||
| 	0X000C: {Name: "TLS_DH_DSS_WITH_DES_CBC_SHA", ShortName: "DH-DSS-DES-CBC-SHA"}, | ||||
| 	0X000D: {Name: "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA", ShortName: "DH-DSS-DES-CBC3-SHA"}, | ||||
| 	0X000E: {Name: "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA", ShortName: "EXP-DH-RSA-DES-CBC-SHA"}, | ||||
| 	0X000F: {Name: "TLS_DH_RSA_WITH_DES_CBC_SHA", ShortName: "DH-RSA-DES-CBC-SHA"}, | ||||
| 	0X0010: {Name: "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA", ShortName: "DH-RSA-DES-CBC3-SHA"}, | ||||
| 	0X0011: {Name: "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", ShortName: "EXP-EDH-DSS-DES-CBC-SHA", ForwardSecret: true}, | ||||
| 	0X0012: {Name: "TLS_DHE_DSS_WITH_DES_CBC_SHA", ShortName: "EDH-DSS-DES-CBC-SHA", ForwardSecret: true}, | ||||
| 	0X0013: {Name: "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA", ShortName: "EDH-DSS-DES-CBC3-SHA", ForwardSecret: true}, | ||||
| 	0X0014: {Name: "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", ShortName: "EXP-EDH-RSA-DES-CBC-SHA", ForwardSecret: true}, | ||||
| 	0X0015: {Name: "TLS_DHE_RSA_WITH_DES_CBC_SHA", ShortName: "EDH-RSA-DES-CBC-SHA", ForwardSecret: true}, | ||||
| 	0X0016: {Name: "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA", ShortName: "EDH-RSA-DES-CBC3-SHA", ForwardSecret: true}, | ||||
| 	0X0017: {Name: "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5"}, | ||||
| 	0X0018: {Name: "TLS_DH_anon_WITH_RC4_128_MD5"}, | ||||
| 	0X0019: {Name: "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA"}, | ||||
| 	0X001A: {Name: "TLS_DH_anon_WITH_DES_CBC_SHA"}, | ||||
| 	0X001B: {Name: "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"}, | ||||
| 	0X001E: {Name: "TLS_KRB5_WITH_DES_CBC_SHA"}, | ||||
| 	0X001F: {Name: "TLS_KRB5_WITH_3DES_EDE_CBC_SHA"}, | ||||
| 	0X0020: {Name: "TLS_KRB5_WITH_RC4_128_SHA"}, | ||||
| 	0X0021: {Name: "TLS_KRB5_WITH_IDEA_CBC_SHA"}, | ||||
| 	0X0022: {Name: "TLS_KRB5_WITH_DES_CBC_MD5"}, | ||||
| 	0X0023: {Name: "TLS_KRB5_WITH_3DES_EDE_CBC_MD5"}, | ||||
| 	0X0024: {Name: "TLS_KRB5_WITH_RC4_128_MD5"}, | ||||
| 	0X0025: {Name: "TLS_KRB5_WITH_IDEA_CBC_MD5"}, | ||||
| 	0X0026: {Name: "TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA"}, | ||||
| 	0X0027: {Name: "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA"}, | ||||
| 	0X0028: {Name: "TLS_KRB5_EXPORT_WITH_RC4_40_SHA"}, | ||||
| 	0X0029: {Name: "TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5"}, | ||||
| 	0X002A: {Name: "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5"}, | ||||
| 	0X002B: {Name: "TLS_KRB5_EXPORT_WITH_RC4_40_MD5"}, | ||||
| 	0X002C: {Name: "TLS_PSK_WITH_NULL_SHA"}, | ||||
| 	0X002D: {Name: "TLS_DHE_PSK_WITH_NULL_SHA", ForwardSecret: true}, | ||||
| 	0X002E: {Name: "TLS_RSA_PSK_WITH_NULL_SHA"}, | ||||
| 	0X002F: {Name: "TLS_RSA_WITH_AES_128_CBC_SHA", ShortName: "AES128-SHA"}, | ||||
| 	0X0030: {Name: "TLS_DH_DSS_WITH_AES_128_CBC_SHA", ShortName: "DH-DSS-AES128-SHA"}, | ||||
| 	0X0031: {Name: "TLS_DH_RSA_WITH_AES_128_CBC_SHA", ShortName: "DH-RSA-AES128-SHA"}, | ||||
| 	0X0032: {Name: "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", ShortName: "DHE-DSS-AES128-SHA", ForwardSecret: true}, | ||||
| 	0X0033: {Name: "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", ShortName: "DHE-RSA-AES128-SHA", ForwardSecret: true}, | ||||
| 	0X0034: {Name: "TLS_DH_anon_WITH_AES_128_CBC_SHA"}, | ||||
| 	0X0035: {Name: "TLS_RSA_WITH_AES_256_CBC_SHA", ShortName: "AES256-SHA"}, | ||||
| 	0X0036: {Name: "TLS_DH_DSS_WITH_AES_256_CBC_SHA", ShortName: "DH-DSS-AES256-SHA"}, | ||||
| 	0X0037: {Name: "TLS_DH_RSA_WITH_AES_256_CBC_SHA", ShortName: "DH-RSA-AES256-SHA"}, | ||||
| 	0X0038: {Name: "TLS_DHE_DSS_WITH_AES_256_CBC_SHA", ShortName: "DHE-DSS-AES256-SHA", ForwardSecret: true}, | ||||
| 	0X0039: {Name: "TLS_DHE_RSA_WITH_AES_256_CBC_SHA", ShortName: "DHE-RSA-AES256-SHA", ForwardSecret: true}, | ||||
| 	0X003A: {Name: "TLS_DH_anon_WITH_AES_256_CBC_SHA"}, | ||||
| 	0X003B: {Name: "TLS_RSA_WITH_NULL_SHA256"}, | ||||
| 	0X003C: {Name: "TLS_RSA_WITH_AES_128_CBC_SHA256", ShortName: "AES128-SHA256"}, | ||||
| 	0X003D: {Name: "TLS_RSA_WITH_AES_256_CBC_SHA256", ShortName: "AES256-SHA256"}, | ||||
| 	0X003E: {Name: "TLS_DH_DSS_WITH_AES_128_CBC_SHA256", ShortName: "DH-DSS-AES128-SHA256"}, | ||||
| 	0X003F: {Name: "TLS_DH_RSA_WITH_AES_128_CBC_SHA256", ShortName: "DH-RSA-AES128-SHA256"}, | ||||
| 	0X0040: {Name: "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256", ShortName: "DHE-DSS-AES128-SHA256", ForwardSecret: true}, | ||||
| 	0X0041: {Name: "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA", ShortName: "CAMELLIA128-SHA"}, | ||||
| 	0X0042: {Name: "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA", ShortName: "DH-DSS-CAMELLIA128-SHA"}, | ||||
| 	0X0043: {Name: "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA", ShortName: "DH-RSA-CAMELLIA128-SHA"}, | ||||
| 	0X0044: {Name: "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA", ShortName: "DHE-DSS-CAMELLIA128-SHA", ForwardSecret: true}, | ||||
| 	0X0045: {Name: "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA", ShortName: "DHE-RSA-CAMELLIA128-SHA", ForwardSecret: true}, | ||||
| 	0X0046: {Name: "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA"}, | ||||
| 	0X0067: {Name: "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256", ShortName: "DHE-RSA-AES128-SHA256", ForwardSecret: true}, | ||||
| 	0X0068: {Name: "TLS_DH_DSS_WITH_AES_256_CBC_SHA256", ShortName: "DH-DSS-AES256-SHA256"}, | ||||
| 	0X0069: {Name: "TLS_DH_RSA_WITH_AES_256_CBC_SHA256", ShortName: "DH-RSA-AES256-SHA256"}, | ||||
| 	0X006A: {Name: "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256", ShortName: "DHE-DSS-AES256-SHA256", ForwardSecret: true}, | ||||
| 	0X006B: {Name: "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256", ShortName: "DHE-RSA-AES256-SHA256", ForwardSecret: true}, | ||||
| 	0X006C: {Name: "TLS_DH_anon_WITH_AES_128_CBC_SHA256"}, | ||||
| 	0X006D: {Name: "TLS_DH_anon_WITH_AES_256_CBC_SHA256"}, | ||||
| 	0X0084: {Name: "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA", ShortName: "CAMELLIA256-SHA"}, | ||||
| 	0X0085: {Name: "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA", ShortName: "DH-DSS-CAMELLIA256-SHA"}, | ||||
| 	0X0086: {Name: "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA", ShortName: "DH-RSA-CAMELLIA256-SHA"}, | ||||
| 	0X0087: {Name: "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA", ShortName: "DHE-DSS-CAMELLIA256-SHA", ForwardSecret: true}, | ||||
| 	0X0088: {Name: "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA", ShortName: "DHE-RSA-CAMELLIA256-SHA", ForwardSecret: true}, | ||||
| 	0X0089: {Name: "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA"}, | ||||
| 	0X008A: {Name: "TLS_PSK_WITH_RC4_128_SHA", ShortName: "PSK-RC4-SHA"}, | ||||
| 	0X008B: {Name: "TLS_PSK_WITH_3DES_EDE_CBC_SHA", ShortName: "PSK-3DES-EDE-CBC-SHA"}, | ||||
| 	0X008C: {Name: "TLS_PSK_WITH_AES_128_CBC_SHA", ShortName: "PSK-AES128-CBC-SHA"}, | ||||
| 	0X008D: {Name: "TLS_PSK_WITH_AES_256_CBC_SHA", ShortName: "PSK-AES256-CBC-SHA"}, | ||||
| 	0X008E: {Name: "TLS_DHE_PSK_WITH_RC4_128_SHA", ForwardSecret: true}, | ||||
| 	0X008F: {Name: "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA", ForwardSecret: true}, | ||||
| 	0X0090: {Name: "TLS_DHE_PSK_WITH_AES_128_CBC_SHA", ForwardSecret: true}, | ||||
| 	0X0091: {Name: "TLS_DHE_PSK_WITH_AES_256_CBC_SHA", ForwardSecret: true}, | ||||
| 	0X0092: {Name: "TLS_RSA_PSK_WITH_RC4_128_SHA"}, | ||||
| 	0X0093: {Name: "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA"}, | ||||
| 	0X0094: {Name: "TLS_RSA_PSK_WITH_AES_128_CBC_SHA"}, | ||||
| 	0X0095: {Name: "TLS_RSA_PSK_WITH_AES_256_CBC_SHA"}, | ||||
| 	0X0096: {Name: "TLS_RSA_WITH_SEED_CBC_SHA", ShortName: "SEED-SHA"}, | ||||
| 	0X0097: {Name: "TLS_DH_DSS_WITH_SEED_CBC_SHA", ShortName: "DH-DSS-SEED-SHA"}, | ||||
| 	0X0098: {Name: "TLS_DH_RSA_WITH_SEED_CBC_SHA", ShortName: "DH-RSA-SEED-SHA"}, | ||||
| 	0X0099: {Name: "TLS_DHE_DSS_WITH_SEED_CBC_SHA", ShortName: "DHE-DSS-SEED-SHA", ForwardSecret: true}, | ||||
| 	0X009A: {Name: "TLS_DHE_RSA_WITH_SEED_CBC_SHA", ShortName: "DHE-RSA-SEED-SHA", ForwardSecret: true}, | ||||
| 	0X009B: {Name: "TLS_DH_anon_WITH_SEED_CBC_SHA"}, | ||||
| 	0X009C: {Name: "TLS_RSA_WITH_AES_128_GCM_SHA256", ShortName: "AES128-GCM-SHA256"}, | ||||
| 	0X009D: {Name: "TLS_RSA_WITH_AES_256_GCM_SHA384", ShortName: "AES256-GCM-SHA384"}, | ||||
| 	0X009E: {Name: "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", ShortName: "DHE-RSA-AES128-GCM-SHA256", ForwardSecret: true}, | ||||
| 	0X009F: {Name: "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", ShortName: "DHE-RSA-AES256-GCM-SHA384", ForwardSecret: true}, | ||||
| 	0X00A0: {Name: "TLS_DH_RSA_WITH_AES_128_GCM_SHA256", ShortName: "DH-RSA-AES128-GCM-SHA256"}, | ||||
| 	0X00A1: {Name: "TLS_DH_RSA_WITH_AES_256_GCM_SHA384", ShortName: "DH-RSA-AES256-GCM-SHA384"}, | ||||
| 	0X00A2: {Name: "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", ShortName: "DHE-DSS-AES128-GCM-SHA256", ForwardSecret: true}, | ||||
| 	0X00A3: {Name: "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", ShortName: "DHE-DSS-AES256-GCM-SHA384", ForwardSecret: true}, | ||||
| 	0X00A4: {Name: "TLS_DH_DSS_WITH_AES_128_GCM_SHA256", ShortName: "DH-DSS-AES128-GCM-SHA256"}, | ||||
| 	0X00A5: {Name: "TLS_DH_DSS_WITH_AES_256_GCM_SHA384", ShortName: "DH-DSS-AES256-GCM-SHA384"}, | ||||
| 	0X00A6: {Name: "TLS_DH_anon_WITH_AES_128_GCM_SHA256"}, | ||||
| 	0X00A7: {Name: "TLS_DH_anon_WITH_AES_256_GCM_SHA384"}, | ||||
| 	0X00A8: {Name: "TLS_PSK_WITH_AES_128_GCM_SHA256"}, | ||||
| 	0X00A9: {Name: "TLS_PSK_WITH_AES_256_GCM_SHA384"}, | ||||
| 	0X00AA: {Name: "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256", ForwardSecret: true}, | ||||
| 	0X00AB: {Name: "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384", ForwardSecret: true}, | ||||
| 	0X00AC: {Name: "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256"}, | ||||
| 	0X00AD: {Name: "TLS_RSA_PSK_WITH_AES_256_GCM_SHA384"}, | ||||
| 	0X00AE: {Name: "TLS_PSK_WITH_AES_128_CBC_SHA256"}, | ||||
| 	0X00AF: {Name: "TLS_PSK_WITH_AES_256_CBC_SHA384"}, | ||||
| 	0X00B0: {Name: "TLS_PSK_WITH_NULL_SHA256"}, | ||||
| 	0X00B1: {Name: "TLS_PSK_WITH_NULL_SHA384"}, | ||||
| 	0X00B2: {Name: "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256", ForwardSecret: true}, | ||||
| 	0X00B3: {Name: "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384", ForwardSecret: true}, | ||||
| 	0X00B4: {Name: "TLS_DHE_PSK_WITH_NULL_SHA256", ForwardSecret: true}, | ||||
| 	0X00B5: {Name: "TLS_DHE_PSK_WITH_NULL_SHA384", ForwardSecret: true}, | ||||
| 	0X00B6: {Name: "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256"}, | ||||
| 	0X00B7: {Name: "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384"}, | ||||
| 	0X00B8: {Name: "TLS_RSA_PSK_WITH_NULL_SHA256"}, | ||||
| 	0X00B9: {Name: "TLS_RSA_PSK_WITH_NULL_SHA384"}, | ||||
| 	0X00BA: {Name: "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256"}, | ||||
| 	0X00BB: {Name: "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256"}, | ||||
| 	0X00BC: {Name: "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256"}, | ||||
| 	0X00BD: {Name: "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256", ForwardSecret: true}, | ||||
| 	0X00BE: {Name: "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256", ForwardSecret: true}, | ||||
| 	0X00BF: {Name: "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256"}, | ||||
| 	0X00C0: {Name: "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256"}, | ||||
| 	0X00C1: {Name: "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256"}, | ||||
| 	0X00C2: {Name: "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256"}, | ||||
| 	0X00C3: {Name: "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256", ForwardSecret: true}, | ||||
| 	0X00C4: {Name: "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256", ForwardSecret: true}, | ||||
| 	0X00C5: {Name: "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256"}, | ||||
| 	0X00FF: {Name: "TLS_EMPTY_RENEGOTIATION_INFO_SCSV"}, | ||||
| 	0XC001: {Name: "TLS_ECDH_ECDSA_WITH_NULL_SHA", EllipticCurve: true}, | ||||
| 	0XC002: {Name: "TLS_ECDH_ECDSA_WITH_RC4_128_SHA", ShortName: "ECDH-ECDSA-RC4-SHA", EllipticCurve: true}, | ||||
| 	0XC003: {Name: "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA", ShortName: "ECDH-ECDSA-DES-CBC3-SHA", EllipticCurve: true}, | ||||
| 	0XC004: {Name: "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA", ShortName: "ECDH-ECDSA-AES128-SHA", EllipticCurve: true}, | ||||
| 	0XC005: {Name: "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA", ShortName: "ECDH-ECDSA-AES256-SHA", EllipticCurve: true}, | ||||
| 	0XC006: {Name: "TLS_ECDHE_ECDSA_WITH_NULL_SHA", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC007: {Name: "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", ShortName: "ECDHE-ECDSA-RC4-SHA", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC008: {Name: "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", ShortName: "ECDHE-ECDSA-DES-CBC3-SHA", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC009: {Name: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", ShortName: "ECDHE-ECDSA-AES128-SHA", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC00A: {Name: "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", ShortName: "ECDHE-ECDSA-AES256-SHA", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC00B: {Name: "TLS_ECDH_RSA_WITH_NULL_SHA", EllipticCurve: true}, | ||||
| 	0XC00C: {Name: "TLS_ECDH_RSA_WITH_RC4_128_SHA", ShortName: "ECDH-RSA-RC4-SHA", EllipticCurve: true}, | ||||
| 	0XC00D: {Name: "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA", ShortName: "ECDH-RSA-DES-CBC3-SHA", EllipticCurve: true}, | ||||
| 	0XC00E: {Name: "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA", ShortName: "ECDH-RSA-AES128-SHA", EllipticCurve: true}, | ||||
| 	0XC00F: {Name: "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA", ShortName: "ECDH-RSA-AES256-SHA", EllipticCurve: true}, | ||||
| 	0XC010: {Name: "TLS_ECDHE_RSA_WITH_NULL_SHA", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC011: {Name: "TLS_ECDHE_RSA_WITH_RC4_128_SHA", ShortName: "ECDHE-RSA-RC4-SHA", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC012: {Name: "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", ShortName: "ECDHE-RSA-DES-CBC3-SHA", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC013: {Name: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", ShortName: "ECDHE-RSA-AES128-SHA", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC014: {Name: "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", ShortName: "ECDHE-RSA-AES256-SHA", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC015: {Name: "TLS_ECDH_anon_WITH_NULL_SHA", EllipticCurve: true}, | ||||
| 	0XC016: {Name: "TLS_ECDH_anon_WITH_RC4_128_SHA", EllipticCurve: true}, | ||||
| 	0XC017: {Name: "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA", EllipticCurve: true}, | ||||
| 	0XC018: {Name: "TLS_ECDH_anon_WITH_AES_128_CBC_SHA", EllipticCurve: true}, | ||||
| 	0XC019: {Name: "TLS_ECDH_anon_WITH_AES_256_CBC_SHA", EllipticCurve: true}, | ||||
| 	0XC01A: {Name: "TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA", ShortName: "SRP-3DES-EDE-CBC-SHA"}, | ||||
| 	0XC01B: {Name: "TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA", ShortName: "SRP-RSA-3DES-EDE-CBC-SHA"}, | ||||
| 	0XC01C: {Name: "TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA", ShortName: "SRP-DSS-3DES-EDE-CBC-SHA"}, | ||||
| 	0XC01D: {Name: "TLS_SRP_SHA_WITH_AES_128_CBC_SHA", ShortName: "SRP-AES-128-CBC-SHA"}, | ||||
| 	0XC01E: {Name: "TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA", ShortName: "SRP-RSA-AES-128-CBC-SHA"}, | ||||
| 	0XC01F: {Name: "TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA", ShortName: "SRP-DSS-AES-128-CBC-SHA"}, | ||||
| 	0XC020: {Name: "TLS_SRP_SHA_WITH_AES_256_CBC_SHA", ShortName: "SRP-AES-256-CBC-SHA"}, | ||||
| 	0XC021: {Name: "TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA", ShortName: "SRP-RSA-AES-256-CBC-SHA"}, | ||||
| 	0XC022: {Name: "TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA", ShortName: "SRP-DSS-AES-256-CBC-SHA"}, | ||||
| 	0XC023: {Name: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", ShortName: "ECDHE-ECDSA-AES128-SHA256", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC024: {Name: "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", ShortName: "ECDHE-ECDSA-AES256-SHA384", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC025: {Name: "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256", ShortName: "ECDH-ECDSA-AES128-SHA256", EllipticCurve: true}, | ||||
| 	0XC026: {Name: "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384", ShortName: "ECDH-ECDSA-AES256-SHA384", EllipticCurve: true}, | ||||
| 	0XC027: {Name: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", ShortName: "ECDHE-RSA-AES128-SHA256", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC028: {Name: "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", ShortName: "ECDHE-RSA-AES256-SHA384", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC029: {Name: "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256", ShortName: "ECDH-RSA-AES128-SHA256", EllipticCurve: true}, | ||||
| 	0XC02A: {Name: "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384", ShortName: "ECDH-RSA-AES256-SHA384", EllipticCurve: true}, | ||||
| 	0XC02B: {Name: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", ShortName: "ECDHE-ECDSA-AES128-GCM-SHA256", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC02C: {Name: "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", ShortName: "ECDHE-ECDSA-AES256-GCM-SHA384", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC02D: {Name: "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", ShortName: "ECDH-ECDSA-AES128-GCM-SHA256", EllipticCurve: true}, | ||||
| 	0XC02E: {Name: "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", ShortName: "ECDH-ECDSA-AES256-GCM-SHA384", EllipticCurve: true}, | ||||
| 	0XC02F: {Name: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", ShortName: "ECDHE-RSA-AES128-GCM-SHA256", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC030: {Name: "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", ShortName: "ECDHE-RSA-AES256-GCM-SHA384", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC031: {Name: "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", ShortName: "ECDH-RSA-AES128-GCM-SHA256", EllipticCurve: true}, | ||||
| 	0XC032: {Name: "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", ShortName: "ECDH-RSA-AES256-GCM-SHA384", EllipticCurve: true}, | ||||
| 	0XC033: {Name: "TLS_ECDHE_PSK_WITH_RC4_128_SHA", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC034: {Name: "TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC035: {Name: "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC036: {Name: "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC037: {Name: "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC038: {Name: "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC039: {Name: "TLS_ECDHE_PSK_WITH_NULL_SHA", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC03A: {Name: "TLS_ECDHE_PSK_WITH_NULL_SHA256", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC03B: {Name: "TLS_ECDHE_PSK_WITH_NULL_SHA384", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC03C: {Name: "TLS_RSA_WITH_ARIA_128_CBC_SHA256"}, | ||||
| 	0XC03D: {Name: "TLS_RSA_WITH_ARIA_256_CBC_SHA384"}, | ||||
| 	0XC03E: {Name: "TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256"}, | ||||
| 	0XC03F: {Name: "TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384"}, | ||||
| 	0XC040: {Name: "TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256"}, | ||||
| 	0XC041: {Name: "TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384"}, | ||||
| 	0XC042: {Name: "TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256", ForwardSecret: true}, | ||||
| 	0XC043: {Name: "TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384", ForwardSecret: true}, | ||||
| 	0XC044: {Name: "TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256", ForwardSecret: true}, | ||||
| 	0XC045: {Name: "TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384", ForwardSecret: true}, | ||||
| 	0XC046: {Name: "TLS_DH_anon_WITH_ARIA_128_CBC_SHA256"}, | ||||
| 	0XC047: {Name: "TLS_DH_anon_WITH_ARIA_256_CBC_SHA384"}, | ||||
| 	0XC048: {Name: "TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC049: {Name: "TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC04A: {Name: "TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256", EllipticCurve: true}, | ||||
| 	0XC04B: {Name: "TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384", EllipticCurve: true}, | ||||
| 	0XC04C: {Name: "TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC04D: {Name: "TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC04E: {Name: "TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256", EllipticCurve: true}, | ||||
| 	0XC04F: {Name: "TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384", EllipticCurve: true}, | ||||
| 	0XC050: {Name: "TLS_RSA_WITH_ARIA_128_GCM_SHA256"}, | ||||
| 	0XC051: {Name: "TLS_RSA_WITH_ARIA_256_GCM_SHA384"}, | ||||
| 	0XC052: {Name: "TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256", ForwardSecret: true}, | ||||
| 	0XC053: {Name: "TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384", ForwardSecret: true}, | ||||
| 	0XC054: {Name: "TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256"}, | ||||
| 	0XC055: {Name: "TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384"}, | ||||
| 	0XC056: {Name: "TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256", ForwardSecret: true}, | ||||
| 	0XC057: {Name: "TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384", ForwardSecret: true}, | ||||
| 	0XC058: {Name: "TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256"}, | ||||
| 	0XC059: {Name: "TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384"}, | ||||
| 	0XC05A: {Name: "TLS_DH_anon_WITH_ARIA_128_GCM_SHA256"}, | ||||
| 	0XC05B: {Name: "TLS_DH_anon_WITH_ARIA_256_GCM_SHA384"}, | ||||
| 	0XC05C: {Name: "TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC05D: {Name: "TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC05E: {Name: "TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256", EllipticCurve: true}, | ||||
| 	0XC05F: {Name: "TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384", EllipticCurve: true}, | ||||
| 	0XC060: {Name: "TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC061: {Name: "TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC062: {Name: "TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256", EllipticCurve: true}, | ||||
| 	0XC063: {Name: "TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384", EllipticCurve: true}, | ||||
| 	0XC064: {Name: "TLS_PSK_WITH_ARIA_128_CBC_SHA256"}, | ||||
| 	0XC065: {Name: "TLS_PSK_WITH_ARIA_256_CBC_SHA384"}, | ||||
| 	0XC066: {Name: "TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256", ForwardSecret: true}, | ||||
| 	0XC067: {Name: "TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384", ForwardSecret: true}, | ||||
| 	0XC068: {Name: "TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256"}, | ||||
| 	0XC069: {Name: "TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384"}, | ||||
| 	0XC06A: {Name: "TLS_PSK_WITH_ARIA_128_GCM_SHA256"}, | ||||
| 	0XC06B: {Name: "TLS_PSK_WITH_ARIA_256_GCM_SHA384"}, | ||||
| 	0XC06C: {Name: "TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256", ForwardSecret: true}, | ||||
| 	0XC06D: {Name: "TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384", ForwardSecret: true}, | ||||
| 	0XC06E: {Name: "TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256"}, | ||||
| 	0XC06F: {Name: "TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384"}, | ||||
| 	0XC070: {Name: "TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC071: {Name: "TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC072: {Name: "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC073: {Name: "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC074: {Name: "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256", EllipticCurve: true}, | ||||
| 	0XC075: {Name: "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384", EllipticCurve: true}, | ||||
| 	0XC076: {Name: "TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC077: {Name: "TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC078: {Name: "TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256", EllipticCurve: true}, | ||||
| 	0XC079: {Name: "TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384", EllipticCurve: true}, | ||||
| 	0XC07A: {Name: "TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256"}, | ||||
| 	0XC07B: {Name: "TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384"}, | ||||
| 	0XC07C: {Name: "TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256", ForwardSecret: true}, | ||||
| 	0XC07D: {Name: "TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384", ForwardSecret: true}, | ||||
| 	0XC07E: {Name: "TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256"}, | ||||
| 	0XC07F: {Name: "TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384"}, | ||||
| 	0XC080: {Name: "TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256", ForwardSecret: true}, | ||||
| 	0XC081: {Name: "TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384", ForwardSecret: true}, | ||||
| 	0XC082: {Name: "TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256"}, | ||||
| 	0XC083: {Name: "TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384"}, | ||||
| 	0XC084: {Name: "TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256"}, | ||||
| 	0XC085: {Name: "TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384"}, | ||||
| 	0XC086: {Name: "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC087: {Name: "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC088: {Name: "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256", EllipticCurve: true}, | ||||
| 	0XC089: {Name: "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384", EllipticCurve: true}, | ||||
| 	0XC08A: {Name: "TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC08B: {Name: "TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC08C: {Name: "TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256", EllipticCurve: true}, | ||||
| 	0XC08D: {Name: "TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384", EllipticCurve: true}, | ||||
| 	0XC08E: {Name: "TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256"}, | ||||
| 	0XC08F: {Name: "TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384"}, | ||||
| 	0XC090: {Name: "TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256", ForwardSecret: true}, | ||||
| 	0XC091: {Name: "TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384", ForwardSecret: true}, | ||||
| 	0XC092: {Name: "TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256"}, | ||||
| 	0XC093: {Name: "TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384"}, | ||||
| 	0XC094: {Name: "TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256"}, | ||||
| 	0XC095: {Name: "TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384"}, | ||||
| 	0XC096: {Name: "TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256", ForwardSecret: true}, | ||||
| 	0XC097: {Name: "TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384", ForwardSecret: true}, | ||||
| 	0XC098: {Name: "TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256"}, | ||||
| 	0XC099: {Name: "TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384"}, | ||||
| 	0XC09A: {Name: "TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC09B: {Name: "TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC09C: {Name: "TLS_RSA_WITH_AES_128_CCM"}, | ||||
| 	0XC09D: {Name: "TLS_RSA_WITH_AES_256_CCM"}, | ||||
| 	0XC09E: {Name: "TLS_DHE_RSA_WITH_AES_128_CCM", ForwardSecret: true}, | ||||
| 	0XC09F: {Name: "TLS_DHE_RSA_WITH_AES_256_CCM", ForwardSecret: true}, | ||||
| 	0XC0A0: {Name: "TLS_RSA_WITH_AES_128_CCM_8"}, | ||||
| 	0XC0A1: {Name: "TLS_RSA_WITH_AES_256_CCM_8"}, | ||||
| 	0XC0A2: {Name: "TLS_DHE_RSA_WITH_AES_128_CCM_8", ForwardSecret: true}, | ||||
| 	0XC0A3: {Name: "TLS_DHE_RSA_WITH_AES_256_CCM_8", ForwardSecret: true}, | ||||
| 	0XC0A4: {Name: "TLS_PSK_WITH_AES_128_CCM"}, | ||||
| 	0XC0A5: {Name: "TLS_PSK_WITH_AES_256_CCM"}, | ||||
| 	0XC0A6: {Name: "TLS_DHE_PSK_WITH_AES_128_CCM", ForwardSecret: true}, | ||||
| 	0XC0A7: {Name: "TLS_DHE_PSK_WITH_AES_256_CCM", ForwardSecret: true}, | ||||
| 	0XC0A8: {Name: "TLS_PSK_WITH_AES_128_CCM_8"}, | ||||
| 	0XC0A9: {Name: "TLS_PSK_WITH_AES_256_CCM_8"}, | ||||
| 	0XC0AA: {Name: "TLS_PSK_DHE_WITH_AES_128_CCM_8", ForwardSecret: true}, | ||||
| 	0XC0AB: {Name: "TLS_PSK_DHE_WITH_AES_256_CCM_8", ForwardSecret: true}, | ||||
| 	0XC0AC: {Name: "TLS_ECDHE_ECDSA_WITH_AES_128_CCM", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC0AD: {Name: "TLS_ECDHE_ECDSA_WITH_AES_256_CCM", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC0AE: {Name: "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XC0AF: {Name: "TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	// Non-IANA standardized cipher suites: | ||||
| 	// ChaCha20, Poly1305 cipher suites are defined in | ||||
| 	// https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04 | ||||
| 	0XCC13: {Name: "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XCC14: {Name: "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", ForwardSecret: true, EllipticCurve: true}, | ||||
| 	0XCC15: {Name: "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256", ForwardSecret: true, EllipticCurve: true}, | ||||
| } | ||||
|  | ||||
| var Curves = map[CurveID]string{ | ||||
| 	0:     "Unassigned", | ||||
| 	1:     "sect163k1", | ||||
| 	2:     "sect163r1", | ||||
| 	3:     "sect163r2", | ||||
| 	4:     "sect193r1", | ||||
| 	5:     "sect193r2", | ||||
| 	6:     "sect233k1", | ||||
| 	7:     "sect233r1", | ||||
| 	8:     "sect239k1", | ||||
| 	9:     "sect283k1", | ||||
| 	10:    "sect283r1", | ||||
| 	11:    "sect409k1", | ||||
| 	12:    "sect409r1", | ||||
| 	13:    "sect571k1", | ||||
| 	14:    "sect571r1", | ||||
| 	15:    "secp160k1", | ||||
| 	16:    "secp160r1", | ||||
| 	17:    "secp160r2", | ||||
| 	18:    "secp192k1", | ||||
| 	19:    "secp192r1", | ||||
| 	20:    "secp224k1", | ||||
| 	21:    "secp224r1", | ||||
| 	22:    "secp256k1", | ||||
| 	23:    "secp256r1", | ||||
| 	24:    "secp384r1", | ||||
| 	25:    "secp521r1", | ||||
| 	26:    "brainpoolP256r1", | ||||
| 	27:    "brainpoolP384r1", | ||||
| 	28:    "brainpoolP512r1", | ||||
| 	65281: "arbitrary_explicit_prime_curves", | ||||
| 	65282: "arbitrary_explicit_char2_curves", | ||||
| } | ||||
							
								
								
									
										109
									
								
								vendor/github.com/cloudflare/cfssl/scan/crypto/tls/cfsslscan_handshake.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								vendor/github.com/cloudflare/cfssl/scan/crypto/tls/cfsslscan_handshake.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,109 @@ | ||||
| package tls | ||||
|  | ||||
| // SayHello constructs a simple Client Hello to a server, parses its serverHelloMsg response | ||||
| // and returns the negotiated ciphersuite ID, and, if an EC cipher suite, the curve ID | ||||
| func (c *Conn) SayHello(newSigAls []SignatureAndHash) (cipherID, curveType uint16, curveID CurveID, version uint16, certs [][]byte, err error) { | ||||
| 	// Set the supported signatures and hashes to the set `newSigAls` | ||||
| 	supportedSignatureAlgorithms := make([]signatureAndHash, len(newSigAls)) | ||||
| 	for i := range newSigAls { | ||||
| 		supportedSignatureAlgorithms[i] = newSigAls[i].internal() | ||||
| 	} | ||||
|  | ||||
| 	hello := &clientHelloMsg{ | ||||
| 		vers:                c.config.maxVersion(), | ||||
| 		compressionMethods:  []uint8{compressionNone}, | ||||
| 		random:              make([]byte, 32), | ||||
| 		ocspStapling:        true, | ||||
| 		serverName:          c.config.ServerName, | ||||
| 		supportedCurves:     c.config.curvePreferences(), | ||||
| 		supportedPoints:     []uint8{pointFormatUncompressed}, | ||||
| 		nextProtoNeg:        len(c.config.NextProtos) > 0, | ||||
| 		secureRenegotiation: true, | ||||
| 		cipherSuites:        c.config.cipherSuites(), | ||||
| 		signatureAndHashes:  supportedSignatureAlgorithms, | ||||
| 	} | ||||
| 	serverHello, err := c.sayHello(hello) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	// Prime the connection, if necessary, for key | ||||
| 	// exchange messages by reading off the certificate | ||||
| 	// message and, if necessary, the OCSP stapling | ||||
| 	// message | ||||
| 	var msg interface{} | ||||
| 	msg, err = c.readHandshake() | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	certMsg, ok := msg.(*certificateMsg) | ||||
| 	if !ok || len(certMsg.certificates) == 0 { | ||||
| 		err = unexpectedMessageError(certMsg, msg) | ||||
| 		return | ||||
| 	} | ||||
| 	certs = certMsg.certificates | ||||
|  | ||||
| 	if serverHello.ocspStapling { | ||||
| 		msg, err = c.readHandshake() | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 		certStatusMsg, ok := msg.(*certificateStatusMsg) | ||||
| 		if !ok { | ||||
| 			err = unexpectedMessageError(certStatusMsg, msg) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if CipherSuites[serverHello.cipherSuite].EllipticCurve { | ||||
|  | ||||
| 		var skx *serverKeyExchangeMsg | ||||
| 		skx, err = c.exchangeKeys() | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 		if skx.raw[0] != typeServerKeyExchange { | ||||
| 			err = unexpectedMessageError(skx, msg) | ||||
| 			return | ||||
| 		} | ||||
| 		if len(skx.key) < 4 { | ||||
| 			err = unexpectedMessageError(skx, msg) | ||||
| 			return | ||||
| 		} | ||||
| 		curveType = uint16(skx.key[0]) | ||||
| 		// If we have a named curve, report which one it is. | ||||
| 		if curveType == 3 { | ||||
| 			curveID = CurveID(skx.key[1])<<8 | CurveID(skx.key[2]) | ||||
| 		} | ||||
| 	} | ||||
| 	cipherID, version = serverHello.cipherSuite, serverHello.vers | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // sayHello is the backend to SayHello that returns a full serverHelloMsg for processing. | ||||
| func (c *Conn) sayHello(hello *clientHelloMsg) (serverHello *serverHelloMsg, err error) { | ||||
| 	c.writeRecord(recordTypeHandshake, hello.marshal()) | ||||
| 	msg, err := c.readHandshake() | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	serverHello, ok := msg.(*serverHelloMsg) | ||||
| 	if !ok { | ||||
| 		return nil, unexpectedMessageError(serverHello, msg) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // exchangeKeys continues the handshake to receive the serverKeyExchange message, | ||||
| // from which we can extract elliptic curve parameters | ||||
| func (c *Conn) exchangeKeys() (serverKeyExchange *serverKeyExchangeMsg, err error) { | ||||
| 	msg, err := c.readHandshake() | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	serverKeyExchange, ok := msg.(*serverKeyExchangeMsg) | ||||
| 	if !ok { | ||||
| 		return nil, unexpectedMessageError(serverKeyExchange, msg) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										289
									
								
								vendor/github.com/cloudflare/cfssl/scan/crypto/tls/cipher_suites.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										289
									
								
								vendor/github.com/cloudflare/cfssl/scan/crypto/tls/cipher_suites.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,289 @@ | ||||
| // Copyright 2010 The Go Authors. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package tls | ||||
|  | ||||
| import ( | ||||
| 	"crypto/aes" | ||||
| 	"crypto/cipher" | ||||
| 	"crypto/des" | ||||
| 	"crypto/hmac" | ||||
| 	"crypto/rc4" | ||||
| 	"crypto/sha1" | ||||
| 	"crypto/x509" | ||||
| 	"hash" | ||||
| ) | ||||
|  | ||||
| // a keyAgreement implements the client and server side of a TLS key agreement | ||||
| // protocol by generating and processing key exchange messages. | ||||
| type keyAgreement interface { | ||||
| 	// On the server side, the first two methods are called in order. | ||||
|  | ||||
| 	// In the case that the key agreement protocol doesn't use a | ||||
| 	// ServerKeyExchange message, generateServerKeyExchange can return nil, | ||||
| 	// nil. | ||||
| 	generateServerKeyExchange(*Config, *Certificate, *clientHelloMsg, *serverHelloMsg) (*serverKeyExchangeMsg, error) | ||||
| 	processClientKeyExchange(*Config, *Certificate, *clientKeyExchangeMsg, uint16) ([]byte, error) | ||||
|  | ||||
| 	// On the client side, the next two methods are called in order. | ||||
|  | ||||
| 	// This method may not be called if the server doesn't send a | ||||
| 	// ServerKeyExchange message. | ||||
| 	processServerKeyExchange(*Config, *clientHelloMsg, *serverHelloMsg, *x509.Certificate, *serverKeyExchangeMsg) error | ||||
| 	generateClientKeyExchange(*Config, *clientHelloMsg, *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) | ||||
| } | ||||
|  | ||||
| const ( | ||||
| 	// suiteECDH indicates that the cipher suite involves elliptic curve | ||||
| 	// Diffie-Hellman. This means that it should only be selected when the | ||||
| 	// client indicates that it supports ECC with a curve and point format | ||||
| 	// that we're happy with. | ||||
| 	suiteECDHE = 1 << iota | ||||
| 	// suiteECDSA indicates that the cipher suite involves an ECDSA | ||||
| 	// signature and therefore may only be selected when the server's | ||||
| 	// certificate is ECDSA. If this is not set then the cipher suite is | ||||
| 	// RSA based. | ||||
| 	suiteECDSA | ||||
| 	// suiteTLS12 indicates that the cipher suite should only be advertised | ||||
| 	// and accepted when using TLS 1.2. | ||||
| 	suiteTLS12 | ||||
| 	// suiteSHA384 indicates that the cipher suite uses SHA384 as the | ||||
| 	// handshake hash. | ||||
| 	suiteSHA384 | ||||
| 	// suiteDefaultOff indicates that this cipher suite is not included by | ||||
| 	// default. | ||||
| 	suiteDefaultOff | ||||
| ) | ||||
|  | ||||
| // A cipherSuite is a specific combination of key agreement, cipher and MAC | ||||
| // function. All cipher suites currently assume RSA key agreement. | ||||
| type cipherSuite struct { | ||||
| 	id uint16 | ||||
| 	// the lengths, in bytes, of the key material needed for each component. | ||||
| 	keyLen int | ||||
| 	macLen int | ||||
| 	ivLen  int | ||||
| 	ka     func(version uint16) keyAgreement | ||||
| 	// flags is a bitmask of the suite* values, above. | ||||
| 	flags  int | ||||
| 	cipher func(key, iv []byte, isRead bool) interface{} | ||||
| 	mac    func(version uint16, macKey []byte) macFunction | ||||
| 	aead   func(key, fixedNonce []byte) cipher.AEAD | ||||
| } | ||||
|  | ||||
| var cipherSuites = []*cipherSuite{ | ||||
| 	// Ciphersuite order is chosen so that ECDHE comes before plain RSA | ||||
| 	// and RC4 comes before AES (because of the Lucky13 attack). | ||||
| 	{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadAESGCM}, | ||||
| 	{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadAESGCM}, | ||||
| 	{TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM}, | ||||
| 	{TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM}, | ||||
| 	{TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, suiteECDHE | suiteDefaultOff, cipherRC4, macSHA1, nil}, | ||||
| 	{TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteDefaultOff, cipherRC4, macSHA1, nil}, | ||||
| 	{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil}, | ||||
| 	{TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil}, | ||||
| 	{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil}, | ||||
| 	{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil}, | ||||
| 	{TLS_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, rsaKA, suiteTLS12, nil, nil, aeadAESGCM}, | ||||
| 	{TLS_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, rsaKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM}, | ||||
| 	{TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, suiteDefaultOff, cipherRC4, macSHA1, nil}, | ||||
| 	{TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil}, | ||||
| 	{TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil}, | ||||
| 	{TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, suiteECDHE, cipher3DES, macSHA1, nil}, | ||||
| 	{TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, 0, cipher3DES, macSHA1, nil}, | ||||
| } | ||||
|  | ||||
| func cipherRC4(key, iv []byte, isRead bool) interface{} { | ||||
| 	cipher, _ := rc4.NewCipher(key) | ||||
| 	return cipher | ||||
| } | ||||
|  | ||||
| func cipher3DES(key, iv []byte, isRead bool) interface{} { | ||||
| 	block, _ := des.NewTripleDESCipher(key) | ||||
| 	if isRead { | ||||
| 		return cipher.NewCBCDecrypter(block, iv) | ||||
| 	} | ||||
| 	return cipher.NewCBCEncrypter(block, iv) | ||||
| } | ||||
|  | ||||
| func cipherAES(key, iv []byte, isRead bool) interface{} { | ||||
| 	block, _ := aes.NewCipher(key) | ||||
| 	if isRead { | ||||
| 		return cipher.NewCBCDecrypter(block, iv) | ||||
| 	} | ||||
| 	return cipher.NewCBCEncrypter(block, iv) | ||||
| } | ||||
|  | ||||
| // macSHA1 returns a macFunction for the given protocol version. | ||||
| func macSHA1(version uint16, key []byte) macFunction { | ||||
| 	if version == VersionSSL30 { | ||||
| 		mac := ssl30MAC{ | ||||
| 			h:   sha1.New(), | ||||
| 			key: make([]byte, len(key)), | ||||
| 		} | ||||
| 		copy(mac.key, key) | ||||
| 		return mac | ||||
| 	} | ||||
| 	return tls10MAC{hmac.New(sha1.New, key)} | ||||
| } | ||||
|  | ||||
| type macFunction interface { | ||||
| 	Size() int | ||||
| 	MAC(digestBuf, seq, header, data []byte) []byte | ||||
| } | ||||
|  | ||||
| // fixedNonceAEAD wraps an AEAD and prefixes a fixed portion of the nonce to | ||||
| // each call. | ||||
| type fixedNonceAEAD struct { | ||||
| 	// sealNonce and openNonce are buffers where the larger nonce will be | ||||
| 	// constructed. Since a seal and open operation may be running | ||||
| 	// concurrently, there is a separate buffer for each. | ||||
| 	sealNonce, openNonce []byte | ||||
| 	aead                 cipher.AEAD | ||||
| } | ||||
|  | ||||
| func (f *fixedNonceAEAD) NonceSize() int { return 8 } | ||||
| func (f *fixedNonceAEAD) Overhead() int  { return f.aead.Overhead() } | ||||
|  | ||||
| func (f *fixedNonceAEAD) Seal(out, nonce, plaintext, additionalData []byte) []byte { | ||||
| 	copy(f.sealNonce[len(f.sealNonce)-8:], nonce) | ||||
| 	return f.aead.Seal(out, f.sealNonce, plaintext, additionalData) | ||||
| } | ||||
|  | ||||
| func (f *fixedNonceAEAD) Open(out, nonce, plaintext, additionalData []byte) ([]byte, error) { | ||||
| 	copy(f.openNonce[len(f.openNonce)-8:], nonce) | ||||
| 	return f.aead.Open(out, f.openNonce, plaintext, additionalData) | ||||
| } | ||||
|  | ||||
| func aeadAESGCM(key, fixedNonce []byte) cipher.AEAD { | ||||
| 	aes, err := aes.NewCipher(key) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	aead, err := cipher.NewGCM(aes) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
|  | ||||
| 	nonce1, nonce2 := make([]byte, 12), make([]byte, 12) | ||||
| 	copy(nonce1, fixedNonce) | ||||
| 	copy(nonce2, fixedNonce) | ||||
|  | ||||
| 	return &fixedNonceAEAD{nonce1, nonce2, aead} | ||||
| } | ||||
|  | ||||
| // ssl30MAC implements the SSLv3 MAC function, as defined in | ||||
| // www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt section 5.2.3.1 | ||||
| type ssl30MAC struct { | ||||
| 	h   hash.Hash | ||||
| 	key []byte | ||||
| } | ||||
|  | ||||
| func (s ssl30MAC) Size() int { | ||||
| 	return s.h.Size() | ||||
| } | ||||
|  | ||||
| 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} | ||||
|  | ||||
| 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} | ||||
|  | ||||
| func (s ssl30MAC) MAC(digestBuf, seq, header, data []byte) []byte { | ||||
| 	padLength := 48 | ||||
| 	if s.h.Size() == 20 { | ||||
| 		padLength = 40 | ||||
| 	} | ||||
|  | ||||
| 	s.h.Reset() | ||||
| 	s.h.Write(s.key) | ||||
| 	s.h.Write(ssl30Pad1[:padLength]) | ||||
| 	s.h.Write(seq) | ||||
| 	s.h.Write(header[:1]) | ||||
| 	s.h.Write(header[3:5]) | ||||
| 	s.h.Write(data) | ||||
| 	digestBuf = s.h.Sum(digestBuf[:0]) | ||||
|  | ||||
| 	s.h.Reset() | ||||
| 	s.h.Write(s.key) | ||||
| 	s.h.Write(ssl30Pad2[:padLength]) | ||||
| 	s.h.Write(digestBuf) | ||||
| 	return s.h.Sum(digestBuf[:0]) | ||||
| } | ||||
|  | ||||
| // tls10MAC implements the TLS 1.0 MAC function. RFC 2246, section 6.2.3. | ||||
| type tls10MAC struct { | ||||
| 	h hash.Hash | ||||
| } | ||||
|  | ||||
| func (s tls10MAC) Size() int { | ||||
| 	return s.h.Size() | ||||
| } | ||||
|  | ||||
| func (s tls10MAC) MAC(digestBuf, seq, header, data []byte) []byte { | ||||
| 	s.h.Reset() | ||||
| 	s.h.Write(seq) | ||||
| 	s.h.Write(header) | ||||
| 	s.h.Write(data) | ||||
| 	return s.h.Sum(digestBuf[:0]) | ||||
| } | ||||
|  | ||||
| func rsaKA(version uint16) keyAgreement { | ||||
| 	return rsaKeyAgreement{} | ||||
| } | ||||
|  | ||||
| func ecdheECDSAKA(version uint16) keyAgreement { | ||||
| 	return &ecdheKeyAgreement{ | ||||
| 		sigType: signatureECDSA, | ||||
| 		version: version, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func ecdheRSAKA(version uint16) keyAgreement { | ||||
| 	return &ecdheKeyAgreement{ | ||||
| 		sigType: signatureRSA, | ||||
| 		version: version, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // mutualCipherSuite returns a cipherSuite given a list of supported | ||||
| // ciphersuites and the id requested by the peer. | ||||
| func mutualCipherSuite(have []uint16, want uint16) *cipherSuite { | ||||
| 	for _, id := range have { | ||||
| 		if id == want { | ||||
| 			for _, suite := range cipherSuites { | ||||
| 				if suite.id == want { | ||||
| 					return suite | ||||
| 				} | ||||
| 			} | ||||
| 			return nil | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // A list of the possible cipher suite ids. Taken from | ||||
| // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml | ||||
| const ( | ||||
| 	TLS_RSA_WITH_RC4_128_SHA                uint16 = 0x0005 | ||||
| 	TLS_RSA_WITH_3DES_EDE_CBC_SHA           uint16 = 0x000a | ||||
| 	TLS_RSA_WITH_AES_128_CBC_SHA            uint16 = 0x002f | ||||
| 	TLS_RSA_WITH_AES_256_CBC_SHA            uint16 = 0x0035 | ||||
| 	TLS_RSA_WITH_AES_128_GCM_SHA256         uint16 = 0x009c | ||||
| 	TLS_RSA_WITH_AES_256_GCM_SHA384         uint16 = 0x009d | ||||
| 	TLS_ECDHE_ECDSA_WITH_RC4_128_SHA        uint16 = 0xc007 | ||||
| 	TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA    uint16 = 0xc009 | ||||
| 	TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA    uint16 = 0xc00a | ||||
| 	TLS_ECDHE_RSA_WITH_RC4_128_SHA          uint16 = 0xc011 | ||||
| 	TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA     uint16 = 0xc012 | ||||
| 	TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA      uint16 = 0xc013 | ||||
| 	TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA      uint16 = 0xc014 | ||||
| 	TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256   uint16 = 0xc02f | ||||
| 	TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02b | ||||
| 	TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384   uint16 = 0xc030 | ||||
| 	TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xc02c | ||||
|  | ||||
| 	// TLS_FALLBACK_SCSV isn't a standard cipher suite but an indicator | ||||
| 	// that the client is doing version fallback. See | ||||
| 	// https://tools.ietf.org/html/draft-ietf-tls-downgrade-scsv-00. | ||||
| 	TLS_FALLBACK_SCSV uint16 = 0x5600 | ||||
| ) | ||||
							
								
								
									
										714
									
								
								vendor/github.com/cloudflare/cfssl/scan/crypto/tls/common.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										714
									
								
								vendor/github.com/cloudflare/cfssl/scan/crypto/tls/common.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,714 @@ | ||||
| // Copyright 2009 The Go Authors. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package tls | ||||
|  | ||||
| import ( | ||||
| 	"container/list" | ||||
| 	"crypto" | ||||
| 	"crypto/rand" | ||||
| 	"crypto/sha512" | ||||
| 	"crypto/x509" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"math/big" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	VersionSSL30 = 0x0300 | ||||
| 	VersionTLS10 = 0x0301 | ||||
| 	VersionTLS11 = 0x0302 | ||||
| 	VersionTLS12 = 0x0303 | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	maxPlaintext    = 16384        // maximum plaintext payload length | ||||
| 	maxCiphertext   = 16384 + 2048 // maximum ciphertext payload length | ||||
| 	recordHeaderLen = 5            // record header length | ||||
| 	maxHandshake    = 65536        // maximum handshake we support (protocol max is 16 MB) | ||||
|  | ||||
| 	minVersion = VersionTLS10 | ||||
| 	maxVersion = VersionTLS12 | ||||
| ) | ||||
|  | ||||
| // TLS record types. | ||||
| type recordType uint8 | ||||
|  | ||||
| const ( | ||||
| 	recordTypeChangeCipherSpec recordType = 20 | ||||
| 	recordTypeAlert            recordType = 21 | ||||
| 	recordTypeHandshake        recordType = 22 | ||||
| 	recordTypeApplicationData  recordType = 23 | ||||
| ) | ||||
|  | ||||
| // TLS handshake message types. | ||||
| const ( | ||||
| 	typeClientHello        uint8 = 1 | ||||
| 	typeServerHello        uint8 = 2 | ||||
| 	typeNewSessionTicket   uint8 = 4 | ||||
| 	typeCertificate        uint8 = 11 | ||||
| 	typeServerKeyExchange  uint8 = 12 | ||||
| 	typeCertificateRequest uint8 = 13 | ||||
| 	typeServerHelloDone    uint8 = 14 | ||||
| 	typeCertificateVerify  uint8 = 15 | ||||
| 	typeClientKeyExchange  uint8 = 16 | ||||
| 	typeFinished           uint8 = 20 | ||||
| 	typeCertificateStatus  uint8 = 22 | ||||
| 	typeNextProtocol       uint8 = 67 // Not IANA assigned | ||||
| ) | ||||
|  | ||||
| // TLS compression types. | ||||
| const ( | ||||
| 	compressionNone uint8 = 0 | ||||
| ) | ||||
|  | ||||
| // TLS extension numbers | ||||
| const ( | ||||
| 	extensionServerName          uint16 = 0 | ||||
| 	extensionStatusRequest       uint16 = 5 | ||||
| 	extensionSupportedCurves     uint16 = 10 | ||||
| 	extensionSupportedPoints     uint16 = 11 | ||||
| 	extensionSignatureAlgorithms uint16 = 13 | ||||
| 	extensionALPN                uint16 = 16 | ||||
| 	extensionSCT                 uint16 = 18 // https://tools.ietf.org/html/rfc6962#section-6 | ||||
| 	extensionSessionTicket       uint16 = 35 | ||||
| 	extensionNextProtoNeg        uint16 = 13172 // not IANA assigned | ||||
| 	extensionRenegotiationInfo   uint16 = 0xff01 | ||||
| ) | ||||
|  | ||||
| // TLS signaling cipher suite values | ||||
| const ( | ||||
| 	scsvRenegotiation uint16 = 0x00ff | ||||
| ) | ||||
|  | ||||
| // CurveID is the type of a TLS identifier for an elliptic curve. See | ||||
| // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8 | ||||
| type CurveID uint16 | ||||
|  | ||||
| const ( | ||||
| 	CurveP256 CurveID = 23 | ||||
| 	CurveP384 CurveID = 24 | ||||
| 	CurveP521 CurveID = 25 | ||||
| ) | ||||
|  | ||||
| // TLS Elliptic Curve Point Formats | ||||
| // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-9 | ||||
| const ( | ||||
| 	pointFormatUncompressed uint8 = 0 | ||||
| ) | ||||
|  | ||||
| // TLS CertificateStatusType (RFC 3546) | ||||
| const ( | ||||
| 	statusTypeOCSP uint8 = 1 | ||||
| ) | ||||
|  | ||||
| // Certificate types (for certificateRequestMsg) | ||||
| const ( | ||||
| 	certTypeRSASign    = 1 // A certificate containing an RSA key | ||||
| 	certTypeDSSSign    = 2 // A certificate containing a DSA key | ||||
| 	certTypeRSAFixedDH = 3 // A certificate containing a static DH key | ||||
| 	certTypeDSSFixedDH = 4 // A certificate containing a static DH key | ||||
|  | ||||
| 	// See RFC4492 sections 3 and 5.5. | ||||
| 	certTypeECDSASign      = 64 // A certificate containing an ECDSA-capable public key, signed with ECDSA. | ||||
| 	certTypeRSAFixedECDH   = 65 // A certificate containing an ECDH-capable public key, signed with RSA. | ||||
| 	certTypeECDSAFixedECDH = 66 // A certificate containing an ECDH-capable public key, signed with ECDSA. | ||||
|  | ||||
| 	// Rest of these are reserved by the TLS spec | ||||
| ) | ||||
|  | ||||
| // Hash functions for TLS 1.2 (See RFC 5246, section A.4.1) | ||||
| const ( | ||||
| 	hashSHA1   uint8 = 2 | ||||
| 	hashSHA256 uint8 = 4 | ||||
| 	hashSHA384 uint8 = 5 | ||||
| ) | ||||
|  | ||||
| // Signature algorithms for TLS 1.2 (See RFC 5246, section A.4.1) | ||||
| const ( | ||||
| 	signatureRSA   uint8 = 1 | ||||
| 	signatureECDSA uint8 = 3 | ||||
| ) | ||||
|  | ||||
| // signatureAndHash mirrors the TLS 1.2, SignatureAndHashAlgorithm struct. See | ||||
| // RFC 5246, section A.4.1. | ||||
| type signatureAndHash struct { | ||||
| 	hash, signature uint8 | ||||
| } | ||||
|  | ||||
| // supportedSignatureAlgorithms contains the signature and hash algorithms that | ||||
| // the code advertises as supported in a TLS 1.2 ClientHello and in a TLS 1.2 | ||||
| // CertificateRequest. | ||||
| var supportedSignatureAlgorithms = []signatureAndHash{ | ||||
| 	{hashSHA256, signatureRSA}, | ||||
| 	{hashSHA256, signatureECDSA}, | ||||
| 	{hashSHA384, signatureRSA}, | ||||
| 	{hashSHA384, signatureECDSA}, | ||||
| 	{hashSHA1, signatureRSA}, | ||||
| 	{hashSHA1, signatureECDSA}, | ||||
| } | ||||
|  | ||||
| // ConnectionState records basic TLS details about the connection. | ||||
| type ConnectionState struct { | ||||
| 	Version                     uint16                // TLS version used by the connection (e.g. VersionTLS12) | ||||
| 	HandshakeComplete           bool                  // TLS handshake is complete | ||||
| 	DidResume                   bool                  // connection resumes a previous TLS connection | ||||
| 	CipherSuite                 uint16                // cipher suite in use (TLS_RSA_WITH_RC4_128_SHA, ...) | ||||
| 	NegotiatedProtocol          string                // negotiated next protocol (from Config.NextProtos) | ||||
| 	NegotiatedProtocolIsMutual  bool                  // negotiated protocol was advertised by server | ||||
| 	ServerName                  string                // server name requested by client, if any (server side only) | ||||
| 	PeerCertificates            []*x509.Certificate   // certificate chain presented by remote peer | ||||
| 	VerifiedChains              [][]*x509.Certificate // verified chains built from PeerCertificates | ||||
| 	SignedCertificateTimestamps [][]byte              // SCTs from the server, if any | ||||
| 	OCSPResponse                []byte                // stapled OCSP response from server, if any | ||||
|  | ||||
| 	// TLSUnique contains the "tls-unique" channel binding value (see RFC | ||||
| 	// 5929, section 3). For resumed sessions this value will be nil | ||||
| 	// because resumption does not include enough context (see | ||||
| 	// https://secure-resumption.com/#channelbindings). This will change in | ||||
| 	// future versions of Go once the TLS master-secret fix has been | ||||
| 	// standardized and implemented. | ||||
| 	TLSUnique []byte | ||||
| } | ||||
|  | ||||
| // ClientAuthType declares the policy the server will follow for | ||||
| // TLS Client Authentication. | ||||
| type ClientAuthType int | ||||
|  | ||||
| const ( | ||||
| 	NoClientCert ClientAuthType = iota | ||||
| 	RequestClientCert | ||||
| 	RequireAnyClientCert | ||||
| 	VerifyClientCertIfGiven | ||||
| 	RequireAndVerifyClientCert | ||||
| ) | ||||
|  | ||||
| // ClientSessionState contains the state needed by clients to resume TLS | ||||
| // sessions. | ||||
| type ClientSessionState struct { | ||||
| 	sessionTicket      []uint8               // Encrypted ticket used for session resumption with server | ||||
| 	vers               uint16                // SSL/TLS version negotiated for the session | ||||
| 	cipherSuite        uint16                // Ciphersuite negotiated for the session | ||||
| 	masterSecret       []byte                // MasterSecret generated by client on a full handshake | ||||
| 	serverCertificates []*x509.Certificate   // Certificate chain presented by the server | ||||
| 	verifiedChains     [][]*x509.Certificate // Certificate chains we built for verification | ||||
| } | ||||
|  | ||||
| // ClientSessionCache is a cache of ClientSessionState objects that can be used | ||||
| // by a client to resume a TLS session with a given server. ClientSessionCache | ||||
| // implementations should expect to be called concurrently from different | ||||
| // goroutines. | ||||
| type ClientSessionCache interface { | ||||
| 	// Get searches for a ClientSessionState associated with the given key. | ||||
| 	// On return, ok is true if one was found. | ||||
| 	Get(sessionKey string) (session *ClientSessionState, ok bool) | ||||
|  | ||||
| 	// Put adds the ClientSessionState to the cache with the given key. | ||||
| 	Put(sessionKey string, cs *ClientSessionState) | ||||
| } | ||||
|  | ||||
| // ClientHelloInfo contains information from a ClientHello message in order to | ||||
| // guide certificate selection in the GetCertificate callback. | ||||
| type ClientHelloInfo struct { | ||||
| 	// CipherSuites lists the CipherSuites supported by the client (e.g. | ||||
| 	// TLS_RSA_WITH_RC4_128_SHA). | ||||
| 	CipherSuites []uint16 | ||||
|  | ||||
| 	// ServerName indicates the name of the server requested by the client | ||||
| 	// in order to support virtual hosting. ServerName is only set if the | ||||
| 	// client is using SNI (see | ||||
| 	// http://tools.ietf.org/html/rfc4366#section-3.1). | ||||
| 	ServerName string | ||||
|  | ||||
| 	// SupportedCurves lists the elliptic curves supported by the client. | ||||
| 	// SupportedCurves is set only if the Supported Elliptic Curves | ||||
| 	// Extension is being used (see | ||||
| 	// http://tools.ietf.org/html/rfc4492#section-5.1.1). | ||||
| 	SupportedCurves []CurveID | ||||
|  | ||||
| 	// SupportedPoints lists the point formats supported by the client. | ||||
| 	// SupportedPoints is set only if the Supported Point Formats Extension | ||||
| 	// is being used (see | ||||
| 	// http://tools.ietf.org/html/rfc4492#section-5.1.2). | ||||
| 	SupportedPoints []uint8 | ||||
| } | ||||
|  | ||||
| // A Config structure is used to configure a TLS client or server. | ||||
| // After one has been passed to a TLS function it must not be | ||||
| // modified. A Config may be reused; the tls package will also not | ||||
| // modify it. | ||||
| type Config struct { | ||||
| 	// Rand provides the source of entropy for nonces and RSA blinding. | ||||
| 	// If Rand is nil, TLS uses the cryptographic random reader in package | ||||
| 	// crypto/rand. | ||||
| 	// The Reader must be safe for use by multiple goroutines. | ||||
| 	Rand io.Reader | ||||
|  | ||||
| 	// Time returns the current time as the number of seconds since the epoch. | ||||
| 	// If Time is nil, TLS uses time.Now. | ||||
| 	Time func() time.Time | ||||
|  | ||||
| 	// Certificates contains one or more certificate chains | ||||
| 	// to present to the other side of the connection. | ||||
| 	// Server configurations must include at least one certificate | ||||
| 	// or else set GetCertificate. | ||||
| 	Certificates []Certificate | ||||
|  | ||||
| 	// NameToCertificate maps from a certificate name to an element of | ||||
| 	// Certificates. Note that a certificate name can be of the form | ||||
| 	// '*.example.com' and so doesn't have to be a domain name as such. | ||||
| 	// See Config.BuildNameToCertificate | ||||
| 	// The nil value causes the first element of Certificates to be used | ||||
| 	// for all connections. | ||||
| 	NameToCertificate map[string]*Certificate | ||||
|  | ||||
| 	// GetCertificate returns a Certificate based on the given | ||||
| 	// ClientHelloInfo. It will only be called if the client supplies SNI | ||||
| 	// information or if Certificates is empty. | ||||
| 	// | ||||
| 	// If GetCertificate is nil or returns nil, then the certificate is | ||||
| 	// retrieved from NameToCertificate. If NameToCertificate is nil, the | ||||
| 	// first element of Certificates will be used. | ||||
| 	GetCertificate func(clientHello *ClientHelloInfo) (*Certificate, error) | ||||
|  | ||||
| 	// RootCAs defines the set of root certificate authorities | ||||
| 	// that clients use when verifying server certificates. | ||||
| 	// If RootCAs is nil, TLS uses the host's root CA set. | ||||
| 	RootCAs *x509.CertPool | ||||
|  | ||||
| 	// NextProtos is a list of supported, application level protocols. | ||||
| 	NextProtos []string | ||||
|  | ||||
| 	// ServerName is used to verify the hostname on the returned | ||||
| 	// certificates unless InsecureSkipVerify is given. It is also included | ||||
| 	// in the client's handshake to support virtual hosting unless it is | ||||
| 	// an IP address. | ||||
| 	ServerName string | ||||
|  | ||||
| 	// ClientAuth determines the server's policy for | ||||
| 	// TLS Client Authentication. The default is NoClientCert. | ||||
| 	ClientAuth ClientAuthType | ||||
|  | ||||
| 	// ClientCAs defines the set of root certificate authorities | ||||
| 	// that servers use if required to verify a client certificate | ||||
| 	// by the policy in ClientAuth. | ||||
| 	ClientCAs *x509.CertPool | ||||
|  | ||||
| 	// InsecureSkipVerify controls whether a client verifies the | ||||
| 	// server's certificate chain and host name. | ||||
| 	// If InsecureSkipVerify is true, TLS accepts any certificate | ||||
| 	// presented by the server and any host name in that certificate. | ||||
| 	// In this mode, TLS is susceptible to man-in-the-middle attacks. | ||||
| 	// This should be used only for testing. | ||||
| 	InsecureSkipVerify bool | ||||
|  | ||||
| 	// CipherSuites is a list of supported cipher suites. If CipherSuites | ||||
| 	// is nil, TLS uses a list of suites supported by the implementation. | ||||
| 	CipherSuites []uint16 | ||||
|  | ||||
| 	// PreferServerCipherSuites controls whether the server selects the | ||||
| 	// client's most preferred ciphersuite, or the server's most preferred | ||||
| 	// ciphersuite. If true then the server's preference, as expressed in | ||||
| 	// the order of elements in CipherSuites, is used. | ||||
| 	PreferServerCipherSuites bool | ||||
|  | ||||
| 	// SessionTicketsDisabled may be set to true to disable session ticket | ||||
| 	// (resumption) support. | ||||
| 	SessionTicketsDisabled bool | ||||
|  | ||||
| 	// SessionTicketKey is used by TLS servers to provide session | ||||
| 	// resumption. See RFC 5077. If zero, it will be filled with | ||||
| 	// random data before the first server handshake. | ||||
| 	// | ||||
| 	// If multiple servers are terminating connections for the same host | ||||
| 	// they should all have the same SessionTicketKey. If the | ||||
| 	// SessionTicketKey leaks, previously recorded and future TLS | ||||
| 	// connections using that key are compromised. | ||||
| 	SessionTicketKey [32]byte | ||||
|  | ||||
| 	// SessionCache is a cache of ClientSessionState entries for TLS session | ||||
| 	// resumption. | ||||
| 	ClientSessionCache ClientSessionCache | ||||
|  | ||||
| 	// MinVersion contains the minimum SSL/TLS version that is acceptable. | ||||
| 	// If zero, then TLS 1.0 is taken as the minimum. | ||||
| 	MinVersion uint16 | ||||
|  | ||||
| 	// MaxVersion contains the maximum SSL/TLS version that is acceptable. | ||||
| 	// If zero, then the maximum version supported by this package is used, | ||||
| 	// which is currently TLS 1.2. | ||||
| 	MaxVersion uint16 | ||||
|  | ||||
| 	// CurvePreferences contains the elliptic curves that will be used in | ||||
| 	// an ECDHE handshake, in preference order. If empty, the default will | ||||
| 	// be used. | ||||
| 	CurvePreferences []CurveID | ||||
|  | ||||
| 	serverInitOnce sync.Once // guards calling (*Config).serverInit | ||||
|  | ||||
| 	// mutex protects sessionTicketKeys | ||||
| 	mutex sync.RWMutex | ||||
| 	// sessionTicketKeys contains zero or more ticket keys. If the length | ||||
| 	// is zero, SessionTicketsDisabled must be true. The first key is used | ||||
| 	// for new tickets and any subsequent keys can be used to decrypt old | ||||
| 	// tickets. | ||||
| 	sessionTicketKeys []ticketKey | ||||
| } | ||||
|  | ||||
| // ticketKeyNameLen is the number of bytes of identifier that is prepended to | ||||
| // an encrypted session ticket in order to identify the key used to encrypt it. | ||||
| const ticketKeyNameLen = 16 | ||||
|  | ||||
| // ticketKey is the internal representation of a session ticket key. | ||||
| type ticketKey struct { | ||||
| 	// keyName is an opaque byte string that serves to identify the session | ||||
| 	// ticket key. It's exposed as plaintext in every session ticket. | ||||
| 	keyName [ticketKeyNameLen]byte | ||||
| 	aesKey  [16]byte | ||||
| 	hmacKey [16]byte | ||||
| } | ||||
|  | ||||
| // ticketKeyFromBytes converts from the external representation of a session | ||||
| // ticket key to a ticketKey. Externally, session ticket keys are 32 random | ||||
| // bytes and this function expands that into sufficient name and key material. | ||||
| func ticketKeyFromBytes(b [32]byte) (key ticketKey) { | ||||
| 	hashed := sha512.Sum512(b[:]) | ||||
| 	copy(key.keyName[:], hashed[:ticketKeyNameLen]) | ||||
| 	copy(key.aesKey[:], hashed[ticketKeyNameLen:ticketKeyNameLen+16]) | ||||
| 	copy(key.hmacKey[:], hashed[ticketKeyNameLen+16:ticketKeyNameLen+32]) | ||||
| 	return key | ||||
| } | ||||
|  | ||||
| func (c *Config) serverInit() { | ||||
| 	if c.SessionTicketsDisabled { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	alreadySet := false | ||||
| 	for _, b := range c.SessionTicketKey { | ||||
| 		if b != 0 { | ||||
| 			alreadySet = true | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if !alreadySet { | ||||
| 		if _, err := io.ReadFull(c.rand(), c.SessionTicketKey[:]); err != nil { | ||||
| 			c.SessionTicketsDisabled = true | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	c.sessionTicketKeys = []ticketKey{ticketKeyFromBytes(c.SessionTicketKey)} | ||||
| } | ||||
|  | ||||
| func (c *Config) ticketKeys() []ticketKey { | ||||
| 	c.mutex.RLock() | ||||
| 	// c.sessionTicketKeys is constant once created. SetSessionTicketKeys | ||||
| 	// will only update it by replacing it with a new value. | ||||
| 	ret := c.sessionTicketKeys | ||||
| 	c.mutex.RUnlock() | ||||
| 	return ret | ||||
| } | ||||
|  | ||||
| // SetSessionTicketKeys updates the session ticket keys for a server. The first | ||||
| // key will be used when creating new tickets, while all keys can be used for | ||||
| // decrypting tickets. It is safe to call this function while the server is | ||||
| // running in order to rotate the session ticket keys. The function will panic | ||||
| // if keys is empty. | ||||
| func (c *Config) SetSessionTicketKeys(keys [][32]byte) { | ||||
| 	if len(keys) == 0 { | ||||
| 		panic("tls: keys must have at least one key") | ||||
| 	} | ||||
|  | ||||
| 	newKeys := make([]ticketKey, len(keys)) | ||||
| 	for i, bytes := range keys { | ||||
| 		newKeys[i] = ticketKeyFromBytes(bytes) | ||||
| 	} | ||||
|  | ||||
| 	c.mutex.Lock() | ||||
| 	c.sessionTicketKeys = newKeys | ||||
| 	c.mutex.Unlock() | ||||
| } | ||||
|  | ||||
| func (c *Config) rand() io.Reader { | ||||
| 	r := c.Rand | ||||
| 	if r == nil { | ||||
| 		return rand.Reader | ||||
| 	} | ||||
| 	return r | ||||
| } | ||||
|  | ||||
| func (c *Config) time() time.Time { | ||||
| 	t := c.Time | ||||
| 	if t == nil { | ||||
| 		t = time.Now | ||||
| 	} | ||||
| 	return t() | ||||
| } | ||||
|  | ||||
| func (c *Config) cipherSuites() []uint16 { | ||||
| 	s := c.CipherSuites | ||||
| 	if s == nil { | ||||
| 		s = defaultCipherSuites() | ||||
| 	} | ||||
| 	return s | ||||
| } | ||||
|  | ||||
| func (c *Config) minVersion() uint16 { | ||||
| 	if c == nil || c.MinVersion == 0 { | ||||
| 		return minVersion | ||||
| 	} | ||||
| 	return c.MinVersion | ||||
| } | ||||
|  | ||||
| func (c *Config) maxVersion() uint16 { | ||||
| 	if c == nil || c.MaxVersion == 0 { | ||||
| 		return maxVersion | ||||
| 	} | ||||
| 	return c.MaxVersion | ||||
| } | ||||
|  | ||||
| var defaultCurvePreferences = []CurveID{CurveP256, CurveP384, CurveP521} | ||||
|  | ||||
| func (c *Config) curvePreferences() []CurveID { | ||||
| 	if c == nil || len(c.CurvePreferences) == 0 { | ||||
| 		return defaultCurvePreferences | ||||
| 	} | ||||
| 	return c.CurvePreferences | ||||
| } | ||||
|  | ||||
| // mutualVersion returns the protocol version to use given the advertised | ||||
| // version of the peer. | ||||
| func (c *Config) mutualVersion(vers uint16) (uint16, bool) { | ||||
| 	minVersion := c.minVersion() | ||||
| 	maxVersion := c.maxVersion() | ||||
|  | ||||
| 	if vers < minVersion { | ||||
| 		return 0, false | ||||
| 	} | ||||
| 	if vers > maxVersion { | ||||
| 		vers = maxVersion | ||||
| 	} | ||||
| 	return vers, true | ||||
| } | ||||
|  | ||||
| // getCertificate returns the best certificate for the given ClientHelloInfo, | ||||
| // defaulting to the first element of c.Certificates. | ||||
| func (c *Config) getCertificate(clientHello *ClientHelloInfo) (*Certificate, error) { | ||||
| 	if c.GetCertificate != nil && | ||||
| 		(len(c.Certificates) == 0 || len(clientHello.ServerName) > 0) { | ||||
| 		cert, err := c.GetCertificate(clientHello) | ||||
| 		if cert != nil || err != nil { | ||||
| 			return cert, err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if len(c.Certificates) == 0 { | ||||
| 		return nil, errors.New("crypto/tls: no certificates configured") | ||||
| 	} | ||||
|  | ||||
| 	if len(c.Certificates) == 1 || c.NameToCertificate == nil { | ||||
| 		// There's only one choice, so no point doing any work. | ||||
| 		return &c.Certificates[0], nil | ||||
| 	} | ||||
|  | ||||
| 	name := strings.ToLower(clientHello.ServerName) | ||||
| 	for len(name) > 0 && name[len(name)-1] == '.' { | ||||
| 		name = name[:len(name)-1] | ||||
| 	} | ||||
|  | ||||
| 	if cert, ok := c.NameToCertificate[name]; ok { | ||||
| 		return cert, nil | ||||
| 	} | ||||
|  | ||||
| 	// try replacing labels in the name with wildcards until we get a | ||||
| 	// match. | ||||
| 	labels := strings.Split(name, ".") | ||||
| 	for i := range labels { | ||||
| 		labels[i] = "*" | ||||
| 		candidate := strings.Join(labels, ".") | ||||
| 		if cert, ok := c.NameToCertificate[candidate]; ok { | ||||
| 			return cert, nil | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// If nothing matches, return the first certificate. | ||||
| 	return &c.Certificates[0], nil | ||||
| } | ||||
|  | ||||
| // BuildNameToCertificate parses c.Certificates and builds c.NameToCertificate | ||||
| // from the CommonName and SubjectAlternateName fields of each of the leaf | ||||
| // certificates. | ||||
| func (c *Config) BuildNameToCertificate() { | ||||
| 	c.NameToCertificate = make(map[string]*Certificate) | ||||
| 	for i := range c.Certificates { | ||||
| 		cert := &c.Certificates[i] | ||||
| 		x509Cert, err := x509.ParseCertificate(cert.Certificate[0]) | ||||
| 		if err != nil { | ||||
| 			continue | ||||
| 		} | ||||
| 		if len(x509Cert.Subject.CommonName) > 0 { | ||||
| 			c.NameToCertificate[x509Cert.Subject.CommonName] = cert | ||||
| 		} | ||||
| 		for _, san := range x509Cert.DNSNames { | ||||
| 			c.NameToCertificate[san] = cert | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // A Certificate is a chain of one or more certificates, leaf first. | ||||
| type Certificate struct { | ||||
| 	Certificate [][]byte | ||||
| 	// PrivateKey contains the private key corresponding to the public key | ||||
| 	// in Leaf. For a server, this must implement crypto.Signer and/or | ||||
| 	// crypto.Decrypter, with an RSA or ECDSA PublicKey. For a client | ||||
| 	// (performing client authentication), this must be a crypto.Signer | ||||
| 	// with an RSA or ECDSA PublicKey. | ||||
| 	PrivateKey crypto.PrivateKey | ||||
| 	// OCSPStaple contains an optional OCSP response which will be served | ||||
| 	// to clients that request it. | ||||
| 	OCSPStaple []byte | ||||
| 	// SignedCertificateTimestamps contains an optional list of Signed | ||||
| 	// Certificate Timestamps which will be served to clients that request it. | ||||
| 	SignedCertificateTimestamps [][]byte | ||||
| 	// Leaf is the parsed form of the leaf certificate, which may be | ||||
| 	// initialized using x509.ParseCertificate to reduce per-handshake | ||||
| 	// processing for TLS clients doing client authentication. If nil, the | ||||
| 	// leaf certificate will be parsed as needed. | ||||
| 	Leaf *x509.Certificate | ||||
| } | ||||
|  | ||||
| // A TLS record. | ||||
| type record struct { | ||||
| 	contentType  recordType | ||||
| 	major, minor uint8 | ||||
| 	payload      []byte | ||||
| } | ||||
|  | ||||
| type handshakeMessage interface { | ||||
| 	marshal() []byte | ||||
| 	unmarshal([]byte) bool | ||||
| } | ||||
|  | ||||
| // lruSessionCache is a ClientSessionCache implementation that uses an LRU | ||||
| // caching strategy. | ||||
| type lruSessionCache struct { | ||||
| 	sync.Mutex | ||||
|  | ||||
| 	m        map[string]*list.Element | ||||
| 	q        *list.List | ||||
| 	capacity int | ||||
| } | ||||
|  | ||||
| type lruSessionCacheEntry struct { | ||||
| 	sessionKey string | ||||
| 	state      *ClientSessionState | ||||
| } | ||||
|  | ||||
| // NewLRUClientSessionCache returns a ClientSessionCache with the given | ||||
| // capacity that uses an LRU strategy. If capacity is < 1, a default capacity | ||||
| // is used instead. | ||||
| func NewLRUClientSessionCache(capacity int) ClientSessionCache { | ||||
| 	const defaultSessionCacheCapacity = 64 | ||||
|  | ||||
| 	if capacity < 1 { | ||||
| 		capacity = defaultSessionCacheCapacity | ||||
| 	} | ||||
| 	return &lruSessionCache{ | ||||
| 		m:        make(map[string]*list.Element), | ||||
| 		q:        list.New(), | ||||
| 		capacity: capacity, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Put adds the provided (sessionKey, cs) pair to the cache. | ||||
| func (c *lruSessionCache) Put(sessionKey string, cs *ClientSessionState) { | ||||
| 	c.Lock() | ||||
| 	defer c.Unlock() | ||||
|  | ||||
| 	if elem, ok := c.m[sessionKey]; ok { | ||||
| 		entry := elem.Value.(*lruSessionCacheEntry) | ||||
| 		entry.state = cs | ||||
| 		c.q.MoveToFront(elem) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if c.q.Len() < c.capacity { | ||||
| 		entry := &lruSessionCacheEntry{sessionKey, cs} | ||||
| 		c.m[sessionKey] = c.q.PushFront(entry) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	elem := c.q.Back() | ||||
| 	entry := elem.Value.(*lruSessionCacheEntry) | ||||
| 	delete(c.m, entry.sessionKey) | ||||
| 	entry.sessionKey = sessionKey | ||||
| 	entry.state = cs | ||||
| 	c.q.MoveToFront(elem) | ||||
| 	c.m[sessionKey] = elem | ||||
| } | ||||
|  | ||||
| // Get returns the ClientSessionState value associated with a given key. It | ||||
| // returns (nil, false) if no value is found. | ||||
| func (c *lruSessionCache) Get(sessionKey string) (*ClientSessionState, bool) { | ||||
| 	c.Lock() | ||||
| 	defer c.Unlock() | ||||
|  | ||||
| 	if elem, ok := c.m[sessionKey]; ok { | ||||
| 		c.q.MoveToFront(elem) | ||||
| 		return elem.Value.(*lruSessionCacheEntry).state, true | ||||
| 	} | ||||
| 	return nil, false | ||||
| } | ||||
|  | ||||
| // TODO(jsing): Make these available to both crypto/x509 and crypto/tls. | ||||
| type dsaSignature struct { | ||||
| 	R, S *big.Int | ||||
| } | ||||
|  | ||||
| type ecdsaSignature dsaSignature | ||||
|  | ||||
| var emptyConfig Config | ||||
|  | ||||
| func defaultConfig() *Config { | ||||
| 	return &emptyConfig | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	once                   sync.Once | ||||
| 	varDefaultCipherSuites []uint16 | ||||
| ) | ||||
|  | ||||
| func defaultCipherSuites() []uint16 { | ||||
| 	once.Do(initDefaultCipherSuites) | ||||
| 	return varDefaultCipherSuites | ||||
| } | ||||
|  | ||||
| func initDefaultCipherSuites() { | ||||
| 	varDefaultCipherSuites = make([]uint16, 0, len(cipherSuites)) | ||||
| 	for _, suite := range cipherSuites { | ||||
| 		if suite.flags&suiteDefaultOff != 0 { | ||||
| 			continue | ||||
| 		} | ||||
| 		varDefaultCipherSuites = append(varDefaultCipherSuites, suite.id) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func unexpectedMessageError(wanted, got interface{}) error { | ||||
| 	return fmt.Errorf("tls: received unexpected handshake message of type %T when waiting for %T", got, wanted) | ||||
| } | ||||
|  | ||||
| func isSupportedSignatureAndHash(sigHash signatureAndHash, sigHashes []signatureAndHash) bool { | ||||
| 	for _, s := range sigHashes { | ||||
| 		if s == sigHash { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
							
								
								
									
										1091
									
								
								vendor/github.com/cloudflare/cfssl/scan/crypto/tls/conn.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1091
									
								
								vendor/github.com/cloudflare/cfssl/scan/crypto/tls/conn.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										161
									
								
								vendor/github.com/cloudflare/cfssl/scan/crypto/tls/generate_cert.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								vendor/github.com/cloudflare/cfssl/scan/crypto/tls/generate_cert.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,161 @@ | ||||
| // Copyright 2009 The Go Authors. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| // +build ignore | ||||
|  | ||||
| // Generate a self-signed X.509 certificate for a TLS server. Outputs to | ||||
| // 'cert.pem' and 'key.pem' and will overwrite existing files. | ||||
|  | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"crypto/ecdsa" | ||||
| 	"crypto/elliptic" | ||||
| 	"crypto/rand" | ||||
| 	"crypto/rsa" | ||||
| 	"crypto/x509" | ||||
| 	"crypto/x509/pkix" | ||||
| 	"encoding/pem" | ||||
| 	"flag" | ||||
| 	"fmt" | ||||
| 	"log" | ||||
| 	"math/big" | ||||
| 	"net" | ||||
| 	"os" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	host       = flag.String("host", "", "Comma-separated hostnames and IPs to generate a certificate for") | ||||
| 	validFrom  = flag.String("start-date", "", "Creation date formatted as Jan 1 15:04:05 2011") | ||||
| 	validFor   = flag.Duration("duration", 365*24*time.Hour, "Duration that certificate is valid for") | ||||
| 	isCA       = flag.Bool("ca", false, "whether this cert should be its own Certificate Authority") | ||||
| 	rsaBits    = flag.Int("rsa-bits", 2048, "Size of RSA key to generate. Ignored if --ecdsa-curve is set") | ||||
| 	ecdsaCurve = flag.String("ecdsa-curve", "", "ECDSA curve to use to generate a key. Valid values are P224, P256, P384, P521") | ||||
| ) | ||||
|  | ||||
| func publicKey(priv interface{}) interface{} { | ||||
| 	switch k := priv.(type) { | ||||
| 	case *rsa.PrivateKey: | ||||
| 		return &k.PublicKey | ||||
| 	case *ecdsa.PrivateKey: | ||||
| 		return &k.PublicKey | ||||
| 	default: | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func pemBlockForKey(priv interface{}) *pem.Block { | ||||
| 	switch k := priv.(type) { | ||||
| 	case *rsa.PrivateKey: | ||||
| 		return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(k)} | ||||
| 	case *ecdsa.PrivateKey: | ||||
| 		b, err := x509.MarshalECPrivateKey(k) | ||||
| 		if err != nil { | ||||
| 			fmt.Fprintf(os.Stderr, "Unable to marshal ECDSA private key: %v", err) | ||||
| 			os.Exit(2) | ||||
| 		} | ||||
| 		return &pem.Block{Type: "EC PRIVATE KEY", Bytes: b} | ||||
| 	default: | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func main() { | ||||
| 	flag.Parse() | ||||
|  | ||||
| 	if len(*host) == 0 { | ||||
| 		log.Fatalf("Missing required --host parameter") | ||||
| 	} | ||||
|  | ||||
| 	var priv interface{} | ||||
| 	var err error | ||||
| 	switch *ecdsaCurve { | ||||
| 	case "": | ||||
| 		priv, err = rsa.GenerateKey(rand.Reader, *rsaBits) | ||||
| 	case "P224": | ||||
| 		priv, err = ecdsa.GenerateKey(elliptic.P224(), rand.Reader) | ||||
| 	case "P256": | ||||
| 		priv, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) | ||||
| 	case "P384": | ||||
| 		priv, err = ecdsa.GenerateKey(elliptic.P384(), rand.Reader) | ||||
| 	case "P521": | ||||
| 		priv, err = ecdsa.GenerateKey(elliptic.P521(), rand.Reader) | ||||
| 	default: | ||||
| 		fmt.Fprintf(os.Stderr, "Unrecognized elliptic curve: %q", *ecdsaCurve) | ||||
| 		os.Exit(1) | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		log.Fatalf("failed to generate private key: %s", err) | ||||
| 	} | ||||
|  | ||||
| 	var notBefore time.Time | ||||
| 	if len(*validFrom) == 0 { | ||||
| 		notBefore = time.Now() | ||||
| 	} else { | ||||
| 		notBefore, err = time.Parse("Jan 2 15:04:05 2006", *validFrom) | ||||
| 		if err != nil { | ||||
| 			fmt.Fprintf(os.Stderr, "Failed to parse creation date: %s\n", err) | ||||
| 			os.Exit(1) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	notAfter := notBefore.Add(*validFor) | ||||
|  | ||||
| 	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) | ||||
| 	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) | ||||
| 	if err != nil { | ||||
| 		log.Fatalf("failed to generate serial number: %s", err) | ||||
| 	} | ||||
|  | ||||
| 	template := x509.Certificate{ | ||||
| 		SerialNumber: serialNumber, | ||||
| 		Subject: pkix.Name{ | ||||
| 			Organization: []string{"Acme Co"}, | ||||
| 		}, | ||||
| 		NotBefore: notBefore, | ||||
| 		NotAfter:  notAfter, | ||||
|  | ||||
| 		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, | ||||
| 		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, | ||||
| 		BasicConstraintsValid: true, | ||||
| 	} | ||||
|  | ||||
| 	hosts := strings.Split(*host, ",") | ||||
| 	for _, h := range hosts { | ||||
| 		if ip := net.ParseIP(h); ip != nil { | ||||
| 			template.IPAddresses = append(template.IPAddresses, ip) | ||||
| 		} else { | ||||
| 			template.DNSNames = append(template.DNSNames, h) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if *isCA { | ||||
| 		template.IsCA = true | ||||
| 		template.KeyUsage |= x509.KeyUsageCertSign | ||||
| 	} | ||||
|  | ||||
| 	derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv) | ||||
| 	if err != nil { | ||||
| 		log.Fatalf("Failed to create certificate: %s", err) | ||||
| 	} | ||||
|  | ||||
| 	certOut, err := os.Create("cert.pem") | ||||
| 	if err != nil { | ||||
| 		log.Fatalf("failed to open cert.pem for writing: %s", err) | ||||
| 	} | ||||
| 	pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) | ||||
| 	certOut.Close() | ||||
| 	log.Print("written cert.pem\n") | ||||
|  | ||||
| 	keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) | ||||
| 	if err != nil { | ||||
| 		log.Print("failed to open key.pem for writing:", err) | ||||
| 		return | ||||
| 	} | ||||
| 	pem.Encode(keyOut, pemBlockForKey(priv)) | ||||
| 	keyOut.Close() | ||||
| 	log.Print("written key.pem\n") | ||||
| } | ||||
							
								
								
									
										667
									
								
								vendor/github.com/cloudflare/cfssl/scan/crypto/tls/handshake_client.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										667
									
								
								vendor/github.com/cloudflare/cfssl/scan/crypto/tls/handshake_client.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,667 @@ | ||||
| // Copyright 2009 The Go Authors. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package tls | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"crypto" | ||||
| 	"crypto/ecdsa" | ||||
| 	"crypto/rsa" | ||||
| 	"crypto/subtle" | ||||
| 	"crypto/x509" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"net" | ||||
| 	"strconv" | ||||
| ) | ||||
|  | ||||
| type clientHandshakeState struct { | ||||
| 	c            *Conn | ||||
| 	serverHello  *serverHelloMsg | ||||
| 	hello        *clientHelloMsg | ||||
| 	suite        *cipherSuite | ||||
| 	finishedHash finishedHash | ||||
| 	masterSecret []byte | ||||
| 	session      *ClientSessionState | ||||
| } | ||||
|  | ||||
| func (c *Conn) clientHandshake() error { | ||||
| 	if c.config == nil { | ||||
| 		c.config = defaultConfig() | ||||
| 	} | ||||
|  | ||||
| 	if len(c.config.ServerName) == 0 && !c.config.InsecureSkipVerify { | ||||
| 		return errors.New("tls: either ServerName or InsecureSkipVerify must be specified in the tls.Config") | ||||
| 	} | ||||
|  | ||||
| 	nextProtosLength := 0 | ||||
| 	for _, proto := range c.config.NextProtos { | ||||
| 		if l := len(proto); l == 0 || l > 255 { | ||||
| 			return errors.New("tls: invalid NextProtos value") | ||||
| 		} else { | ||||
| 			nextProtosLength += 1 + l | ||||
| 		} | ||||
| 	} | ||||
| 	if nextProtosLength > 0xffff { | ||||
| 		return errors.New("tls: NextProtos values too large") | ||||
| 	} | ||||
|  | ||||
| 	sni := c.config.ServerName | ||||
| 	// IP address literals are not permitted as SNI values. See | ||||
| 	// https://tools.ietf.org/html/rfc6066#section-3. | ||||
| 	if net.ParseIP(sni) != nil { | ||||
| 		sni = "" | ||||
| 	} | ||||
|  | ||||
| 	hello := &clientHelloMsg{ | ||||
| 		vers:                c.config.maxVersion(), | ||||
| 		compressionMethods:  []uint8{compressionNone}, | ||||
| 		random:              make([]byte, 32), | ||||
| 		ocspStapling:        true, | ||||
| 		scts:                true, | ||||
| 		serverName:          sni, | ||||
| 		supportedCurves:     c.config.curvePreferences(), | ||||
| 		supportedPoints:     []uint8{pointFormatUncompressed}, | ||||
| 		nextProtoNeg:        len(c.config.NextProtos) > 0, | ||||
| 		secureRenegotiation: true, | ||||
| 		alpnProtocols:       c.config.NextProtos, | ||||
| 	} | ||||
|  | ||||
| 	possibleCipherSuites := c.config.cipherSuites() | ||||
| 	hello.cipherSuites = make([]uint16, 0, len(possibleCipherSuites)) | ||||
|  | ||||
| NextCipherSuite: | ||||
| 	for _, suiteId := range possibleCipherSuites { | ||||
| 		for _, suite := range cipherSuites { | ||||
| 			if suite.id != suiteId { | ||||
| 				continue | ||||
| 			} | ||||
| 			// Don't advertise TLS 1.2-only cipher suites unless | ||||
| 			// we're attempting TLS 1.2. | ||||
| 			if hello.vers < VersionTLS12 && suite.flags&suiteTLS12 != 0 { | ||||
| 				continue | ||||
| 			} | ||||
| 			hello.cipherSuites = append(hello.cipherSuites, suiteId) | ||||
| 			continue NextCipherSuite | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	_, err := io.ReadFull(c.config.rand(), hello.random) | ||||
| 	if err != nil { | ||||
| 		c.sendAlert(alertInternalError) | ||||
| 		return errors.New("tls: short read from Rand: " + err.Error()) | ||||
| 	} | ||||
|  | ||||
| 	if hello.vers >= VersionTLS12 { | ||||
| 		hello.signatureAndHashes = supportedSignatureAlgorithms | ||||
| 	} | ||||
|  | ||||
| 	var session *ClientSessionState | ||||
| 	var cacheKey string | ||||
| 	sessionCache := c.config.ClientSessionCache | ||||
| 	if c.config.SessionTicketsDisabled { | ||||
| 		sessionCache = nil | ||||
| 	} | ||||
|  | ||||
| 	if sessionCache != nil { | ||||
| 		hello.ticketSupported = true | ||||
|  | ||||
| 		// Try to resume a previously negotiated TLS session, if | ||||
| 		// available. | ||||
| 		cacheKey = clientSessionCacheKey(c.conn.RemoteAddr(), c.config) | ||||
| 		candidateSession, ok := sessionCache.Get(cacheKey) | ||||
| 		if ok { | ||||
| 			// Check that the ciphersuite/version used for the | ||||
| 			// previous session are still valid. | ||||
| 			cipherSuiteOk := false | ||||
| 			for _, id := range hello.cipherSuites { | ||||
| 				if id == candidateSession.cipherSuite { | ||||
| 					cipherSuiteOk = true | ||||
| 					break | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			versOk := candidateSession.vers >= c.config.minVersion() && | ||||
| 				candidateSession.vers <= c.config.maxVersion() | ||||
| 			if versOk && cipherSuiteOk { | ||||
| 				session = candidateSession | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if session != nil { | ||||
| 		hello.sessionTicket = session.sessionTicket | ||||
| 		// A random session ID is used to detect when the | ||||
| 		// server accepted the ticket and is resuming a session | ||||
| 		// (see RFC 5077). | ||||
| 		hello.sessionId = make([]byte, 16) | ||||
| 		if _, err := io.ReadFull(c.config.rand(), hello.sessionId); err != nil { | ||||
| 			c.sendAlert(alertInternalError) | ||||
| 			return errors.New("tls: short read from Rand: " + err.Error()) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	c.writeRecord(recordTypeHandshake, hello.marshal()) | ||||
|  | ||||
| 	msg, err := c.readHandshake() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	serverHello, ok := msg.(*serverHelloMsg) | ||||
| 	if !ok { | ||||
| 		c.sendAlert(alertUnexpectedMessage) | ||||
| 		return unexpectedMessageError(serverHello, msg) | ||||
| 	} | ||||
|  | ||||
| 	vers, ok := c.config.mutualVersion(serverHello.vers) | ||||
| 	if !ok || vers < VersionTLS10 { | ||||
| 		// TLS 1.0 is the minimum version supported as a client. | ||||
| 		c.sendAlert(alertProtocolVersion) | ||||
| 		return fmt.Errorf("tls: server selected unsupported protocol version %x", serverHello.vers) | ||||
| 	} | ||||
| 	c.vers = vers | ||||
| 	c.haveVers = true | ||||
|  | ||||
| 	suite := mutualCipherSuite(hello.cipherSuites, serverHello.cipherSuite) | ||||
| 	if suite == nil { | ||||
| 		c.sendAlert(alertHandshakeFailure) | ||||
| 		return errors.New("tls: server chose an unconfigured cipher suite") | ||||
| 	} | ||||
|  | ||||
| 	hs := &clientHandshakeState{ | ||||
| 		c:            c, | ||||
| 		serverHello:  serverHello, | ||||
| 		hello:        hello, | ||||
| 		suite:        suite, | ||||
| 		finishedHash: newFinishedHash(c.vers, suite), | ||||
| 		session:      session, | ||||
| 	} | ||||
|  | ||||
| 	isResume, err := hs.processServerHello() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// No signatures of the handshake are needed in a resumption. | ||||
| 	// Otherwise, in a full handshake, if we don't have any certificates | ||||
| 	// configured then we will never send a CertificateVerify message and | ||||
| 	// thus no signatures are needed in that case either. | ||||
| 	if isResume || len(c.config.Certificates) == 0 { | ||||
| 		hs.finishedHash.discardHandshakeBuffer() | ||||
| 	} | ||||
|  | ||||
| 	hs.finishedHash.Write(hs.hello.marshal()) | ||||
| 	hs.finishedHash.Write(hs.serverHello.marshal()) | ||||
|  | ||||
| 	if isResume { | ||||
| 		if err := hs.establishKeys(); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if err := hs.readSessionTicket(); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if err := hs.readFinished(c.firstFinished[:]); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if err := hs.sendFinished(nil); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} else { | ||||
| 		if err := hs.doFullHandshake(); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if err := hs.establishKeys(); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if err := hs.sendFinished(c.firstFinished[:]); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if err := hs.readSessionTicket(); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if err := hs.readFinished(nil); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if sessionCache != nil && hs.session != nil && session != hs.session { | ||||
| 		sessionCache.Put(cacheKey, hs.session) | ||||
| 	} | ||||
|  | ||||
| 	c.didResume = isResume | ||||
| 	c.handshakeComplete = true | ||||
| 	c.cipherSuite = suite.id | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (hs *clientHandshakeState) doFullHandshake() error { | ||||
| 	c := hs.c | ||||
|  | ||||
| 	msg, err := c.readHandshake() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	certMsg, ok := msg.(*certificateMsg) | ||||
| 	if !ok || len(certMsg.certificates) == 0 { | ||||
| 		c.sendAlert(alertUnexpectedMessage) | ||||
| 		return unexpectedMessageError(certMsg, msg) | ||||
| 	} | ||||
| 	hs.finishedHash.Write(certMsg.marshal()) | ||||
|  | ||||
| 	certs := make([]*x509.Certificate, len(certMsg.certificates)) | ||||
| 	for i, asn1Data := range certMsg.certificates { | ||||
| 		cert, err := x509.ParseCertificate(asn1Data) | ||||
| 		if err != nil { | ||||
| 			c.sendAlert(alertBadCertificate) | ||||
| 			return errors.New("tls: failed to parse certificate from server: " + err.Error()) | ||||
| 		} | ||||
| 		certs[i] = cert | ||||
| 	} | ||||
|  | ||||
| 	if !c.config.InsecureSkipVerify { | ||||
| 		opts := x509.VerifyOptions{ | ||||
| 			Roots:         c.config.RootCAs, | ||||
| 			CurrentTime:   c.config.time(), | ||||
| 			DNSName:       c.config.ServerName, | ||||
| 			Intermediates: x509.NewCertPool(), | ||||
| 		} | ||||
|  | ||||
| 		for i, cert := range certs { | ||||
| 			if i == 0 { | ||||
| 				continue | ||||
| 			} | ||||
| 			opts.Intermediates.AddCert(cert) | ||||
| 		} | ||||
| 		c.verifiedChains, err = certs[0].Verify(opts) | ||||
| 		if err != nil { | ||||
| 			c.sendAlert(alertBadCertificate) | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	switch certs[0].PublicKey.(type) { | ||||
| 	case *rsa.PublicKey, *ecdsa.PublicKey: | ||||
| 		break | ||||
| 	default: | ||||
| 		c.sendAlert(alertUnsupportedCertificate) | ||||
| 		return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", certs[0].PublicKey) | ||||
| 	} | ||||
|  | ||||
| 	c.peerCertificates = certs | ||||
|  | ||||
| 	if hs.serverHello.ocspStapling { | ||||
| 		msg, err = c.readHandshake() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		cs, ok := msg.(*certificateStatusMsg) | ||||
| 		if !ok { | ||||
| 			c.sendAlert(alertUnexpectedMessage) | ||||
| 			return unexpectedMessageError(cs, msg) | ||||
| 		} | ||||
| 		hs.finishedHash.Write(cs.marshal()) | ||||
|  | ||||
| 		if cs.statusType == statusTypeOCSP { | ||||
| 			c.ocspResponse = cs.response | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	msg, err = c.readHandshake() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	keyAgreement := hs.suite.ka(c.vers) | ||||
|  | ||||
| 	skx, ok := msg.(*serverKeyExchangeMsg) | ||||
| 	if ok { | ||||
| 		hs.finishedHash.Write(skx.marshal()) | ||||
| 		err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, certs[0], skx) | ||||
| 		if err != nil { | ||||
| 			c.sendAlert(alertUnexpectedMessage) | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		msg, err = c.readHandshake() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	var chainToSend *Certificate | ||||
| 	var certRequested bool | ||||
| 	certReq, ok := msg.(*certificateRequestMsg) | ||||
| 	if ok { | ||||
| 		certRequested = true | ||||
|  | ||||
| 		// RFC 4346 on the certificateAuthorities field: | ||||
| 		// A list of the distinguished names of acceptable certificate | ||||
| 		// authorities. These distinguished names may specify a desired | ||||
| 		// distinguished name for a root CA or for a subordinate CA; | ||||
| 		// thus, this message can be used to describe both known roots | ||||
| 		// and a desired authorization space. If the | ||||
| 		// certificate_authorities list is empty then the client MAY | ||||
| 		// send any certificate of the appropriate | ||||
| 		// ClientCertificateType, unless there is some external | ||||
| 		// arrangement to the contrary. | ||||
|  | ||||
| 		hs.finishedHash.Write(certReq.marshal()) | ||||
|  | ||||
| 		var rsaAvail, ecdsaAvail bool | ||||
| 		for _, certType := range certReq.certificateTypes { | ||||
| 			switch certType { | ||||
| 			case certTypeRSASign: | ||||
| 				rsaAvail = true | ||||
| 			case certTypeECDSASign: | ||||
| 				ecdsaAvail = true | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// We need to search our list of client certs for one | ||||
| 		// where SignatureAlgorithm is acceptable to the server and the | ||||
| 		// Issuer is in certReq.certificateAuthorities | ||||
| 	findCert: | ||||
| 		for i, chain := range c.config.Certificates { | ||||
| 			if !rsaAvail && !ecdsaAvail { | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			for j, cert := range chain.Certificate { | ||||
| 				x509Cert := chain.Leaf | ||||
| 				// parse the certificate if this isn't the leaf | ||||
| 				// node, or if chain.Leaf was nil | ||||
| 				if j != 0 || x509Cert == nil { | ||||
| 					if x509Cert, err = x509.ParseCertificate(cert); err != nil { | ||||
| 						c.sendAlert(alertInternalError) | ||||
| 						return errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error()) | ||||
| 					} | ||||
| 				} | ||||
|  | ||||
| 				switch { | ||||
| 				case rsaAvail && x509Cert.PublicKeyAlgorithm == x509.RSA: | ||||
| 				case ecdsaAvail && x509Cert.PublicKeyAlgorithm == x509.ECDSA: | ||||
| 				default: | ||||
| 					continue findCert | ||||
| 				} | ||||
|  | ||||
| 				if len(certReq.certificateAuthorities) == 0 { | ||||
| 					// they gave us an empty list, so just take the | ||||
| 					// first cert from c.config.Certificates | ||||
| 					chainToSend = &chain | ||||
| 					break findCert | ||||
| 				} | ||||
|  | ||||
| 				for _, ca := range certReq.certificateAuthorities { | ||||
| 					if bytes.Equal(x509Cert.RawIssuer, ca) { | ||||
| 						chainToSend = &chain | ||||
| 						break findCert | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		msg, err = c.readHandshake() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	shd, ok := msg.(*serverHelloDoneMsg) | ||||
| 	if !ok { | ||||
| 		c.sendAlert(alertUnexpectedMessage) | ||||
| 		return unexpectedMessageError(shd, msg) | ||||
| 	} | ||||
| 	hs.finishedHash.Write(shd.marshal()) | ||||
|  | ||||
| 	// If the server requested a certificate then we have to send a | ||||
| 	// Certificate message, even if it's empty because we don't have a | ||||
| 	// certificate to send. | ||||
| 	if certRequested { | ||||
| 		certMsg = new(certificateMsg) | ||||
| 		if chainToSend != nil { | ||||
| 			certMsg.certificates = chainToSend.Certificate | ||||
| 		} | ||||
| 		hs.finishedHash.Write(certMsg.marshal()) | ||||
| 		c.writeRecord(recordTypeHandshake, certMsg.marshal()) | ||||
| 	} | ||||
|  | ||||
| 	preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, certs[0]) | ||||
| 	if err != nil { | ||||
| 		c.sendAlert(alertInternalError) | ||||
| 		return err | ||||
| 	} | ||||
| 	if ckx != nil { | ||||
| 		hs.finishedHash.Write(ckx.marshal()) | ||||
| 		c.writeRecord(recordTypeHandshake, ckx.marshal()) | ||||
| 	} | ||||
|  | ||||
| 	if chainToSend != nil { | ||||
| 		certVerify := &certificateVerifyMsg{ | ||||
| 			hasSignatureAndHash: c.vers >= VersionTLS12, | ||||
| 		} | ||||
|  | ||||
| 		key, ok := chainToSend.PrivateKey.(crypto.Signer) | ||||
| 		if !ok { | ||||
| 			c.sendAlert(alertInternalError) | ||||
| 			return fmt.Errorf("tls: client certificate private key of type %T does not implement crypto.Signer", chainToSend.PrivateKey) | ||||
| 		} | ||||
|  | ||||
| 		var signatureType uint8 | ||||
| 		switch key.Public().(type) { | ||||
| 		case *ecdsa.PublicKey: | ||||
| 			signatureType = signatureECDSA | ||||
| 		case *rsa.PublicKey: | ||||
| 			signatureType = signatureRSA | ||||
| 		default: | ||||
| 			c.sendAlert(alertInternalError) | ||||
| 			return fmt.Errorf("tls: failed to sign handshake with client certificate: unknown client certificate key type: %T", key) | ||||
| 		} | ||||
|  | ||||
| 		certVerify.signatureAndHash, err = hs.finishedHash.selectClientCertSignatureAlgorithm(certReq.signatureAndHashes, signatureType) | ||||
| 		if err != nil { | ||||
| 			c.sendAlert(alertInternalError) | ||||
| 			return err | ||||
| 		} | ||||
| 		digest, hashFunc, err := hs.finishedHash.hashForClientCertificate(certVerify.signatureAndHash, hs.masterSecret) | ||||
| 		if err != nil { | ||||
| 			c.sendAlert(alertInternalError) | ||||
| 			return err | ||||
| 		} | ||||
| 		certVerify.signature, err = key.Sign(c.config.rand(), digest, hashFunc) | ||||
| 		if err != nil { | ||||
| 			c.sendAlert(alertInternalError) | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		hs.finishedHash.Write(certVerify.marshal()) | ||||
| 		c.writeRecord(recordTypeHandshake, certVerify.marshal()) | ||||
| 	} | ||||
|  | ||||
| 	hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random) | ||||
|  | ||||
| 	hs.finishedHash.discardHandshakeBuffer() | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (hs *clientHandshakeState) establishKeys() error { | ||||
| 	c := hs.c | ||||
|  | ||||
| 	clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV := | ||||
| 		keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.hello.random, hs.serverHello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen) | ||||
| 	var clientCipher, serverCipher interface{} | ||||
| 	var clientHash, serverHash macFunction | ||||
| 	if hs.suite.cipher != nil { | ||||
| 		clientCipher = hs.suite.cipher(clientKey, clientIV, false /* not for reading */) | ||||
| 		clientHash = hs.suite.mac(c.vers, clientMAC) | ||||
| 		serverCipher = hs.suite.cipher(serverKey, serverIV, true /* for reading */) | ||||
| 		serverHash = hs.suite.mac(c.vers, serverMAC) | ||||
| 	} else { | ||||
| 		clientCipher = hs.suite.aead(clientKey, clientIV) | ||||
| 		serverCipher = hs.suite.aead(serverKey, serverIV) | ||||
| 	} | ||||
|  | ||||
| 	c.in.prepareCipherSpec(c.vers, serverCipher, serverHash) | ||||
| 	c.out.prepareCipherSpec(c.vers, clientCipher, clientHash) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (hs *clientHandshakeState) serverResumedSession() bool { | ||||
| 	// If the server responded with the same sessionId then it means the | ||||
| 	// sessionTicket is being used to resume a TLS session. | ||||
| 	return hs.session != nil && hs.hello.sessionId != nil && | ||||
| 		bytes.Equal(hs.serverHello.sessionId, hs.hello.sessionId) | ||||
| } | ||||
|  | ||||
| func (hs *clientHandshakeState) processServerHello() (bool, error) { | ||||
| 	c := hs.c | ||||
|  | ||||
| 	if hs.serverHello.compressionMethod != compressionNone { | ||||
| 		c.sendAlert(alertUnexpectedMessage) | ||||
| 		return false, errors.New("tls: server selected unsupported compression format") | ||||
| 	} | ||||
|  | ||||
| 	clientDidNPN := hs.hello.nextProtoNeg | ||||
| 	clientDidALPN := len(hs.hello.alpnProtocols) > 0 | ||||
| 	serverHasNPN := hs.serverHello.nextProtoNeg | ||||
| 	serverHasALPN := len(hs.serverHello.alpnProtocol) > 0 | ||||
|  | ||||
| 	if !clientDidNPN && serverHasNPN { | ||||
| 		c.sendAlert(alertHandshakeFailure) | ||||
| 		return false, errors.New("server advertised unrequested NPN extension") | ||||
| 	} | ||||
|  | ||||
| 	if !clientDidALPN && serverHasALPN { | ||||
| 		c.sendAlert(alertHandshakeFailure) | ||||
| 		return false, errors.New("server advertised unrequested ALPN extension") | ||||
| 	} | ||||
|  | ||||
| 	if serverHasNPN && serverHasALPN { | ||||
| 		c.sendAlert(alertHandshakeFailure) | ||||
| 		return false, errors.New("server advertised both NPN and ALPN extensions") | ||||
| 	} | ||||
|  | ||||
| 	if serverHasALPN { | ||||
| 		c.clientProtocol = hs.serverHello.alpnProtocol | ||||
| 		c.clientProtocolFallback = false | ||||
| 	} | ||||
| 	c.scts = hs.serverHello.scts | ||||
|  | ||||
| 	if hs.serverResumedSession() { | ||||
| 		// Restore masterSecret and peerCerts from previous state | ||||
| 		hs.masterSecret = hs.session.masterSecret | ||||
| 		c.peerCertificates = hs.session.serverCertificates | ||||
| 		c.verifiedChains = hs.session.verifiedChains | ||||
| 		return true, nil | ||||
| 	} | ||||
| 	return false, nil | ||||
| } | ||||
|  | ||||
| func (hs *clientHandshakeState) readFinished(out []byte) error { | ||||
| 	c := hs.c | ||||
|  | ||||
| 	c.readRecord(recordTypeChangeCipherSpec) | ||||
| 	if err := c.in.error(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	msg, err := c.readHandshake() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	serverFinished, ok := msg.(*finishedMsg) | ||||
| 	if !ok { | ||||
| 		c.sendAlert(alertUnexpectedMessage) | ||||
| 		return unexpectedMessageError(serverFinished, msg) | ||||
| 	} | ||||
|  | ||||
| 	verify := hs.finishedHash.serverSum(hs.masterSecret) | ||||
| 	if len(verify) != len(serverFinished.verifyData) || | ||||
| 		subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 { | ||||
| 		c.sendAlert(alertHandshakeFailure) | ||||
| 		return errors.New("tls: server's Finished message was incorrect") | ||||
| 	} | ||||
| 	hs.finishedHash.Write(serverFinished.marshal()) | ||||
| 	copy(out, verify) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (hs *clientHandshakeState) readSessionTicket() error { | ||||
| 	if !hs.serverHello.ticketSupported { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	c := hs.c | ||||
| 	msg, err := c.readHandshake() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	sessionTicketMsg, ok := msg.(*newSessionTicketMsg) | ||||
| 	if !ok { | ||||
| 		c.sendAlert(alertUnexpectedMessage) | ||||
| 		return unexpectedMessageError(sessionTicketMsg, msg) | ||||
| 	} | ||||
| 	hs.finishedHash.Write(sessionTicketMsg.marshal()) | ||||
|  | ||||
| 	hs.session = &ClientSessionState{ | ||||
| 		sessionTicket:      sessionTicketMsg.ticket, | ||||
| 		vers:               c.vers, | ||||
| 		cipherSuite:        hs.suite.id, | ||||
| 		masterSecret:       hs.masterSecret, | ||||
| 		serverCertificates: c.peerCertificates, | ||||
| 		verifiedChains:     c.verifiedChains, | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (hs *clientHandshakeState) sendFinished(out []byte) error { | ||||
| 	c := hs.c | ||||
|  | ||||
| 	c.writeRecord(recordTypeChangeCipherSpec, []byte{1}) | ||||
| 	if hs.serverHello.nextProtoNeg { | ||||
| 		nextProto := new(nextProtoMsg) | ||||
| 		proto, fallback := mutualProtocol(c.config.NextProtos, hs.serverHello.nextProtos) | ||||
| 		nextProto.proto = proto | ||||
| 		c.clientProtocol = proto | ||||
| 		c.clientProtocolFallback = fallback | ||||
|  | ||||
| 		hs.finishedHash.Write(nextProto.marshal()) | ||||
| 		c.writeRecord(recordTypeHandshake, nextProto.marshal()) | ||||
| 	} | ||||
|  | ||||
| 	finished := new(finishedMsg) | ||||
| 	finished.verifyData = hs.finishedHash.clientSum(hs.masterSecret) | ||||
| 	hs.finishedHash.Write(finished.marshal()) | ||||
| 	c.writeRecord(recordTypeHandshake, finished.marshal()) | ||||
| 	copy(out, finished.verifyData) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // clientSessionCacheKey returns a key used to cache sessionTickets that could | ||||
| // be used to resume previously negotiated TLS sessions with a server. | ||||
| func clientSessionCacheKey(serverAddr net.Addr, config *Config) string { | ||||
| 	if len(config.ServerName) > 0 { | ||||
| 		return config.ServerName | ||||
| 	} | ||||
| 	return serverAddr.String() | ||||
| } | ||||
|  | ||||
| // mutualProtocol finds the mutual Next Protocol Negotiation or ALPN protocol | ||||
| // given list of possible protocols and a list of the preference order. The | ||||
| // first list must not be empty. It returns the resulting protocol and flag | ||||
| // indicating if the fallback case was reached. | ||||
| func mutualProtocol(protos, preferenceProtos []string) (string, bool) { | ||||
| 	for _, s := range preferenceProtos { | ||||
| 		for _, c := range protos { | ||||
| 			if s == c { | ||||
| 				return s, false | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return protos[0], true | ||||
| } | ||||
							
								
								
									
										1528
									
								
								vendor/github.com/cloudflare/cfssl/scan/crypto/tls/handshake_messages.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1528
									
								
								vendor/github.com/cloudflare/cfssl/scan/crypto/tls/handshake_messages.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										750
									
								
								vendor/github.com/cloudflare/cfssl/scan/crypto/tls/handshake_server.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										750
									
								
								vendor/github.com/cloudflare/cfssl/scan/crypto/tls/handshake_server.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,750 @@ | ||||
| // Copyright 2009 The Go Authors. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package tls | ||||
|  | ||||
| import ( | ||||
| 	"crypto" | ||||
| 	"crypto/ecdsa" | ||||
| 	"crypto/rsa" | ||||
| 	"crypto/subtle" | ||||
| 	"crypto/x509" | ||||
| 	"encoding/asn1" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| ) | ||||
|  | ||||
| // serverHandshakeState contains details of a server handshake in progress. | ||||
| // It's discarded once the handshake has completed. | ||||
| type serverHandshakeState struct { | ||||
| 	c               *Conn | ||||
| 	clientHello     *clientHelloMsg | ||||
| 	hello           *serverHelloMsg | ||||
| 	suite           *cipherSuite | ||||
| 	ellipticOk      bool | ||||
| 	ecdsaOk         bool | ||||
| 	rsaDecryptOk    bool | ||||
| 	rsaSignOk       bool | ||||
| 	sessionState    *sessionState | ||||
| 	finishedHash    finishedHash | ||||
| 	masterSecret    []byte | ||||
| 	certsFromClient [][]byte | ||||
| 	cert            *Certificate | ||||
| } | ||||
|  | ||||
| // serverHandshake performs a TLS handshake as a server. | ||||
| func (c *Conn) serverHandshake() error { | ||||
| 	config := c.config | ||||
|  | ||||
| 	// If this is the first server handshake, we generate a random key to | ||||
| 	// encrypt the tickets with. | ||||
| 	config.serverInitOnce.Do(config.serverInit) | ||||
|  | ||||
| 	hs := serverHandshakeState{ | ||||
| 		c: c, | ||||
| 	} | ||||
| 	isResume, err := hs.readClientHello() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// For an overview of TLS handshaking, see https://tools.ietf.org/html/rfc5246#section-7.3 | ||||
| 	if isResume { | ||||
| 		// The client has included a session ticket and so we do an abbreviated handshake. | ||||
| 		if err := hs.doResumeHandshake(); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if err := hs.establishKeys(); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		// ticketSupported is set in a resumption handshake if the | ||||
| 		// ticket from the client was encrypted with an old session | ||||
| 		// ticket key and thus a refreshed ticket should be sent. | ||||
| 		if hs.hello.ticketSupported { | ||||
| 			if err := hs.sendSessionTicket(); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 		if err := hs.sendFinished(c.firstFinished[:]); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if err := hs.readFinished(nil); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		c.didResume = true | ||||
| 	} else { | ||||
| 		// The client didn't include a session ticket, or it wasn't | ||||
| 		// valid so we do a full handshake. | ||||
| 		if err := hs.doFullHandshake(); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if err := hs.establishKeys(); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if err := hs.readFinished(c.firstFinished[:]); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if err := hs.sendSessionTicket(); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if err := hs.sendFinished(nil); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	c.handshakeComplete = true | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // readClientHello reads a ClientHello message from the client and decides | ||||
| // whether we will perform session resumption. | ||||
| func (hs *serverHandshakeState) readClientHello() (isResume bool, err error) { | ||||
| 	config := hs.c.config | ||||
| 	c := hs.c | ||||
|  | ||||
| 	msg, err := c.readHandshake() | ||||
| 	if err != nil { | ||||
| 		return false, err | ||||
| 	} | ||||
| 	var ok bool | ||||
| 	hs.clientHello, ok = msg.(*clientHelloMsg) | ||||
| 	if !ok { | ||||
| 		c.sendAlert(alertUnexpectedMessage) | ||||
| 		return false, unexpectedMessageError(hs.clientHello, msg) | ||||
| 	} | ||||
| 	c.vers, ok = config.mutualVersion(hs.clientHello.vers) | ||||
| 	if !ok { | ||||
| 		c.sendAlert(alertProtocolVersion) | ||||
| 		return false, fmt.Errorf("tls: client offered an unsupported, maximum protocol version of %x", hs.clientHello.vers) | ||||
| 	} | ||||
| 	c.haveVers = true | ||||
|  | ||||
| 	hs.hello = new(serverHelloMsg) | ||||
|  | ||||
| 	supportedCurve := false | ||||
| 	preferredCurves := config.curvePreferences() | ||||
| Curves: | ||||
| 	for _, curve := range hs.clientHello.supportedCurves { | ||||
| 		for _, supported := range preferredCurves { | ||||
| 			if supported == curve { | ||||
| 				supportedCurve = true | ||||
| 				break Curves | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	supportedPointFormat := false | ||||
| 	for _, pointFormat := range hs.clientHello.supportedPoints { | ||||
| 		if pointFormat == pointFormatUncompressed { | ||||
| 			supportedPointFormat = true | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
| 	hs.ellipticOk = supportedCurve && supportedPointFormat | ||||
|  | ||||
| 	foundCompression := false | ||||
| 	// We only support null compression, so check that the client offered it. | ||||
| 	for _, compression := range hs.clientHello.compressionMethods { | ||||
| 		if compression == compressionNone { | ||||
| 			foundCompression = true | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if !foundCompression { | ||||
| 		c.sendAlert(alertHandshakeFailure) | ||||
| 		return false, errors.New("tls: client does not support uncompressed connections") | ||||
| 	} | ||||
|  | ||||
| 	hs.hello.vers = c.vers | ||||
| 	hs.hello.random = make([]byte, 32) | ||||
| 	_, err = io.ReadFull(config.rand(), hs.hello.random) | ||||
| 	if err != nil { | ||||
| 		c.sendAlert(alertInternalError) | ||||
| 		return false, err | ||||
| 	} | ||||
| 	hs.hello.secureRenegotiation = hs.clientHello.secureRenegotiation | ||||
| 	hs.hello.compressionMethod = compressionNone | ||||
| 	if len(hs.clientHello.serverName) > 0 { | ||||
| 		c.serverName = hs.clientHello.serverName | ||||
| 	} | ||||
|  | ||||
| 	if len(hs.clientHello.alpnProtocols) > 0 { | ||||
| 		if selectedProto, fallback := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos); !fallback { | ||||
| 			hs.hello.alpnProtocol = selectedProto | ||||
| 			c.clientProtocol = selectedProto | ||||
| 		} | ||||
| 	} else { | ||||
| 		// Although sending an empty NPN extension is reasonable, Firefox has | ||||
| 		// had a bug around this. Best to send nothing at all if | ||||
| 		// config.NextProtos is empty. See | ||||
| 		// https://golang.org/issue/5445. | ||||
| 		if hs.clientHello.nextProtoNeg && len(config.NextProtos) > 0 { | ||||
| 			hs.hello.nextProtoNeg = true | ||||
| 			hs.hello.nextProtos = config.NextProtos | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if hs.cert, err = config.getCertificate(&ClientHelloInfo{ | ||||
| 		CipherSuites:    hs.clientHello.cipherSuites, | ||||
| 		ServerName:      hs.clientHello.serverName, | ||||
| 		SupportedCurves: hs.clientHello.supportedCurves, | ||||
| 		SupportedPoints: hs.clientHello.supportedPoints, | ||||
| 	}); err != nil { | ||||
| 		c.sendAlert(alertInternalError) | ||||
| 		return false, err | ||||
| 	} | ||||
| 	if hs.clientHello.scts { | ||||
| 		hs.hello.scts = hs.cert.SignedCertificateTimestamps | ||||
| 	} | ||||
|  | ||||
| 	if priv, ok := hs.cert.PrivateKey.(crypto.Signer); ok { | ||||
| 		switch priv.Public().(type) { | ||||
| 		case *ecdsa.PublicKey: | ||||
| 			hs.ecdsaOk = true | ||||
| 		case *rsa.PublicKey: | ||||
| 			hs.rsaSignOk = true | ||||
| 		default: | ||||
| 			c.sendAlert(alertInternalError) | ||||
| 			return false, fmt.Errorf("crypto/tls: unsupported signing key type (%T)", priv.Public()) | ||||
| 		} | ||||
| 	} | ||||
| 	if priv, ok := hs.cert.PrivateKey.(crypto.Decrypter); ok { | ||||
| 		switch priv.Public().(type) { | ||||
| 		case *rsa.PublicKey: | ||||
| 			hs.rsaDecryptOk = true | ||||
| 		default: | ||||
| 			c.sendAlert(alertInternalError) | ||||
| 			return false, fmt.Errorf("crypto/tls: unsupported decryption key type (%T)", priv.Public()) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if hs.checkForResumption() { | ||||
| 		return true, nil | ||||
| 	} | ||||
|  | ||||
| 	var preferenceList, supportedList []uint16 | ||||
| 	if c.config.PreferServerCipherSuites { | ||||
| 		preferenceList = c.config.cipherSuites() | ||||
| 		supportedList = hs.clientHello.cipherSuites | ||||
| 	} else { | ||||
| 		preferenceList = hs.clientHello.cipherSuites | ||||
| 		supportedList = c.config.cipherSuites() | ||||
| 	} | ||||
|  | ||||
| 	for _, id := range preferenceList { | ||||
| 		if hs.setCipherSuite(id, supportedList, c.vers) { | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if hs.suite == nil { | ||||
| 		c.sendAlert(alertHandshakeFailure) | ||||
| 		return false, errors.New("tls: no cipher suite supported by both client and server") | ||||
| 	} | ||||
|  | ||||
| 	// See https://tools.ietf.org/html/draft-ietf-tls-downgrade-scsv-00. | ||||
| 	for _, id := range hs.clientHello.cipherSuites { | ||||
| 		if id == TLS_FALLBACK_SCSV { | ||||
| 			// The client is doing a fallback connection. | ||||
| 			if hs.clientHello.vers < c.config.maxVersion() { | ||||
| 				c.sendAlert(alertInappropriateFallback) | ||||
| 				return false, errors.New("tls: client using inappropriate protocol fallback") | ||||
| 			} | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return false, nil | ||||
| } | ||||
|  | ||||
| // checkForResumption reports whether we should perform resumption on this connection. | ||||
| func (hs *serverHandshakeState) checkForResumption() bool { | ||||
| 	c := hs.c | ||||
|  | ||||
| 	if c.config.SessionTicketsDisabled { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	var ok bool | ||||
| 	var sessionTicket = append([]uint8{}, hs.clientHello.sessionTicket...) | ||||
| 	if hs.sessionState, ok = c.decryptTicket(sessionTicket); !ok { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	if hs.sessionState.vers > hs.clientHello.vers { | ||||
| 		return false | ||||
| 	} | ||||
| 	if vers, ok := c.config.mutualVersion(hs.sessionState.vers); !ok || vers != hs.sessionState.vers { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	cipherSuiteOk := false | ||||
| 	// Check that the client is still offering the ciphersuite in the session. | ||||
| 	for _, id := range hs.clientHello.cipherSuites { | ||||
| 		if id == hs.sessionState.cipherSuite { | ||||
| 			cipherSuiteOk = true | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
| 	if !cipherSuiteOk { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	// Check that we also support the ciphersuite from the session. | ||||
| 	if !hs.setCipherSuite(hs.sessionState.cipherSuite, c.config.cipherSuites(), hs.sessionState.vers) { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	sessionHasClientCerts := len(hs.sessionState.certificates) != 0 | ||||
| 	needClientCerts := c.config.ClientAuth == RequireAnyClientCert || c.config.ClientAuth == RequireAndVerifyClientCert | ||||
| 	if needClientCerts && !sessionHasClientCerts { | ||||
| 		return false | ||||
| 	} | ||||
| 	if sessionHasClientCerts && c.config.ClientAuth == NoClientCert { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| func (hs *serverHandshakeState) doResumeHandshake() error { | ||||
| 	c := hs.c | ||||
|  | ||||
| 	hs.hello.cipherSuite = hs.suite.id | ||||
| 	// We echo the client's session ID in the ServerHello to let it know | ||||
| 	// that we're doing a resumption. | ||||
| 	hs.hello.sessionId = hs.clientHello.sessionId | ||||
| 	hs.hello.ticketSupported = hs.sessionState.usedOldKey | ||||
| 	hs.finishedHash = newFinishedHash(c.vers, hs.suite) | ||||
| 	hs.finishedHash.discardHandshakeBuffer() | ||||
| 	hs.finishedHash.Write(hs.clientHello.marshal()) | ||||
| 	hs.finishedHash.Write(hs.hello.marshal()) | ||||
| 	c.writeRecord(recordTypeHandshake, hs.hello.marshal()) | ||||
|  | ||||
| 	if len(hs.sessionState.certificates) > 0 { | ||||
| 		if _, err := hs.processCertsFromClient(hs.sessionState.certificates); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	hs.masterSecret = hs.sessionState.masterSecret | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (hs *serverHandshakeState) doFullHandshake() error { | ||||
| 	config := hs.c.config | ||||
| 	c := hs.c | ||||
|  | ||||
| 	if hs.clientHello.ocspStapling && len(hs.cert.OCSPStaple) > 0 { | ||||
| 		hs.hello.ocspStapling = true | ||||
| 	} | ||||
|  | ||||
| 	hs.hello.ticketSupported = hs.clientHello.ticketSupported && !config.SessionTicketsDisabled | ||||
| 	hs.hello.cipherSuite = hs.suite.id | ||||
|  | ||||
| 	hs.finishedHash = newFinishedHash(hs.c.vers, hs.suite) | ||||
| 	if config.ClientAuth == NoClientCert { | ||||
| 		// No need to keep a full record of the handshake if client | ||||
| 		// certificates won't be used. | ||||
| 		hs.finishedHash.discardHandshakeBuffer() | ||||
| 	} | ||||
| 	hs.finishedHash.Write(hs.clientHello.marshal()) | ||||
| 	hs.finishedHash.Write(hs.hello.marshal()) | ||||
| 	c.writeRecord(recordTypeHandshake, hs.hello.marshal()) | ||||
|  | ||||
| 	certMsg := new(certificateMsg) | ||||
| 	certMsg.certificates = hs.cert.Certificate | ||||
| 	hs.finishedHash.Write(certMsg.marshal()) | ||||
| 	c.writeRecord(recordTypeHandshake, certMsg.marshal()) | ||||
|  | ||||
| 	if hs.hello.ocspStapling { | ||||
| 		certStatus := new(certificateStatusMsg) | ||||
| 		certStatus.statusType = statusTypeOCSP | ||||
| 		certStatus.response = hs.cert.OCSPStaple | ||||
| 		hs.finishedHash.Write(certStatus.marshal()) | ||||
| 		c.writeRecord(recordTypeHandshake, certStatus.marshal()) | ||||
| 	} | ||||
|  | ||||
| 	keyAgreement := hs.suite.ka(c.vers) | ||||
| 	skx, err := keyAgreement.generateServerKeyExchange(config, hs.cert, hs.clientHello, hs.hello) | ||||
| 	if err != nil { | ||||
| 		c.sendAlert(alertHandshakeFailure) | ||||
| 		return err | ||||
| 	} | ||||
| 	if skx != nil { | ||||
| 		hs.finishedHash.Write(skx.marshal()) | ||||
| 		c.writeRecord(recordTypeHandshake, skx.marshal()) | ||||
| 	} | ||||
|  | ||||
| 	if config.ClientAuth >= RequestClientCert { | ||||
| 		// Request a client certificate | ||||
| 		certReq := new(certificateRequestMsg) | ||||
| 		certReq.certificateTypes = []byte{ | ||||
| 			byte(certTypeRSASign), | ||||
| 			byte(certTypeECDSASign), | ||||
| 		} | ||||
| 		if c.vers >= VersionTLS12 { | ||||
| 			certReq.hasSignatureAndHash = true | ||||
| 			certReq.signatureAndHashes = supportedSignatureAlgorithms | ||||
| 		} | ||||
|  | ||||
| 		// An empty list of certificateAuthorities signals to | ||||
| 		// the client that it may send any certificate in response | ||||
| 		// to our request. When we know the CAs we trust, then | ||||
| 		// we can send them down, so that the client can choose | ||||
| 		// an appropriate certificate to give to us. | ||||
| 		if config.ClientCAs != nil { | ||||
| 			certReq.certificateAuthorities = config.ClientCAs.Subjects() | ||||
| 		} | ||||
| 		hs.finishedHash.Write(certReq.marshal()) | ||||
| 		c.writeRecord(recordTypeHandshake, certReq.marshal()) | ||||
| 	} | ||||
|  | ||||
| 	helloDone := new(serverHelloDoneMsg) | ||||
| 	hs.finishedHash.Write(helloDone.marshal()) | ||||
| 	c.writeRecord(recordTypeHandshake, helloDone.marshal()) | ||||
|  | ||||
| 	var pub crypto.PublicKey // public key for client auth, if any | ||||
|  | ||||
| 	msg, err := c.readHandshake() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	var ok bool | ||||
| 	// If we requested a client certificate, then the client must send a | ||||
| 	// certificate message, even if it's empty. | ||||
| 	if config.ClientAuth >= RequestClientCert { | ||||
| 		if certMsg, ok = msg.(*certificateMsg); !ok { | ||||
| 			c.sendAlert(alertUnexpectedMessage) | ||||
| 			return unexpectedMessageError(certMsg, msg) | ||||
| 		} | ||||
| 		hs.finishedHash.Write(certMsg.marshal()) | ||||
|  | ||||
| 		if len(certMsg.certificates) == 0 { | ||||
| 			// The client didn't actually send a certificate | ||||
| 			switch config.ClientAuth { | ||||
| 			case RequireAnyClientCert, RequireAndVerifyClientCert: | ||||
| 				c.sendAlert(alertBadCertificate) | ||||
| 				return errors.New("tls: client didn't provide a certificate") | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		pub, err = hs.processCertsFromClient(certMsg.certificates) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		msg, err = c.readHandshake() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Get client key exchange | ||||
| 	ckx, ok := msg.(*clientKeyExchangeMsg) | ||||
| 	if !ok { | ||||
| 		c.sendAlert(alertUnexpectedMessage) | ||||
| 		return unexpectedMessageError(ckx, msg) | ||||
| 	} | ||||
| 	hs.finishedHash.Write(ckx.marshal()) | ||||
|  | ||||
| 	preMasterSecret, err := keyAgreement.processClientKeyExchange(config, hs.cert, ckx, c.vers) | ||||
| 	if err != nil { | ||||
| 		c.sendAlert(alertHandshakeFailure) | ||||
| 		return err | ||||
| 	} | ||||
| 	hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.clientHello.random, hs.hello.random) | ||||
|  | ||||
| 	// If we received a client cert in response to our certificate request message, | ||||
| 	// the client will send us a certificateVerifyMsg immediately after the | ||||
| 	// clientKeyExchangeMsg.  This message is a digest of all preceding | ||||
| 	// handshake-layer messages that is signed using the private key corresponding | ||||
| 	// to the client's certificate. This allows us to verify that the client is in | ||||
| 	// possession of the private key of the certificate. | ||||
| 	if len(c.peerCertificates) > 0 { | ||||
| 		msg, err = c.readHandshake() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		certVerify, ok := msg.(*certificateVerifyMsg) | ||||
| 		if !ok { | ||||
| 			c.sendAlert(alertUnexpectedMessage) | ||||
| 			return unexpectedMessageError(certVerify, msg) | ||||
| 		} | ||||
|  | ||||
| 		// Determine the signature type. | ||||
| 		var signatureAndHash signatureAndHash | ||||
| 		if certVerify.hasSignatureAndHash { | ||||
| 			signatureAndHash = certVerify.signatureAndHash | ||||
| 			if !isSupportedSignatureAndHash(signatureAndHash, supportedSignatureAlgorithms) { | ||||
| 				return errors.New("tls: unsupported hash function for client certificate") | ||||
| 			} | ||||
| 		} else { | ||||
| 			// Before TLS 1.2 the signature algorithm was implicit | ||||
| 			// from the key type, and only one hash per signature | ||||
| 			// algorithm was possible. Leave the hash as zero. | ||||
| 			switch pub.(type) { | ||||
| 			case *ecdsa.PublicKey: | ||||
| 				signatureAndHash.signature = signatureECDSA | ||||
| 			case *rsa.PublicKey: | ||||
| 				signatureAndHash.signature = signatureRSA | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		switch key := pub.(type) { | ||||
| 		case *ecdsa.PublicKey: | ||||
| 			if signatureAndHash.signature != signatureECDSA { | ||||
| 				err = errors.New("bad signature type for client's ECDSA certificate") | ||||
| 				break | ||||
| 			} | ||||
| 			ecdsaSig := new(ecdsaSignature) | ||||
| 			if _, err = asn1.Unmarshal(certVerify.signature, ecdsaSig); err != nil { | ||||
| 				break | ||||
| 			} | ||||
| 			if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 { | ||||
| 				err = errors.New("ECDSA signature contained zero or negative values") | ||||
| 				break | ||||
| 			} | ||||
| 			var digest []byte | ||||
| 			if digest, _, err = hs.finishedHash.hashForClientCertificate(signatureAndHash, hs.masterSecret); err != nil { | ||||
| 				break | ||||
| 			} | ||||
| 			if !ecdsa.Verify(key, digest, ecdsaSig.R, ecdsaSig.S) { | ||||
| 				err = errors.New("ECDSA verification failure") | ||||
| 			} | ||||
| 		case *rsa.PublicKey: | ||||
| 			if signatureAndHash.signature != signatureRSA { | ||||
| 				err = errors.New("bad signature type for client's RSA certificate") | ||||
| 				break | ||||
| 			} | ||||
| 			var digest []byte | ||||
| 			var hashFunc crypto.Hash | ||||
| 			if digest, hashFunc, err = hs.finishedHash.hashForClientCertificate(signatureAndHash, hs.masterSecret); err != nil { | ||||
| 				break | ||||
| 			} | ||||
| 			err = rsa.VerifyPKCS1v15(key, hashFunc, digest, certVerify.signature) | ||||
| 		} | ||||
| 		if err != nil { | ||||
| 			c.sendAlert(alertBadCertificate) | ||||
| 			return errors.New("tls: could not validate signature of connection nonces: " + err.Error()) | ||||
| 		} | ||||
|  | ||||
| 		hs.finishedHash.Write(certVerify.marshal()) | ||||
| 	} | ||||
|  | ||||
| 	hs.finishedHash.discardHandshakeBuffer() | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (hs *serverHandshakeState) establishKeys() error { | ||||
| 	c := hs.c | ||||
|  | ||||
| 	clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV := | ||||
| 		keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.clientHello.random, hs.hello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen) | ||||
|  | ||||
| 	var clientCipher, serverCipher interface{} | ||||
| 	var clientHash, serverHash macFunction | ||||
|  | ||||
| 	if hs.suite.aead == nil { | ||||
| 		clientCipher = hs.suite.cipher(clientKey, clientIV, true /* for reading */) | ||||
| 		clientHash = hs.suite.mac(c.vers, clientMAC) | ||||
| 		serverCipher = hs.suite.cipher(serverKey, serverIV, false /* not for reading */) | ||||
| 		serverHash = hs.suite.mac(c.vers, serverMAC) | ||||
| 	} else { | ||||
| 		clientCipher = hs.suite.aead(clientKey, clientIV) | ||||
| 		serverCipher = hs.suite.aead(serverKey, serverIV) | ||||
| 	} | ||||
|  | ||||
| 	c.in.prepareCipherSpec(c.vers, clientCipher, clientHash) | ||||
| 	c.out.prepareCipherSpec(c.vers, serverCipher, serverHash) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (hs *serverHandshakeState) readFinished(out []byte) error { | ||||
| 	c := hs.c | ||||
|  | ||||
| 	c.readRecord(recordTypeChangeCipherSpec) | ||||
| 	if err := c.in.error(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if hs.hello.nextProtoNeg { | ||||
| 		msg, err := c.readHandshake() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		nextProto, ok := msg.(*nextProtoMsg) | ||||
| 		if !ok { | ||||
| 			c.sendAlert(alertUnexpectedMessage) | ||||
| 			return unexpectedMessageError(nextProto, msg) | ||||
| 		} | ||||
| 		hs.finishedHash.Write(nextProto.marshal()) | ||||
| 		c.clientProtocol = nextProto.proto | ||||
| 	} | ||||
|  | ||||
| 	msg, err := c.readHandshake() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	clientFinished, ok := msg.(*finishedMsg) | ||||
| 	if !ok { | ||||
| 		c.sendAlert(alertUnexpectedMessage) | ||||
| 		return unexpectedMessageError(clientFinished, msg) | ||||
| 	} | ||||
|  | ||||
| 	verify := hs.finishedHash.clientSum(hs.masterSecret) | ||||
| 	if len(verify) != len(clientFinished.verifyData) || | ||||
| 		subtle.ConstantTimeCompare(verify, clientFinished.verifyData) != 1 { | ||||
| 		c.sendAlert(alertHandshakeFailure) | ||||
| 		return errors.New("tls: client's Finished message is incorrect") | ||||
| 	} | ||||
|  | ||||
| 	hs.finishedHash.Write(clientFinished.marshal()) | ||||
| 	copy(out, verify) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (hs *serverHandshakeState) sendSessionTicket() error { | ||||
| 	if !hs.hello.ticketSupported { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	c := hs.c | ||||
| 	m := new(newSessionTicketMsg) | ||||
|  | ||||
| 	var err error | ||||
| 	state := sessionState{ | ||||
| 		vers:         c.vers, | ||||
| 		cipherSuite:  hs.suite.id, | ||||
| 		masterSecret: hs.masterSecret, | ||||
| 		certificates: hs.certsFromClient, | ||||
| 	} | ||||
| 	m.ticket, err = c.encryptTicket(&state) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	hs.finishedHash.Write(m.marshal()) | ||||
| 	c.writeRecord(recordTypeHandshake, m.marshal()) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (hs *serverHandshakeState) sendFinished(out []byte) error { | ||||
| 	c := hs.c | ||||
|  | ||||
| 	c.writeRecord(recordTypeChangeCipherSpec, []byte{1}) | ||||
|  | ||||
| 	finished := new(finishedMsg) | ||||
| 	finished.verifyData = hs.finishedHash.serverSum(hs.masterSecret) | ||||
| 	hs.finishedHash.Write(finished.marshal()) | ||||
| 	c.writeRecord(recordTypeHandshake, finished.marshal()) | ||||
|  | ||||
| 	c.cipherSuite = hs.suite.id | ||||
| 	copy(out, finished.verifyData) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // processCertsFromClient takes a chain of client certificates either from a | ||||
| // Certificates message or from a sessionState and verifies them. It returns | ||||
| // the public key of the leaf certificate. | ||||
| func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (crypto.PublicKey, error) { | ||||
| 	c := hs.c | ||||
|  | ||||
| 	hs.certsFromClient = certificates | ||||
| 	certs := make([]*x509.Certificate, len(certificates)) | ||||
| 	var err error | ||||
| 	for i, asn1Data := range certificates { | ||||
| 		if certs[i], err = x509.ParseCertificate(asn1Data); err != nil { | ||||
| 			c.sendAlert(alertBadCertificate) | ||||
| 			return nil, errors.New("tls: failed to parse client certificate: " + err.Error()) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 { | ||||
| 		opts := x509.VerifyOptions{ | ||||
| 			Roots:         c.config.ClientCAs, | ||||
| 			CurrentTime:   c.config.time(), | ||||
| 			Intermediates: x509.NewCertPool(), | ||||
| 			KeyUsages:     []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, | ||||
| 		} | ||||
|  | ||||
| 		for _, cert := range certs[1:] { | ||||
| 			opts.Intermediates.AddCert(cert) | ||||
| 		} | ||||
|  | ||||
| 		chains, err := certs[0].Verify(opts) | ||||
| 		if err != nil { | ||||
| 			c.sendAlert(alertBadCertificate) | ||||
| 			return nil, errors.New("tls: failed to verify client's certificate: " + err.Error()) | ||||
| 		} | ||||
|  | ||||
| 		c.verifiedChains = chains | ||||
| 	} | ||||
|  | ||||
| 	if len(certs) > 0 { | ||||
| 		var pub crypto.PublicKey | ||||
| 		switch key := certs[0].PublicKey.(type) { | ||||
| 		case *ecdsa.PublicKey, *rsa.PublicKey: | ||||
| 			pub = key | ||||
| 		default: | ||||
| 			c.sendAlert(alertUnsupportedCertificate) | ||||
| 			return nil, fmt.Errorf("tls: client's certificate contains an unsupported public key of type %T", certs[0].PublicKey) | ||||
| 		} | ||||
| 		c.peerCertificates = certs | ||||
| 		return pub, nil | ||||
| 	} | ||||
|  | ||||
| 	return nil, nil | ||||
| } | ||||
|  | ||||
| // setCipherSuite sets a cipherSuite with the given id as the serverHandshakeState | ||||
| // suite if that cipher suite is acceptable to use. | ||||
| // It returns a bool indicating if the suite was set. | ||||
| func (hs *serverHandshakeState) setCipherSuite(id uint16, supportedCipherSuites []uint16, version uint16) bool { | ||||
| 	for _, supported := range supportedCipherSuites { | ||||
| 		if id == supported { | ||||
| 			var candidate *cipherSuite | ||||
|  | ||||
| 			for _, s := range cipherSuites { | ||||
| 				if s.id == id { | ||||
| 					candidate = s | ||||
| 					break | ||||
| 				} | ||||
| 			} | ||||
| 			if candidate == nil { | ||||
| 				continue | ||||
| 			} | ||||
| 			// Don't select a ciphersuite which we can't | ||||
| 			// support for this client. | ||||
| 			if candidate.flags&suiteECDHE != 0 { | ||||
| 				if !hs.ellipticOk { | ||||
| 					continue | ||||
| 				} | ||||
| 				if candidate.flags&suiteECDSA != 0 { | ||||
| 					if !hs.ecdsaOk { | ||||
| 						continue | ||||
| 					} | ||||
| 				} else if !hs.rsaSignOk { | ||||
| 					continue | ||||
| 				} | ||||
| 			} else if !hs.rsaDecryptOk { | ||||
| 				continue | ||||
| 			} | ||||
| 			if version < VersionTLS12 && candidate.flags&suiteTLS12 != 0 { | ||||
| 				continue | ||||
| 			} | ||||
| 			hs.suite = candidate | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
							
								
								
									
										405
									
								
								vendor/github.com/cloudflare/cfssl/scan/crypto/tls/key_agreement.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										405
									
								
								vendor/github.com/cloudflare/cfssl/scan/crypto/tls/key_agreement.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,405 @@ | ||||
| // Copyright 2010 The Go Authors. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package tls | ||||
|  | ||||
| import ( | ||||
| 	"crypto" | ||||
| 	"crypto/ecdsa" | ||||
| 	"crypto/elliptic" | ||||
| 	"crypto/md5" | ||||
| 	"crypto/rsa" | ||||
| 	"crypto/sha1" | ||||
| 	"crypto/x509" | ||||
| 	"encoding/asn1" | ||||
| 	"errors" | ||||
| 	"io" | ||||
| 	"math/big" | ||||
| ) | ||||
|  | ||||
| var errClientKeyExchange = errors.New("tls: invalid ClientKeyExchange message") | ||||
| var errServerKeyExchange = errors.New("tls: invalid ServerKeyExchange message") | ||||
|  | ||||
| // rsaKeyAgreement implements the standard TLS key agreement where the client | ||||
| // encrypts the pre-master secret to the server's public key. | ||||
| type rsaKeyAgreement struct{} | ||||
|  | ||||
| func (ka rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) { | ||||
| 	return nil, nil | ||||
| } | ||||
|  | ||||
| func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) { | ||||
| 	if len(ckx.ciphertext) < 2 { | ||||
| 		return nil, errClientKeyExchange | ||||
| 	} | ||||
|  | ||||
| 	ciphertext := ckx.ciphertext | ||||
| 	if version != VersionSSL30 { | ||||
| 		ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1]) | ||||
| 		if ciphertextLen != len(ckx.ciphertext)-2 { | ||||
| 			return nil, errClientKeyExchange | ||||
| 		} | ||||
| 		ciphertext = ckx.ciphertext[2:] | ||||
| 	} | ||||
| 	priv, ok := cert.PrivateKey.(crypto.Decrypter) | ||||
| 	if !ok { | ||||
| 		return nil, errors.New("tls: certificate private key does not implement crypto.Decrypter") | ||||
| 	} | ||||
| 	// Perform constant time RSA PKCS#1 v1.5 decryption | ||||
| 	preMasterSecret, err := priv.Decrypt(config.rand(), ciphertext, &rsa.PKCS1v15DecryptOptions{SessionKeyLen: 48}) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	// We don't check the version number in the premaster secret.  For one, | ||||
| 	// by checking it, we would leak information about the validity of the | ||||
| 	// encrypted pre-master secret. Secondly, it provides only a small | ||||
| 	// benefit against a downgrade attack and some implementations send the | ||||
| 	// wrong version anyway. See the discussion at the end of section | ||||
| 	// 7.4.7.1 of RFC 4346. | ||||
| 	return preMasterSecret, nil | ||||
| } | ||||
|  | ||||
| func (ka rsaKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error { | ||||
| 	return errors.New("tls: unexpected ServerKeyExchange") | ||||
| } | ||||
|  | ||||
| func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) { | ||||
| 	preMasterSecret := make([]byte, 48) | ||||
| 	preMasterSecret[0] = byte(clientHello.vers >> 8) | ||||
| 	preMasterSecret[1] = byte(clientHello.vers) | ||||
| 	_, err := io.ReadFull(config.rand(), preMasterSecret[2:]) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
|  | ||||
| 	encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), preMasterSecret) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	ckx := new(clientKeyExchangeMsg) | ||||
| 	ckx.ciphertext = make([]byte, len(encrypted)+2) | ||||
| 	ckx.ciphertext[0] = byte(len(encrypted) >> 8) | ||||
| 	ckx.ciphertext[1] = byte(len(encrypted)) | ||||
| 	copy(ckx.ciphertext[2:], encrypted) | ||||
| 	return preMasterSecret, ckx, nil | ||||
| } | ||||
|  | ||||
| // sha1Hash calculates a SHA1 hash over the given byte slices. | ||||
| func sha1Hash(slices [][]byte) []byte { | ||||
| 	hsha1 := sha1.New() | ||||
| 	for _, slice := range slices { | ||||
| 		hsha1.Write(slice) | ||||
| 	} | ||||
| 	return hsha1.Sum(nil) | ||||
| } | ||||
|  | ||||
| // md5SHA1Hash implements TLS 1.0's hybrid hash function which consists of the | ||||
| // concatenation of an MD5 and SHA1 hash. | ||||
| func md5SHA1Hash(slices [][]byte) []byte { | ||||
| 	md5sha1 := make([]byte, md5.Size+sha1.Size) | ||||
| 	hmd5 := md5.New() | ||||
| 	for _, slice := range slices { | ||||
| 		hmd5.Write(slice) | ||||
| 	} | ||||
| 	copy(md5sha1, hmd5.Sum(nil)) | ||||
| 	copy(md5sha1[md5.Size:], sha1Hash(slices)) | ||||
| 	return md5sha1 | ||||
| } | ||||
|  | ||||
| // hashForServerKeyExchange hashes the given slices and returns their digest | ||||
| // and the identifier of the hash function used. The sigAndHash argument is | ||||
| // only used for >= TLS 1.2 and precisely identifies the hash function to use. | ||||
| func hashForServerKeyExchange(sigAndHash signatureAndHash, version uint16, slices ...[]byte) ([]byte, crypto.Hash, error) { | ||||
| 	if version >= VersionTLS12 { | ||||
| 		if !isSupportedSignatureAndHash(sigAndHash, supportedSignatureAlgorithms) { | ||||
| 			return nil, crypto.Hash(0), errors.New("tls: unsupported hash function used by peer") | ||||
| 		} | ||||
| 		hashFunc, err := lookupTLSHash(sigAndHash.hash) | ||||
| 		if err != nil { | ||||
| 			return nil, crypto.Hash(0), err | ||||
| 		} | ||||
| 		h := hashFunc.New() | ||||
| 		for _, slice := range slices { | ||||
| 			h.Write(slice) | ||||
| 		} | ||||
| 		digest := h.Sum(nil) | ||||
| 		return digest, hashFunc, nil | ||||
| 	} | ||||
| 	if sigAndHash.signature == signatureECDSA { | ||||
| 		return sha1Hash(slices), crypto.SHA1, nil | ||||
| 	} | ||||
| 	return md5SHA1Hash(slices), crypto.MD5SHA1, nil | ||||
| } | ||||
|  | ||||
| // pickTLS12HashForSignature returns a TLS 1.2 hash identifier for signing a | ||||
| // ServerKeyExchange given the signature type being used and the client's | ||||
| // advertised list of supported signature and hash combinations. | ||||
| func pickTLS12HashForSignature(sigType uint8, clientList []signatureAndHash) (uint8, error) { | ||||
| 	if len(clientList) == 0 { | ||||
| 		// If the client didn't specify any signature_algorithms | ||||
| 		// extension then we can assume that it supports SHA1. See | ||||
| 		// http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 | ||||
| 		return hashSHA1, nil | ||||
| 	} | ||||
|  | ||||
| 	for _, sigAndHash := range clientList { | ||||
| 		if sigAndHash.signature != sigType { | ||||
| 			continue | ||||
| 		} | ||||
| 		if isSupportedSignatureAndHash(sigAndHash, supportedSignatureAlgorithms) { | ||||
| 			return sigAndHash.hash, nil | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return 0, errors.New("tls: client doesn't support any common hash functions") | ||||
| } | ||||
|  | ||||
| func curveForCurveID(id CurveID) (elliptic.Curve, bool) { | ||||
| 	switch id { | ||||
| 	case CurveP256: | ||||
| 		return elliptic.P256(), true | ||||
| 	case CurveP384: | ||||
| 		return elliptic.P384(), true | ||||
| 	case CurveP521: | ||||
| 		return elliptic.P521(), true | ||||
| 	default: | ||||
| 		return nil, false | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| // ecdheRSAKeyAgreement implements a TLS key agreement where the server | ||||
| // generates a ephemeral EC public/private key pair and signs it. The | ||||
| // pre-master secret is then calculated using ECDH. The signature may | ||||
| // either be ECDSA or RSA. | ||||
| type ecdheKeyAgreement struct { | ||||
| 	version    uint16 | ||||
| 	sigType    uint8 | ||||
| 	privateKey []byte | ||||
| 	curve      elliptic.Curve | ||||
| 	x, y       *big.Int | ||||
| } | ||||
|  | ||||
| func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) { | ||||
| 	var curveid CurveID | ||||
| 	preferredCurves := config.curvePreferences() | ||||
|  | ||||
| NextCandidate: | ||||
| 	for _, candidate := range preferredCurves { | ||||
| 		for _, c := range clientHello.supportedCurves { | ||||
| 			if candidate == c { | ||||
| 				curveid = c | ||||
| 				break NextCandidate | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if curveid == 0 { | ||||
| 		return nil, errors.New("tls: no supported elliptic curves offered") | ||||
| 	} | ||||
|  | ||||
| 	var ok bool | ||||
| 	if ka.curve, ok = curveForCurveID(curveid); !ok { | ||||
| 		return nil, errors.New("tls: preferredCurves includes unsupported curve") | ||||
| 	} | ||||
|  | ||||
| 	var x, y *big.Int | ||||
| 	var err error | ||||
| 	ka.privateKey, x, y, err = elliptic.GenerateKey(ka.curve, config.rand()) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	ecdhePublic := elliptic.Marshal(ka.curve, x, y) | ||||
|  | ||||
| 	// http://tools.ietf.org/html/rfc4492#section-5.4 | ||||
| 	serverECDHParams := make([]byte, 1+2+1+len(ecdhePublic)) | ||||
| 	serverECDHParams[0] = 3 // named curve | ||||
| 	serverECDHParams[1] = byte(curveid >> 8) | ||||
| 	serverECDHParams[2] = byte(curveid) | ||||
| 	serverECDHParams[3] = byte(len(ecdhePublic)) | ||||
| 	copy(serverECDHParams[4:], ecdhePublic) | ||||
|  | ||||
| 	sigAndHash := signatureAndHash{signature: ka.sigType} | ||||
|  | ||||
| 	if ka.version >= VersionTLS12 { | ||||
| 		if sigAndHash.hash, err = pickTLS12HashForSignature(ka.sigType, clientHello.signatureAndHashes); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	digest, hashFunc, err := hashForServerKeyExchange(sigAndHash, ka.version, clientHello.random, hello.random, serverECDHParams) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	priv, ok := cert.PrivateKey.(crypto.Signer) | ||||
| 	if !ok { | ||||
| 		return nil, errors.New("tls: certificate private key does not implement crypto.Signer") | ||||
| 	} | ||||
| 	var sig []byte | ||||
| 	switch ka.sigType { | ||||
| 	case signatureECDSA: | ||||
| 		_, ok := priv.Public().(*ecdsa.PublicKey) | ||||
| 		if !ok { | ||||
| 			return nil, errors.New("ECDHE ECDSA requires an ECDSA server key") | ||||
| 		} | ||||
| 	case signatureRSA: | ||||
| 		_, ok := priv.Public().(*rsa.PublicKey) | ||||
| 		if !ok { | ||||
| 			return nil, errors.New("ECDHE RSA requires a RSA server key") | ||||
| 		} | ||||
| 	default: | ||||
| 		return nil, errors.New("unknown ECDHE signature algorithm") | ||||
| 	} | ||||
| 	sig, err = priv.Sign(config.rand(), digest, hashFunc) | ||||
| 	if err != nil { | ||||
| 		return nil, errors.New("failed to sign ECDHE parameters: " + err.Error()) | ||||
| 	} | ||||
|  | ||||
| 	skx := new(serverKeyExchangeMsg) | ||||
| 	sigAndHashLen := 0 | ||||
| 	if ka.version >= VersionTLS12 { | ||||
| 		sigAndHashLen = 2 | ||||
| 	} | ||||
| 	skx.key = make([]byte, len(serverECDHParams)+sigAndHashLen+2+len(sig)) | ||||
| 	copy(skx.key, serverECDHParams) | ||||
| 	k := skx.key[len(serverECDHParams):] | ||||
| 	if ka.version >= VersionTLS12 { | ||||
| 		k[0] = sigAndHash.hash | ||||
| 		k[1] = sigAndHash.signature | ||||
| 		k = k[2:] | ||||
| 	} | ||||
| 	k[0] = byte(len(sig) >> 8) | ||||
| 	k[1] = byte(len(sig)) | ||||
| 	copy(k[2:], sig) | ||||
|  | ||||
| 	return skx, nil | ||||
| } | ||||
|  | ||||
| func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) { | ||||
| 	if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 { | ||||
| 		return nil, errClientKeyExchange | ||||
| 	} | ||||
| 	x, y := elliptic.Unmarshal(ka.curve, ckx.ciphertext[1:]) | ||||
| 	if x == nil { | ||||
| 		return nil, errClientKeyExchange | ||||
| 	} | ||||
| 	if !ka.curve.IsOnCurve(x, y) { | ||||
| 		return nil, errClientKeyExchange | ||||
| 	} | ||||
| 	x, _ = ka.curve.ScalarMult(x, y, ka.privateKey) | ||||
| 	preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3) | ||||
| 	xBytes := x.Bytes() | ||||
| 	copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes) | ||||
|  | ||||
| 	return preMasterSecret, nil | ||||
| } | ||||
|  | ||||
| func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error { | ||||
| 	if len(skx.key) < 4 { | ||||
| 		return errServerKeyExchange | ||||
| 	} | ||||
| 	if skx.key[0] != 3 { // named curve | ||||
| 		return errors.New("tls: server selected unsupported curve") | ||||
| 	} | ||||
| 	curveid := CurveID(skx.key[1])<<8 | CurveID(skx.key[2]) | ||||
|  | ||||
| 	var ok bool | ||||
| 	if ka.curve, ok = curveForCurveID(curveid); !ok { | ||||
| 		return errors.New("tls: server selected unsupported curve") | ||||
| 	} | ||||
|  | ||||
| 	publicLen := int(skx.key[3]) | ||||
| 	if publicLen+4 > len(skx.key) { | ||||
| 		return errServerKeyExchange | ||||
| 	} | ||||
| 	ka.x, ka.y = elliptic.Unmarshal(ka.curve, skx.key[4:4+publicLen]) | ||||
| 	if ka.x == nil { | ||||
| 		return errServerKeyExchange | ||||
| 	} | ||||
| 	if !ka.curve.IsOnCurve(ka.x, ka.y) { | ||||
| 		return errServerKeyExchange | ||||
| 	} | ||||
| 	serverECDHParams := skx.key[:4+publicLen] | ||||
|  | ||||
| 	sig := skx.key[4+publicLen:] | ||||
| 	if len(sig) < 2 { | ||||
| 		return errServerKeyExchange | ||||
| 	} | ||||
|  | ||||
| 	sigAndHash := signatureAndHash{signature: ka.sigType} | ||||
| 	if ka.version >= VersionTLS12 { | ||||
| 		// handle SignatureAndHashAlgorithm | ||||
| 		sigAndHash = signatureAndHash{hash: sig[0], signature: sig[1]} | ||||
| 		if sigAndHash.signature != ka.sigType { | ||||
| 			return errServerKeyExchange | ||||
| 		} | ||||
| 		sig = sig[2:] | ||||
| 		if len(sig) < 2 { | ||||
| 			return errServerKeyExchange | ||||
| 		} | ||||
| 	} | ||||
| 	sigLen := int(sig[0])<<8 | int(sig[1]) | ||||
| 	if sigLen+2 != len(sig) { | ||||
| 		return errServerKeyExchange | ||||
| 	} | ||||
| 	sig = sig[2:] | ||||
|  | ||||
| 	digest, hashFunc, err := hashForServerKeyExchange(sigAndHash, ka.version, clientHello.random, serverHello.random, serverECDHParams) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	switch ka.sigType { | ||||
| 	case signatureECDSA: | ||||
| 		pubKey, ok := cert.PublicKey.(*ecdsa.PublicKey) | ||||
| 		if !ok { | ||||
| 			return errors.New("ECDHE ECDSA requires a ECDSA server public key") | ||||
| 		} | ||||
| 		ecdsaSig := new(ecdsaSignature) | ||||
| 		if _, err := asn1.Unmarshal(sig, ecdsaSig); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 { | ||||
| 			return errors.New("ECDSA signature contained zero or negative values") | ||||
| 		} | ||||
| 		if !ecdsa.Verify(pubKey, digest, ecdsaSig.R, ecdsaSig.S) { | ||||
| 			return errors.New("ECDSA verification failure") | ||||
| 		} | ||||
| 	case signatureRSA: | ||||
| 		pubKey, ok := cert.PublicKey.(*rsa.PublicKey) | ||||
| 		if !ok { | ||||
| 			return errors.New("ECDHE RSA requires a RSA server public key") | ||||
| 		} | ||||
| 		if err := rsa.VerifyPKCS1v15(pubKey, hashFunc, digest, sig); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	default: | ||||
| 		return errors.New("unknown ECDHE signature algorithm") | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) { | ||||
| 	if ka.curve == nil { | ||||
| 		return nil, nil, errors.New("missing ServerKeyExchange message") | ||||
| 	} | ||||
| 	priv, mx, my, err := elliptic.GenerateKey(ka.curve, config.rand()) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	x, _ := ka.curve.ScalarMult(ka.x, ka.y, priv) | ||||
| 	preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3) | ||||
| 	xBytes := x.Bytes() | ||||
| 	copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes) | ||||
|  | ||||
| 	serialized := elliptic.Marshal(ka.curve, mx, my) | ||||
|  | ||||
| 	ckx := new(clientKeyExchangeMsg) | ||||
| 	ckx.ciphertext = make([]byte, 1+len(serialized)) | ||||
| 	ckx.ciphertext[0] = byte(len(serialized)) | ||||
| 	copy(ckx.ciphertext[1:], serialized) | ||||
|  | ||||
| 	return preMasterSecret, ckx, nil | ||||
| } | ||||
							
								
								
									
										368
									
								
								vendor/github.com/cloudflare/cfssl/scan/crypto/tls/prf.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										368
									
								
								vendor/github.com/cloudflare/cfssl/scan/crypto/tls/prf.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,368 @@ | ||||
| // Copyright 2009 The Go Authors. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package tls | ||||
|  | ||||
| import ( | ||||
| 	"crypto" | ||||
| 	"crypto/hmac" | ||||
| 	"crypto/md5" | ||||
| 	"crypto/sha1" | ||||
| 	"crypto/sha256" | ||||
| 	"crypto/sha512" | ||||
| 	"errors" | ||||
| 	"hash" | ||||
| ) | ||||
|  | ||||
| // Split a premaster secret in two as specified in RFC 4346, section 5. | ||||
| func splitPreMasterSecret(secret []byte) (s1, s2 []byte) { | ||||
| 	s1 = secret[0 : (len(secret)+1)/2] | ||||
| 	s2 = secret[len(secret)/2:] | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // pHash implements the P_hash function, as defined in RFC 4346, section 5. | ||||
| func pHash(result, secret, seed []byte, hash func() hash.Hash) { | ||||
| 	h := hmac.New(hash, secret) | ||||
| 	h.Write(seed) | ||||
| 	a := h.Sum(nil) | ||||
|  | ||||
| 	j := 0 | ||||
| 	for j < len(result) { | ||||
| 		h.Reset() | ||||
| 		h.Write(a) | ||||
| 		h.Write(seed) | ||||
| 		b := h.Sum(nil) | ||||
| 		todo := len(b) | ||||
| 		if j+todo > len(result) { | ||||
| 			todo = len(result) - j | ||||
| 		} | ||||
| 		copy(result[j:j+todo], b) | ||||
| 		j += todo | ||||
|  | ||||
| 		h.Reset() | ||||
| 		h.Write(a) | ||||
| 		a = h.Sum(nil) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // prf10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, section 5. | ||||
| func prf10(result, secret, label, seed []byte) { | ||||
| 	hashSHA1 := sha1.New | ||||
| 	hashMD5 := md5.New | ||||
|  | ||||
| 	labelAndSeed := make([]byte, len(label)+len(seed)) | ||||
| 	copy(labelAndSeed, label) | ||||
| 	copy(labelAndSeed[len(label):], seed) | ||||
|  | ||||
| 	s1, s2 := splitPreMasterSecret(secret) | ||||
| 	pHash(result, s1, labelAndSeed, hashMD5) | ||||
| 	result2 := make([]byte, len(result)) | ||||
| 	pHash(result2, s2, labelAndSeed, hashSHA1) | ||||
|  | ||||
| 	for i, b := range result2 { | ||||
| 		result[i] ^= b | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // prf12 implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, section 5. | ||||
| func prf12(hashFunc func() hash.Hash) func(result, secret, label, seed []byte) { | ||||
| 	return func(result, secret, label, seed []byte) { | ||||
| 		labelAndSeed := make([]byte, len(label)+len(seed)) | ||||
| 		copy(labelAndSeed, label) | ||||
| 		copy(labelAndSeed[len(label):], seed) | ||||
|  | ||||
| 		pHash(result, secret, labelAndSeed, hashFunc) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // prf30 implements the SSL 3.0 pseudo-random function, as defined in | ||||
| // www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt section 6. | ||||
| func prf30(result, secret, label, seed []byte) { | ||||
| 	hashSHA1 := sha1.New() | ||||
| 	hashMD5 := md5.New() | ||||
|  | ||||
| 	done := 0 | ||||
| 	i := 0 | ||||
| 	// RFC5246 section 6.3 says that the largest PRF output needed is 128 | ||||
| 	// bytes. Since no more ciphersuites will be added to SSLv3, this will | ||||
| 	// remain true. Each iteration gives us 16 bytes so 10 iterations will | ||||
| 	// be sufficient. | ||||
| 	var b [11]byte | ||||
| 	for done < len(result) { | ||||
| 		for j := 0; j <= i; j++ { | ||||
| 			b[j] = 'A' + byte(i) | ||||
| 		} | ||||
|  | ||||
| 		hashSHA1.Reset() | ||||
| 		hashSHA1.Write(b[:i+1]) | ||||
| 		hashSHA1.Write(secret) | ||||
| 		hashSHA1.Write(seed) | ||||
| 		digest := hashSHA1.Sum(nil) | ||||
|  | ||||
| 		hashMD5.Reset() | ||||
| 		hashMD5.Write(secret) | ||||
| 		hashMD5.Write(digest) | ||||
|  | ||||
| 		done += copy(result[done:], hashMD5.Sum(nil)) | ||||
| 		i++ | ||||
| 	} | ||||
| } | ||||
|  | ||||
| const ( | ||||
| 	tlsRandomLength      = 32 // Length of a random nonce in TLS 1.1. | ||||
| 	masterSecretLength   = 48 // Length of a master secret in TLS 1.1. | ||||
| 	finishedVerifyLength = 12 // Length of verify_data in a Finished message. | ||||
| ) | ||||
|  | ||||
| var masterSecretLabel = []byte("master secret") | ||||
| var keyExpansionLabel = []byte("key expansion") | ||||
| var clientFinishedLabel = []byte("client finished") | ||||
| var serverFinishedLabel = []byte("server finished") | ||||
|  | ||||
| func prfAndHashForVersion(version uint16, suite *cipherSuite) (func(result, secret, label, seed []byte), crypto.Hash) { | ||||
| 	switch version { | ||||
| 	case VersionSSL30: | ||||
| 		return prf30, crypto.Hash(0) | ||||
| 	case VersionTLS10, VersionTLS11: | ||||
| 		return prf10, crypto.Hash(0) | ||||
| 	case VersionTLS12: | ||||
| 		if suite.flags&suiteSHA384 != 0 { | ||||
| 			return prf12(sha512.New384), crypto.SHA384 | ||||
| 		} | ||||
| 		return prf12(sha256.New), crypto.SHA256 | ||||
| 	default: | ||||
| 		panic("unknown version") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func prfForVersion(version uint16, suite *cipherSuite) func(result, secret, label, seed []byte) { | ||||
| 	prf, _ := prfAndHashForVersion(version, suite) | ||||
| 	return prf | ||||
| } | ||||
|  | ||||
| // masterFromPreMasterSecret generates the master secret from the pre-master | ||||
| // secret. See http://tools.ietf.org/html/rfc5246#section-8.1 | ||||
| func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, clientRandom, serverRandom []byte) []byte { | ||||
| 	seed := make([]byte, 0, len(clientRandom)+len(serverRandom)) | ||||
| 	seed = append(seed, clientRandom...) | ||||
| 	seed = append(seed, serverRandom...) | ||||
|  | ||||
| 	masterSecret := make([]byte, masterSecretLength) | ||||
| 	prfForVersion(version, suite)(masterSecret, preMasterSecret, masterSecretLabel, seed) | ||||
| 	return masterSecret | ||||
| } | ||||
|  | ||||
| // keysFromMasterSecret generates the connection keys from the master | ||||
| // secret, given the lengths of the MAC key, cipher key and IV, as defined in | ||||
| // RFC 2246, section 6.3. | ||||
| func keysFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) { | ||||
| 	seed := make([]byte, 0, len(serverRandom)+len(clientRandom)) | ||||
| 	seed = append(seed, serverRandom...) | ||||
| 	seed = append(seed, clientRandom...) | ||||
|  | ||||
| 	n := 2*macLen + 2*keyLen + 2*ivLen | ||||
| 	keyMaterial := make([]byte, n) | ||||
| 	prfForVersion(version, suite)(keyMaterial, masterSecret, keyExpansionLabel, seed) | ||||
| 	clientMAC = keyMaterial[:macLen] | ||||
| 	keyMaterial = keyMaterial[macLen:] | ||||
| 	serverMAC = keyMaterial[:macLen] | ||||
| 	keyMaterial = keyMaterial[macLen:] | ||||
| 	clientKey = keyMaterial[:keyLen] | ||||
| 	keyMaterial = keyMaterial[keyLen:] | ||||
| 	serverKey = keyMaterial[:keyLen] | ||||
| 	keyMaterial = keyMaterial[keyLen:] | ||||
| 	clientIV = keyMaterial[:ivLen] | ||||
| 	keyMaterial = keyMaterial[ivLen:] | ||||
| 	serverIV = keyMaterial[:ivLen] | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // lookupTLSHash looks up the corresponding crypto.Hash for a given | ||||
| // TLS hash identifier. | ||||
| func lookupTLSHash(hash uint8) (crypto.Hash, error) { | ||||
| 	switch hash { | ||||
| 	case hashSHA1: | ||||
| 		return crypto.SHA1, nil | ||||
| 	case hashSHA256: | ||||
| 		return crypto.SHA256, nil | ||||
| 	case hashSHA384: | ||||
| 		return crypto.SHA384, nil | ||||
| 	default: | ||||
| 		return 0, errors.New("tls: unsupported hash algorithm") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func newFinishedHash(version uint16, cipherSuite *cipherSuite) finishedHash { | ||||
| 	var buffer []byte | ||||
| 	if version == VersionSSL30 || version >= VersionTLS12 { | ||||
| 		buffer = []byte{} | ||||
| 	} | ||||
|  | ||||
| 	prf, hash := prfAndHashForVersion(version, cipherSuite) | ||||
| 	if hash != 0 { | ||||
| 		return finishedHash{hash.New(), hash.New(), nil, nil, buffer, version, prf} | ||||
| 	} | ||||
|  | ||||
| 	return finishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), buffer, version, prf} | ||||
| } | ||||
|  | ||||
| // A finishedHash calculates the hash of a set of handshake messages suitable | ||||
| // for including in a Finished message. | ||||
| type finishedHash struct { | ||||
| 	client hash.Hash | ||||
| 	server hash.Hash | ||||
|  | ||||
| 	// Prior to TLS 1.2, an additional MD5 hash is required. | ||||
| 	clientMD5 hash.Hash | ||||
| 	serverMD5 hash.Hash | ||||
|  | ||||
| 	// In TLS 1.2, a full buffer is sadly required. | ||||
| 	buffer []byte | ||||
|  | ||||
| 	version uint16 | ||||
| 	prf     func(result, secret, label, seed []byte) | ||||
| } | ||||
|  | ||||
| func (h *finishedHash) Write(msg []byte) (n int, err error) { | ||||
| 	h.client.Write(msg) | ||||
| 	h.server.Write(msg) | ||||
|  | ||||
| 	if h.version < VersionTLS12 { | ||||
| 		h.clientMD5.Write(msg) | ||||
| 		h.serverMD5.Write(msg) | ||||
| 	} | ||||
|  | ||||
| 	if h.buffer != nil { | ||||
| 		h.buffer = append(h.buffer, msg...) | ||||
| 	} | ||||
|  | ||||
| 	return len(msg), nil | ||||
| } | ||||
|  | ||||
| func (h finishedHash) Sum() []byte { | ||||
| 	if h.version >= VersionTLS12 { | ||||
| 		return h.client.Sum(nil) | ||||
| 	} | ||||
|  | ||||
| 	out := make([]byte, 0, md5.Size+sha1.Size) | ||||
| 	out = h.clientMD5.Sum(out) | ||||
| 	return h.client.Sum(out) | ||||
| } | ||||
|  | ||||
| // finishedSum30 calculates the contents of the verify_data member of a SSLv3 | ||||
| // Finished message given the MD5 and SHA1 hashes of a set of handshake | ||||
| // messages. | ||||
| func finishedSum30(md5, sha1 hash.Hash, masterSecret []byte, magic []byte) []byte { | ||||
| 	md5.Write(magic) | ||||
| 	md5.Write(masterSecret) | ||||
| 	md5.Write(ssl30Pad1[:]) | ||||
| 	md5Digest := md5.Sum(nil) | ||||
|  | ||||
| 	md5.Reset() | ||||
| 	md5.Write(masterSecret) | ||||
| 	md5.Write(ssl30Pad2[:]) | ||||
| 	md5.Write(md5Digest) | ||||
| 	md5Digest = md5.Sum(nil) | ||||
|  | ||||
| 	sha1.Write(magic) | ||||
| 	sha1.Write(masterSecret) | ||||
| 	sha1.Write(ssl30Pad1[:40]) | ||||
| 	sha1Digest := sha1.Sum(nil) | ||||
|  | ||||
| 	sha1.Reset() | ||||
| 	sha1.Write(masterSecret) | ||||
| 	sha1.Write(ssl30Pad2[:40]) | ||||
| 	sha1.Write(sha1Digest) | ||||
| 	sha1Digest = sha1.Sum(nil) | ||||
|  | ||||
| 	ret := make([]byte, len(md5Digest)+len(sha1Digest)) | ||||
| 	copy(ret, md5Digest) | ||||
| 	copy(ret[len(md5Digest):], sha1Digest) | ||||
| 	return ret | ||||
| } | ||||
|  | ||||
| var ssl3ClientFinishedMagic = [4]byte{0x43, 0x4c, 0x4e, 0x54} | ||||
| var ssl3ServerFinishedMagic = [4]byte{0x53, 0x52, 0x56, 0x52} | ||||
|  | ||||
| // clientSum returns the contents of the verify_data member of a client's | ||||
| // Finished message. | ||||
| func (h finishedHash) clientSum(masterSecret []byte) []byte { | ||||
| 	if h.version == VersionSSL30 { | ||||
| 		return finishedSum30(h.clientMD5, h.client, masterSecret, ssl3ClientFinishedMagic[:]) | ||||
| 	} | ||||
|  | ||||
| 	out := make([]byte, finishedVerifyLength) | ||||
| 	h.prf(out, masterSecret, clientFinishedLabel, h.Sum()) | ||||
| 	return out | ||||
| } | ||||
|  | ||||
| // serverSum returns the contents of the verify_data member of a server's | ||||
| // Finished message. | ||||
| func (h finishedHash) serverSum(masterSecret []byte) []byte { | ||||
| 	if h.version == VersionSSL30 { | ||||
| 		return finishedSum30(h.serverMD5, h.server, masterSecret, ssl3ServerFinishedMagic[:]) | ||||
| 	} | ||||
|  | ||||
| 	out := make([]byte, finishedVerifyLength) | ||||
| 	h.prf(out, masterSecret, serverFinishedLabel, h.Sum()) | ||||
| 	return out | ||||
| } | ||||
|  | ||||
| // selectClientCertSignatureAlgorithm returns a signatureAndHash to sign a | ||||
| // client's CertificateVerify with, or an error if none can be found. | ||||
| func (h finishedHash) selectClientCertSignatureAlgorithm(serverList []signatureAndHash, sigType uint8) (signatureAndHash, error) { | ||||
| 	if h.version < VersionTLS12 { | ||||
| 		// Nothing to negotiate before TLS 1.2. | ||||
| 		return signatureAndHash{signature: sigType}, nil | ||||
| 	} | ||||
|  | ||||
| 	for _, v := range serverList { | ||||
| 		if v.signature == sigType && isSupportedSignatureAndHash(v, supportedSignatureAlgorithms) { | ||||
| 			return v, nil | ||||
| 		} | ||||
| 	} | ||||
| 	return signatureAndHash{}, errors.New("tls: no supported signature algorithm found for signing client certificate") | ||||
| } | ||||
|  | ||||
| // hashForClientCertificate returns a digest, hash function, and TLS 1.2 hash | ||||
| // id suitable for signing by a TLS client certificate. | ||||
| func (h finishedHash) hashForClientCertificate(signatureAndHash signatureAndHash, masterSecret []byte) ([]byte, crypto.Hash, error) { | ||||
| 	if (h.version == VersionSSL30 || h.version >= VersionTLS12) && h.buffer == nil { | ||||
| 		panic("a handshake hash for a client-certificate was requested after discarding the handshake buffer") | ||||
| 	} | ||||
|  | ||||
| 	if h.version == VersionSSL30 { | ||||
| 		if signatureAndHash.signature != signatureRSA { | ||||
| 			return nil, 0, errors.New("tls: unsupported signature type for client certificate") | ||||
| 		} | ||||
|  | ||||
| 		md5Hash := md5.New() | ||||
| 		md5Hash.Write(h.buffer) | ||||
| 		sha1Hash := sha1.New() | ||||
| 		sha1Hash.Write(h.buffer) | ||||
| 		return finishedSum30(md5Hash, sha1Hash, masterSecret, nil), crypto.MD5SHA1, nil | ||||
| 	} | ||||
| 	if h.version >= VersionTLS12 { | ||||
| 		hashAlg, err := lookupTLSHash(signatureAndHash.hash) | ||||
| 		if err != nil { | ||||
| 			return nil, 0, err | ||||
| 		} | ||||
| 		hash := hashAlg.New() | ||||
| 		hash.Write(h.buffer) | ||||
| 		return hash.Sum(nil), hashAlg, nil | ||||
| 	} | ||||
|  | ||||
| 	if signatureAndHash.signature == signatureECDSA { | ||||
| 		return h.server.Sum(nil), crypto.SHA1, nil | ||||
| 	} | ||||
|  | ||||
| 	return h.Sum(), crypto.MD5SHA1, nil | ||||
| } | ||||
|  | ||||
| // discardHandshakeBuffer is called when there is no more need to | ||||
| // buffer the entirety of the handshake messages. | ||||
| func (h *finishedHash) discardHandshakeBuffer() { | ||||
| 	h.buffer = nil | ||||
| } | ||||
							
								
								
									
										204
									
								
								vendor/github.com/cloudflare/cfssl/scan/crypto/tls/ticket.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										204
									
								
								vendor/github.com/cloudflare/cfssl/scan/crypto/tls/ticket.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,204 @@ | ||||
| // Copyright 2012 The Go Authors. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package tls | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"crypto/aes" | ||||
| 	"crypto/cipher" | ||||
| 	"crypto/hmac" | ||||
| 	"crypto/sha256" | ||||
| 	"crypto/subtle" | ||||
| 	"errors" | ||||
| 	"io" | ||||
| ) | ||||
|  | ||||
| // sessionState contains the information that is serialized into a session | ||||
| // ticket in order to later resume a connection. | ||||
| type sessionState struct { | ||||
| 	vers         uint16 | ||||
| 	cipherSuite  uint16 | ||||
| 	masterSecret []byte | ||||
| 	certificates [][]byte | ||||
| 	// usedOldKey is true if the ticket from which this session came from | ||||
| 	// was encrypted with an older key and thus should be refreshed. | ||||
| 	usedOldKey bool | ||||
| } | ||||
|  | ||||
| func (s *sessionState) equal(i interface{}) bool { | ||||
| 	s1, ok := i.(*sessionState) | ||||
| 	if !ok { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	if s.vers != s1.vers || | ||||
| 		s.cipherSuite != s1.cipherSuite || | ||||
| 		!bytes.Equal(s.masterSecret, s1.masterSecret) { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	if len(s.certificates) != len(s1.certificates) { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	for i := range s.certificates { | ||||
| 		if !bytes.Equal(s.certificates[i], s1.certificates[i]) { | ||||
| 			return false | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| func (s *sessionState) marshal() []byte { | ||||
| 	length := 2 + 2 + 2 + len(s.masterSecret) + 2 | ||||
| 	for _, cert := range s.certificates { | ||||
| 		length += 4 + len(cert) | ||||
| 	} | ||||
|  | ||||
| 	ret := make([]byte, length) | ||||
| 	x := ret | ||||
| 	x[0] = byte(s.vers >> 8) | ||||
| 	x[1] = byte(s.vers) | ||||
| 	x[2] = byte(s.cipherSuite >> 8) | ||||
| 	x[3] = byte(s.cipherSuite) | ||||
| 	x[4] = byte(len(s.masterSecret) >> 8) | ||||
| 	x[5] = byte(len(s.masterSecret)) | ||||
| 	x = x[6:] | ||||
| 	copy(x, s.masterSecret) | ||||
| 	x = x[len(s.masterSecret):] | ||||
|  | ||||
| 	x[0] = byte(len(s.certificates) >> 8) | ||||
| 	x[1] = byte(len(s.certificates)) | ||||
| 	x = x[2:] | ||||
|  | ||||
| 	for _, cert := range s.certificates { | ||||
| 		x[0] = byte(len(cert) >> 24) | ||||
| 		x[1] = byte(len(cert) >> 16) | ||||
| 		x[2] = byte(len(cert) >> 8) | ||||
| 		x[3] = byte(len(cert)) | ||||
| 		copy(x[4:], cert) | ||||
| 		x = x[4+len(cert):] | ||||
| 	} | ||||
|  | ||||
| 	return ret | ||||
| } | ||||
|  | ||||
| func (s *sessionState) unmarshal(data []byte) bool { | ||||
| 	if len(data) < 8 { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	s.vers = uint16(data[0])<<8 | uint16(data[1]) | ||||
| 	s.cipherSuite = uint16(data[2])<<8 | uint16(data[3]) | ||||
| 	masterSecretLen := int(data[4])<<8 | int(data[5]) | ||||
| 	data = data[6:] | ||||
| 	if len(data) < masterSecretLen { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	s.masterSecret = data[:masterSecretLen] | ||||
| 	data = data[masterSecretLen:] | ||||
|  | ||||
| 	if len(data) < 2 { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	numCerts := int(data[0])<<8 | int(data[1]) | ||||
| 	data = data[2:] | ||||
|  | ||||
| 	s.certificates = make([][]byte, numCerts) | ||||
| 	for i := range s.certificates { | ||||
| 		if len(data) < 4 { | ||||
| 			return false | ||||
| 		} | ||||
| 		certLen := int(data[0])<<24 | int(data[1])<<16 | int(data[2])<<8 | int(data[3]) | ||||
| 		data = data[4:] | ||||
| 		if certLen < 0 { | ||||
| 			return false | ||||
| 		} | ||||
| 		if len(data) < certLen { | ||||
| 			return false | ||||
| 		} | ||||
| 		s.certificates[i] = data[:certLen] | ||||
| 		data = data[certLen:] | ||||
| 	} | ||||
|  | ||||
| 	if len(data) > 0 { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| func (c *Conn) encryptTicket(state *sessionState) ([]byte, error) { | ||||
| 	serialized := state.marshal() | ||||
| 	encrypted := make([]byte, ticketKeyNameLen+aes.BlockSize+len(serialized)+sha256.Size) | ||||
| 	keyName := encrypted[:ticketKeyNameLen] | ||||
| 	iv := encrypted[ticketKeyNameLen : ticketKeyNameLen+aes.BlockSize] | ||||
| 	macBytes := encrypted[len(encrypted)-sha256.Size:] | ||||
|  | ||||
| 	if _, err := io.ReadFull(c.config.rand(), iv); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	key := c.config.ticketKeys()[0] | ||||
| 	copy(keyName, key.keyName[:]) | ||||
| 	block, err := aes.NewCipher(key.aesKey[:]) | ||||
| 	if err != nil { | ||||
| 		return nil, errors.New("tls: failed to create cipher while encrypting ticket: " + err.Error()) | ||||
| 	} | ||||
| 	cipher.NewCTR(block, iv).XORKeyStream(encrypted[ticketKeyNameLen+aes.BlockSize:], serialized) | ||||
|  | ||||
| 	mac := hmac.New(sha256.New, key.hmacKey[:]) | ||||
| 	mac.Write(encrypted[:len(encrypted)-sha256.Size]) | ||||
| 	mac.Sum(macBytes[:0]) | ||||
|  | ||||
| 	return encrypted, nil | ||||
| } | ||||
|  | ||||
| func (c *Conn) decryptTicket(encrypted []byte) (*sessionState, bool) { | ||||
| 	if c.config.SessionTicketsDisabled || | ||||
| 		len(encrypted) < ticketKeyNameLen+aes.BlockSize+sha256.Size { | ||||
| 		return nil, false | ||||
| 	} | ||||
|  | ||||
| 	keyName := encrypted[:ticketKeyNameLen] | ||||
| 	iv := encrypted[ticketKeyNameLen : ticketKeyNameLen+aes.BlockSize] | ||||
| 	macBytes := encrypted[len(encrypted)-sha256.Size:] | ||||
|  | ||||
| 	keys := c.config.ticketKeys() | ||||
| 	keyIndex := -1 | ||||
| 	for i, candidateKey := range keys { | ||||
| 		if bytes.Equal(keyName, candidateKey.keyName[:]) { | ||||
| 			keyIndex = i | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if keyIndex == -1 { | ||||
| 		return nil, false | ||||
| 	} | ||||
| 	key := &keys[keyIndex] | ||||
|  | ||||
| 	mac := hmac.New(sha256.New, key.hmacKey[:]) | ||||
| 	mac.Write(encrypted[:len(encrypted)-sha256.Size]) | ||||
| 	expected := mac.Sum(nil) | ||||
|  | ||||
| 	if subtle.ConstantTimeCompare(macBytes, expected) != 1 { | ||||
| 		return nil, false | ||||
| 	} | ||||
|  | ||||
| 	block, err := aes.NewCipher(key.aesKey[:]) | ||||
| 	if err != nil { | ||||
| 		return nil, false | ||||
| 	} | ||||
| 	ciphertext := encrypted[ticketKeyNameLen+aes.BlockSize : len(encrypted)-sha256.Size] | ||||
| 	plaintext := ciphertext | ||||
| 	cipher.NewCTR(block, iv).XORKeyStream(plaintext, ciphertext) | ||||
|  | ||||
| 	state := &sessionState{usedOldKey: keyIndex > 0} | ||||
| 	ok := state.unmarshal(plaintext) | ||||
| 	return state, ok | ||||
| } | ||||
							
								
								
									
										298
									
								
								vendor/github.com/cloudflare/cfssl/scan/crypto/tls/tls.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										298
									
								
								vendor/github.com/cloudflare/cfssl/scan/crypto/tls/tls.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,298 @@ | ||||
| // Copyright 2009 The Go Authors. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| // Package tls partially implements TLS 1.2, as specified in RFC 5246. | ||||
| package tls | ||||
|  | ||||
| // BUG(agl): The crypto/tls package does not implement countermeasures | ||||
| // against Lucky13 attacks on CBC-mode encryption. See | ||||
| // http://www.isg.rhul.ac.uk/tls/TLStiming.pdf and | ||||
| // https://www.imperialviolet.org/2013/02/04/luckythirteen.html. | ||||
|  | ||||
| import ( | ||||
| 	"crypto" | ||||
| 	"crypto/ecdsa" | ||||
| 	"crypto/rsa" | ||||
| 	"crypto/x509" | ||||
| 	"encoding/pem" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"net" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| // Server returns a new TLS server side connection | ||||
| // using conn as the underlying transport. | ||||
| // The configuration config must be non-nil and must include | ||||
| // at least one certificate or else set GetCertificate. | ||||
| func Server(conn net.Conn, config *Config) *Conn { | ||||
| 	return &Conn{conn: conn, config: config} | ||||
| } | ||||
|  | ||||
| // Client returns a new TLS client side connection | ||||
| // using conn as the underlying transport. | ||||
| // The config cannot be nil: users must set either ServerName or | ||||
| // InsecureSkipVerify in the config. | ||||
| func Client(conn net.Conn, config *Config) *Conn { | ||||
| 	return &Conn{conn: conn, config: config, isClient: true} | ||||
| } | ||||
|  | ||||
| // A listener implements a network listener (net.Listener) for TLS connections. | ||||
| type listener struct { | ||||
| 	net.Listener | ||||
| 	config *Config | ||||
| } | ||||
|  | ||||
| // Accept waits for and returns the next incoming TLS connection. | ||||
| // The returned connection c is a *tls.Conn. | ||||
| func (l *listener) Accept() (c net.Conn, err error) { | ||||
| 	c, err = l.Listener.Accept() | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	c = Server(c, l.config) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // NewListener creates a Listener which accepts connections from an inner | ||||
| // Listener and wraps each connection with Server. | ||||
| // The configuration config must be non-nil and must include | ||||
| // at least one certificate or else set GetCertificate. | ||||
| func NewListener(inner net.Listener, config *Config) net.Listener { | ||||
| 	l := new(listener) | ||||
| 	l.Listener = inner | ||||
| 	l.config = config | ||||
| 	return l | ||||
| } | ||||
|  | ||||
| // Listen creates a TLS listener accepting connections on the | ||||
| // given network address using net.Listen. | ||||
| // The configuration config must be non-nil and must include | ||||
| // at least one certificate or else set GetCertificate. | ||||
| func Listen(network, laddr string, config *Config) (net.Listener, error) { | ||||
| 	if config == nil || (len(config.Certificates) == 0 && config.GetCertificate == nil) { | ||||
| 		return nil, errors.New("tls: neither Certificates nor GetCertificate set in Config") | ||||
| 	} | ||||
| 	l, err := net.Listen(network, laddr) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return NewListener(l, config), nil | ||||
| } | ||||
|  | ||||
| type timeoutError struct{} | ||||
|  | ||||
| func (timeoutError) Error() string   { return "tls: DialWithDialer timed out" } | ||||
| func (timeoutError) Timeout() bool   { return true } | ||||
| func (timeoutError) Temporary() bool { return true } | ||||
|  | ||||
| // DialWithDialer connects to the given network address using dialer.Dial and | ||||
| // then initiates a TLS handshake, returning the resulting TLS connection. Any | ||||
| // timeout or deadline given in the dialer apply to connection and TLS | ||||
| // handshake as a whole. | ||||
| // | ||||
| // DialWithDialer interprets a nil configuration as equivalent to the zero | ||||
| // configuration; see the documentation of Config for the defaults. | ||||
| func DialWithDialer(dialer *net.Dialer, network, addr string, config *Config) (*Conn, error) { | ||||
| 	// We want the Timeout and Deadline values from dialer to cover the | ||||
| 	// whole process: TCP connection and TLS handshake. This means that we | ||||
| 	// also need to start our own timers now. | ||||
| 	timeout := dialer.Timeout | ||||
|  | ||||
| 	if !dialer.Deadline.IsZero() { | ||||
| 		deadlineTimeout := dialer.Deadline.Sub(time.Now()) | ||||
| 		if timeout == 0 || deadlineTimeout < timeout { | ||||
| 			timeout = deadlineTimeout | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	var errChannel chan error | ||||
|  | ||||
| 	if timeout != 0 { | ||||
| 		errChannel = make(chan error, 2) | ||||
| 		time.AfterFunc(timeout, func() { | ||||
| 			errChannel <- timeoutError{} | ||||
| 		}) | ||||
| 	} | ||||
|  | ||||
| 	rawConn, err := dialer.Dial(network, addr) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	colonPos := strings.LastIndex(addr, ":") | ||||
| 	if colonPos == -1 { | ||||
| 		colonPos = len(addr) | ||||
| 	} | ||||
| 	hostname := addr[:colonPos] | ||||
|  | ||||
| 	if config == nil { | ||||
| 		config = defaultConfig() | ||||
| 	} | ||||
| 	// If no ServerName is set, infer the ServerName | ||||
| 	// from the hostname we're connecting to. | ||||
| 	if config.ServerName == "" { | ||||
| 		// Make a copy to avoid polluting argument or default. | ||||
| 		c := *config | ||||
| 		c.ServerName = hostname | ||||
| 		config = &c | ||||
| 	} | ||||
|  | ||||
| 	conn := Client(rawConn, config) | ||||
|  | ||||
| 	if timeout == 0 { | ||||
| 		err = conn.Handshake() | ||||
| 	} else { | ||||
| 		go func() { | ||||
| 			errChannel <- conn.Handshake() | ||||
| 		}() | ||||
|  | ||||
| 		err = <-errChannel | ||||
| 	} | ||||
|  | ||||
| 	if err != nil { | ||||
| 		rawConn.Close() | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return conn, nil | ||||
| } | ||||
|  | ||||
| // Dial connects to the given network address using net.Dial | ||||
| // and then initiates a TLS handshake, returning the resulting | ||||
| // TLS connection. | ||||
| // Dial interprets a nil configuration as equivalent to | ||||
| // the zero configuration; see the documentation of Config | ||||
| // for the defaults. | ||||
| func Dial(network, addr string, config *Config) (*Conn, error) { | ||||
| 	return DialWithDialer(new(net.Dialer), network, addr, config) | ||||
| } | ||||
|  | ||||
| // LoadX509KeyPair reads and parses a public/private key pair from a pair of | ||||
| // files. The files must contain PEM encoded data. On successful return, | ||||
| // Certificate.Leaf will be nil because the parsed form of the certificate is | ||||
| // not retained. | ||||
| func LoadX509KeyPair(certFile, keyFile string) (Certificate, error) { | ||||
| 	certPEMBlock, err := ioutil.ReadFile(certFile) | ||||
| 	if err != nil { | ||||
| 		return Certificate{}, err | ||||
| 	} | ||||
| 	keyPEMBlock, err := ioutil.ReadFile(keyFile) | ||||
| 	if err != nil { | ||||
| 		return Certificate{}, err | ||||
| 	} | ||||
| 	return X509KeyPair(certPEMBlock, keyPEMBlock) | ||||
| } | ||||
|  | ||||
| // X509KeyPair parses a public/private key pair from a pair of | ||||
| // PEM encoded data. On successful return, Certificate.Leaf will be nil because | ||||
| // the parsed form of the certificate is not retained. | ||||
| func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (Certificate, error) { | ||||
| 	fail := func(err error) (Certificate, error) { return Certificate{}, err } | ||||
|  | ||||
| 	var cert Certificate | ||||
| 	var skippedBlockTypes []string | ||||
| 	for { | ||||
| 		var certDERBlock *pem.Block | ||||
| 		certDERBlock, certPEMBlock = pem.Decode(certPEMBlock) | ||||
| 		if certDERBlock == nil { | ||||
| 			break | ||||
| 		} | ||||
| 		if certDERBlock.Type == "CERTIFICATE" { | ||||
| 			cert.Certificate = append(cert.Certificate, certDERBlock.Bytes) | ||||
| 		} else { | ||||
| 			skippedBlockTypes = append(skippedBlockTypes, certDERBlock.Type) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if len(cert.Certificate) == 0 { | ||||
| 		if len(skippedBlockTypes) == 0 { | ||||
| 			return fail(errors.New("crypto/tls: failed to find any PEM data in certificate input")) | ||||
| 		} else if len(skippedBlockTypes) == 1 && strings.HasSuffix(skippedBlockTypes[0], "PRIVATE KEY") { | ||||
| 			return fail(errors.New("crypto/tls: failed to find certificate PEM data in certificate input, but did find a private key; PEM inputs may have been switched")) | ||||
| 		} else { | ||||
| 			return fail(fmt.Errorf("crypto/tls: failed to find \"CERTIFICATE\" PEM block in certificate input after skipping PEM blocks of the following types: %v", skippedBlockTypes)) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	skippedBlockTypes = skippedBlockTypes[:0] | ||||
| 	var keyDERBlock *pem.Block | ||||
| 	for { | ||||
| 		keyDERBlock, keyPEMBlock = pem.Decode(keyPEMBlock) | ||||
| 		if keyDERBlock == nil { | ||||
| 			if len(skippedBlockTypes) == 0 { | ||||
| 				return fail(errors.New("crypto/tls: failed to find any PEM data in key input")) | ||||
| 			} else if len(skippedBlockTypes) == 1 && skippedBlockTypes[0] == "CERTIFICATE" { | ||||
| 				return fail(errors.New("crypto/tls: found a certificate rather than a key in the PEM for the private key")) | ||||
| 			} else { | ||||
| 				return fail(fmt.Errorf("crypto/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)) | ||||
| 			} | ||||
| 		} | ||||
| 		if keyDERBlock.Type == "PRIVATE KEY" || strings.HasSuffix(keyDERBlock.Type, " PRIVATE KEY") { | ||||
| 			break | ||||
| 		} | ||||
| 		skippedBlockTypes = append(skippedBlockTypes, keyDERBlock.Type) | ||||
| 	} | ||||
|  | ||||
| 	var err error | ||||
| 	cert.PrivateKey, err = parsePrivateKey(keyDERBlock.Bytes) | ||||
| 	if err != nil { | ||||
| 		return fail(err) | ||||
| 	} | ||||
|  | ||||
| 	// We don't need to parse the public key for TLS, but we so do anyway | ||||
| 	// to check that it looks sane and matches the private key. | ||||
| 	x509Cert, err := x509.ParseCertificate(cert.Certificate[0]) | ||||
| 	if err != nil { | ||||
| 		return fail(err) | ||||
| 	} | ||||
|  | ||||
| 	switch pub := x509Cert.PublicKey.(type) { | ||||
| 	case *rsa.PublicKey: | ||||
| 		priv, ok := cert.PrivateKey.(*rsa.PrivateKey) | ||||
| 		if !ok { | ||||
| 			return fail(errors.New("crypto/tls: private key type does not match public key type")) | ||||
| 		} | ||||
| 		if pub.N.Cmp(priv.N) != 0 { | ||||
| 			return fail(errors.New("crypto/tls: private key does not match public key")) | ||||
| 		} | ||||
| 	case *ecdsa.PublicKey: | ||||
| 		priv, ok := cert.PrivateKey.(*ecdsa.PrivateKey) | ||||
| 		if !ok { | ||||
| 			return fail(errors.New("crypto/tls: private key type does not match public key type")) | ||||
|  | ||||
| 		} | ||||
| 		if pub.X.Cmp(priv.X) != 0 || pub.Y.Cmp(priv.Y) != 0 { | ||||
| 			return fail(errors.New("crypto/tls: private key does not match public key")) | ||||
| 		} | ||||
| 	default: | ||||
| 		return fail(errors.New("crypto/tls: unknown public key algorithm")) | ||||
| 	} | ||||
|  | ||||
| 	return cert, nil | ||||
| } | ||||
|  | ||||
| // Attempt to parse the given private key DER block. OpenSSL 0.9.8 generates | ||||
| // PKCS#1 private keys by default, while OpenSSL 1.0.0 generates PKCS#8 keys. | ||||
| // OpenSSL ecparam generates SEC1 EC private keys for ECDSA. We try all three. | ||||
| func parsePrivateKey(der []byte) (crypto.PrivateKey, error) { | ||||
| 	if key, err := x509.ParsePKCS1PrivateKey(der); err == nil { | ||||
| 		return key, nil | ||||
| 	} | ||||
| 	if key, err := x509.ParsePKCS8PrivateKey(der); err == nil { | ||||
| 		switch key := key.(type) { | ||||
| 		case *rsa.PrivateKey, *ecdsa.PrivateKey: | ||||
| 			return key, nil | ||||
| 		default: | ||||
| 			return nil, errors.New("crypto/tls: found unknown private key type in PKCS#8 wrapping") | ||||
| 		} | ||||
| 	} | ||||
| 	if key, err := x509.ParseECPrivateKey(der); err == nil { | ||||
| 		return key, nil | ||||
| 	} | ||||
|  | ||||
| 	return nil, errors.New("crypto/tls: failed to parse private key") | ||||
| } | ||||
							
								
								
									
										2
									
								
								vendor/github.com/cloudflare/cfssl/scan/pki.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/cloudflare/cfssl/scan/pki.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -2,13 +2,13 @@ package scan | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"crypto/tls" | ||||
| 	"crypto/x509" | ||||
| 	"fmt" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/cloudflare/cfssl/helpers" | ||||
| 	"github.com/cloudflare/cfssl/revoke" | ||||
| 	"github.com/cloudflare/cfssl/scan/crypto/tls" | ||||
| ) | ||||
|  | ||||
| // PKI contains scanners for the Public Key Infrastructure. | ||||
|   | ||||
							
								
								
									
										2
									
								
								vendor/github.com/cloudflare/cfssl/scan/scan_common.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/cloudflare/cfssl/scan/scan_common.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,7 +1,6 @@ | ||||
| package scan | ||||
|  | ||||
| import ( | ||||
| 	"crypto/tls" | ||||
| 	"crypto/x509" | ||||
| 	"net" | ||||
| 	"net/http" | ||||
| @@ -11,6 +10,7 @@ import ( | ||||
|  | ||||
| 	"github.com/cloudflare/cfssl/helpers" | ||||
| 	"github.com/cloudflare/cfssl/log" | ||||
| 	"github.com/cloudflare/cfssl/scan/crypto/tls" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
|   | ||||
							
								
								
									
										4
									
								
								vendor/github.com/cloudflare/cfssl/scan/tls_handshake.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/cloudflare/cfssl/scan/tls_handshake.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -2,13 +2,13 @@ package scan | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"crypto/tls" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"net" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/cloudflare/cfssl/helpers" | ||||
| 	"github.com/cloudflare/cfssl/scan/crypto/tls" | ||||
| ) | ||||
|  | ||||
| // Sentinel for failures in sayHello. Should always be caught. | ||||
| @@ -19,7 +19,7 @@ var TLSHandshake = &Family{ | ||||
| 	Description: "Scans for host's SSL/TLS version and cipher suite negotiation", | ||||
| 	Scanners: map[string]*Scanner{ | ||||
| 		"CipherSuite": { | ||||
| 			"Determines host's cipher suites accepted and prefered order", | ||||
| 			"Determines host's cipher suites accepted and preferred order", | ||||
| 			cipherSuiteScan, | ||||
| 		}, | ||||
| 		"SigAlgs": { | ||||
|   | ||||
							
								
								
									
										2
									
								
								vendor/github.com/cloudflare/cfssl/scan/tls_session.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/cloudflare/cfssl/scan/tls_session.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,6 +1,6 @@ | ||||
| package scan | ||||
|  | ||||
| import "crypto/tls" | ||||
| import "github.com/cloudflare/cfssl/scan/crypto/tls" | ||||
|  | ||||
| // TLSSession contains tests of host TLS Session Resumption via | ||||
| // Session Tickets and Session IDs | ||||
|   | ||||
		Reference in New Issue
	
	Block a user