Vendor cfssl and cfssljson
This commit is contained in:
427
vendor/github.com/cloudflare/cfssl/scan/tls_handshake.go
generated
vendored
Normal file
427
vendor/github.com/cloudflare/cfssl/scan/tls_handshake.go
generated
vendored
Normal file
@@ -0,0 +1,427 @@
|
||||
package scan
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"github.com/cloudflare/cfssl/helpers"
|
||||
)
|
||||
|
||||
// Sentinel for failures in sayHello. Should always be caught.
|
||||
var errHelloFailed = errors.New("Handshake failed in sayHello")
|
||||
|
||||
// TLSHandshake contains scanners testing host cipher suite negotiation
|
||||
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",
|
||||
cipherSuiteScan,
|
||||
},
|
||||
"SigAlgs": {
|
||||
"Determines host's accepted signature and hash algorithms",
|
||||
sigAlgsScan,
|
||||
},
|
||||
"CertsBySigAlgs": {
|
||||
"Determines host's certificate signature algorithm matching client's accepted signature and hash algorithms",
|
||||
certSigAlgsScan,
|
||||
},
|
||||
"CertsByCiphers": {
|
||||
"Determines host's certificate signature algorithm matching client's accepted ciphers",
|
||||
certSigAlgsScanByCipher,
|
||||
},
|
||||
"ECCurves": {
|
||||
"Determines the host's ec curve support for TLS 1.2",
|
||||
ecCurveScan,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func getCipherIndex(ciphers []uint16, serverCipher uint16) (cipherIndex int, err error) {
|
||||
//func getCipherIndex(ciphers []uint16, serverCipher uint16) (cipherIndex int, err error) {
|
||||
// fmt.Println(serverCipher, ciphers)
|
||||
var cipherID uint16
|
||||
for cipherIndex, cipherID = range ciphers {
|
||||
if serverCipher == cipherID {
|
||||
return
|
||||
}
|
||||
}
|
||||
err = fmt.Errorf("server negotiated ciphersuite we didn't send: %s", tls.CipherSuites[serverCipher])
|
||||
return
|
||||
}
|
||||
|
||||
func getCurveIndex(curves []tls.CurveID, serverCurve tls.CurveID) (curveIndex int, err error) {
|
||||
var curveID tls.CurveID
|
||||
for curveIndex, curveID = range curves {
|
||||
if serverCurve == curveID {
|
||||
return
|
||||
}
|
||||
}
|
||||
err = fmt.Errorf("server negotiated elliptic curve we didn't send: %s", tls.Curves[serverCurve])
|
||||
return
|
||||
}
|
||||
|
||||
func sayHello(addr, hostname string, ciphers []uint16, curves []tls.CurveID, vers uint16, sigAlgs []tls.SignatureAndHash) (cipherIndex, curveIndex int, certs [][]byte, err error) {
|
||||
tcpConn, err := net.Dial(Network, addr)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
config := defaultTLSConfig(hostname)
|
||||
config.MinVersion = vers
|
||||
config.MaxVersion = vers
|
||||
if ciphers == nil {
|
||||
ciphers = allCiphersIDs()
|
||||
}
|
||||
config.CipherSuites = ciphers
|
||||
|
||||
if curves == nil {
|
||||
curves = allCurvesIDs()
|
||||
}
|
||||
config.CurvePreferences = curves
|
||||
|
||||
if sigAlgs == nil {
|
||||
sigAlgs = tls.AllSignatureAndHashAlgorithms
|
||||
}
|
||||
|
||||
conn := tls.Client(tcpConn, config)
|
||||
serverCipher, serverCurveType, serverCurve, serverVersion, certificates, err := conn.SayHello(sigAlgs)
|
||||
certs = certificates
|
||||
conn.Close()
|
||||
if err != nil {
|
||||
err = errHelloFailed
|
||||
return
|
||||
}
|
||||
|
||||
if serverVersion != vers {
|
||||
err = fmt.Errorf("server negotiated protocol version we didn't send: %s", tls.Versions[serverVersion])
|
||||
return
|
||||
}
|
||||
|
||||
cipherIndex, err = getCipherIndex(ciphers, serverCipher)
|
||||
|
||||
if tls.CipherSuites[serverCipher].EllipticCurve {
|
||||
if curves == nil {
|
||||
curves = allCurvesIDs()
|
||||
}
|
||||
if serverCurveType != 3 {
|
||||
err = fmt.Errorf("server negotiated non-named ECDH parameters; we didn't analyze them. Server curve type: %d", serverCurveType)
|
||||
return
|
||||
}
|
||||
curveIndex, err = getCurveIndex(curves, serverCurve)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func allCiphersIDs() []uint16 {
|
||||
ciphers := make([]uint16, 0, len(tls.CipherSuites))
|
||||
for cipherID := range tls.CipherSuites {
|
||||
ciphers = append(ciphers, cipherID)
|
||||
}
|
||||
return ciphers
|
||||
}
|
||||
|
||||
func allECDHECiphersIDs() []uint16 {
|
||||
var ecdheCiphers = map[uint16]tls.CipherSuite{
|
||||
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},
|
||||
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},
|
||||
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},
|
||||
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},
|
||||
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},
|
||||
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},
|
||||
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},
|
||||
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},
|
||||
0XC05D: {Name: "TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384", ForwardSecret: true, 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},
|
||||
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},
|
||||
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},
|
||||
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},
|
||||
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},
|
||||
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},
|
||||
}
|
||||
|
||||
ciphers := make([]uint16, 0, len(ecdheCiphers))
|
||||
for cipherID := range ecdheCiphers {
|
||||
ciphers = append(ciphers, cipherID)
|
||||
}
|
||||
return ciphers
|
||||
}
|
||||
|
||||
func allCurvesIDs() []tls.CurveID {
|
||||
curves := make([]tls.CurveID, 0, len(tls.Curves))
|
||||
for curveID := range tls.Curves {
|
||||
// No unassigned or explicit curves in the scan, per http://tools.ietf.org/html/rfc4492#section-5.4
|
||||
if curveID == 0 || curveID == 65281 || curveID == 65282 {
|
||||
continue
|
||||
} else {
|
||||
curves = append(curves, curveID)
|
||||
}
|
||||
}
|
||||
return curves
|
||||
}
|
||||
|
||||
type cipherDatum struct {
|
||||
versionID uint16
|
||||
curves []tls.CurveID
|
||||
}
|
||||
|
||||
// cipherVersions contains lists of host's supported cipher suites based on SSL/TLS Version.
|
||||
// If a cipher suite uses ECC, also contains a list of supported curves by SSL/TLS Version.
|
||||
type cipherVersions struct {
|
||||
cipherID uint16
|
||||
data []cipherDatum
|
||||
}
|
||||
|
||||
type cipherVersionList []cipherVersions
|
||||
|
||||
func (cvList cipherVersionList) String() string {
|
||||
cvStrings := make([]string, len(cvList))
|
||||
for i, c := range cvList {
|
||||
versStrings := make([]string, len(c.data))
|
||||
for j, d := range c.data {
|
||||
curveStrings := make([]string, len(d.curves))
|
||||
for k, c := range d.curves {
|
||||
curveStrings[k] = tls.Curves[c]
|
||||
}
|
||||
versStrings[j] = fmt.Sprintf("%s: [ %s ]", tls.Versions[d.versionID], strings.Join(curveStrings, ","))
|
||||
}
|
||||
cvStrings[i] = fmt.Sprintf("%s\t%s", tls.CipherSuites[c.cipherID], strings.Join(versStrings, ","))
|
||||
}
|
||||
return strings.Join(cvStrings, "\n")
|
||||
}
|
||||
|
||||
func (cvList cipherVersionList) MarshalJSON() ([]byte, error) {
|
||||
b := new(bytes.Buffer)
|
||||
cvStrs := make([]string, len(cvList))
|
||||
for i, cv := range cvList {
|
||||
versStrings := make([]string, len(cv.data))
|
||||
for j, d := range cv.data {
|
||||
curveStrings := make([]string, len(d.curves))
|
||||
if len(d.curves) > 0 {
|
||||
for k, c := range d.curves {
|
||||
curveStrings[k] = fmt.Sprintf("\"%s\"", tls.Curves[c])
|
||||
}
|
||||
versStrings[j] = fmt.Sprintf("{\"%s\":[%s]}", tls.Versions[d.versionID], strings.Join(curveStrings, ","))
|
||||
} else {
|
||||
versStrings[j] = fmt.Sprintf("\"%s\"", tls.Versions[d.versionID])
|
||||
}
|
||||
}
|
||||
cvStrs[i] = fmt.Sprintf("{\"%s\":[%s]}", tls.CipherSuites[cv.cipherID].String(), strings.Join(versStrings, ","))
|
||||
}
|
||||
fmt.Fprintf(b, "[%s]", strings.Join(cvStrs, ","))
|
||||
return b.Bytes(), nil
|
||||
}
|
||||
|
||||
func doCurveScan(addr, hostname string, vers, cipherID uint16, ciphers []uint16) (supportedCurves []tls.CurveID, err error) {
|
||||
allCurves := allCurvesIDs()
|
||||
curves := make([]tls.CurveID, len(allCurves))
|
||||
copy(curves, allCurves)
|
||||
for len(curves) > 0 {
|
||||
var curveIndex int
|
||||
_, curveIndex, _, err = sayHello(addr, hostname, []uint16{cipherID}, curves, vers, nil)
|
||||
if err != nil {
|
||||
// This case is expected, because eventually we ask only for curves the server doesn't support
|
||||
if err == errHelloFailed {
|
||||
err = nil
|
||||
break
|
||||
}
|
||||
return
|
||||
}
|
||||
curveID := curves[curveIndex]
|
||||
supportedCurves = append(supportedCurves, curveID)
|
||||
curves = append(curves[:curveIndex], curves[curveIndex+1:]...)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// cipherSuiteScan returns, by TLS Version, the sort list of cipher suites
|
||||
// supported by the host
|
||||
func cipherSuiteScan(addr, hostname string) (grade Grade, output Output, err error) {
|
||||
var cvList cipherVersionList
|
||||
allCiphers := allCiphersIDs()
|
||||
|
||||
var vers uint16
|
||||
for vers = tls.VersionTLS12; vers >= tls.VersionSSL30; vers-- {
|
||||
ciphers := make([]uint16, len(allCiphers))
|
||||
copy(ciphers, allCiphers)
|
||||
for len(ciphers) > 0 {
|
||||
var cipherIndex int
|
||||
cipherIndex, _, _, err = sayHello(addr, hostname, ciphers, nil, vers, nil)
|
||||
if err != nil {
|
||||
if err == errHelloFailed {
|
||||
err = nil
|
||||
break
|
||||
}
|
||||
return
|
||||
}
|
||||
if vers == tls.VersionSSL30 {
|
||||
grade = Warning
|
||||
}
|
||||
cipherID := ciphers[cipherIndex]
|
||||
|
||||
// If this is an EC cipher suite, do a second scan for curve support
|
||||
var supportedCurves []tls.CurveID
|
||||
if tls.CipherSuites[cipherID].EllipticCurve {
|
||||
supportedCurves, err = doCurveScan(addr, hostname, vers, cipherID, ciphers)
|
||||
if len(supportedCurves) == 0 {
|
||||
err = errors.New("couldn't negotiate any curves")
|
||||
}
|
||||
}
|
||||
for i, c := range cvList {
|
||||
if cipherID == c.cipherID {
|
||||
cvList[i].data = append(c.data, cipherDatum{vers, supportedCurves})
|
||||
goto exists
|
||||
}
|
||||
}
|
||||
cvList = append(cvList, cipherVersions{cipherID, []cipherDatum{{vers, supportedCurves}}})
|
||||
exists:
|
||||
ciphers = append(ciphers[:cipherIndex], ciphers[cipherIndex+1:]...)
|
||||
}
|
||||
}
|
||||
|
||||
if len(cvList) == 0 {
|
||||
err = errors.New("couldn't negotiate any cipher suites")
|
||||
return
|
||||
}
|
||||
|
||||
if grade != Warning {
|
||||
grade = Good
|
||||
}
|
||||
|
||||
output = cvList
|
||||
return
|
||||
}
|
||||
|
||||
// sigAlgsScan returns the accepted signature and hash algorithms of the host
|
||||
func sigAlgsScan(addr, hostname string) (grade Grade, output Output, err error) {
|
||||
var supportedSigAlgs []tls.SignatureAndHash
|
||||
for _, sigAlg := range tls.AllSignatureAndHashAlgorithms {
|
||||
_, _, _, e := sayHello(addr, hostname, nil, nil, tls.VersionTLS12, []tls.SignatureAndHash{sigAlg})
|
||||
if e == nil {
|
||||
supportedSigAlgs = append(supportedSigAlgs, sigAlg)
|
||||
}
|
||||
}
|
||||
|
||||
if len(supportedSigAlgs) > 0 {
|
||||
grade = Good
|
||||
output = supportedSigAlgs
|
||||
} else {
|
||||
err = errors.New("no SigAlgs supported")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// certSigAlgScan returns the server certificate with various sigature and hash algorithms in the ClientHello
|
||||
func certSigAlgsScan(addr, hostname string) (grade Grade, output Output, err error) {
|
||||
var certSigAlgs = make(map[string]string)
|
||||
for _, sigAlg := range tls.AllSignatureAndHashAlgorithms {
|
||||
_, _, derCerts, e := sayHello(addr, hostname, nil, nil, tls.VersionTLS12, []tls.SignatureAndHash{sigAlg})
|
||||
if e == nil {
|
||||
if len(derCerts) == 0 {
|
||||
return Bad, nil, errors.New("no certs returned")
|
||||
}
|
||||
certs, _, err := helpers.ParseCertificatesDER(derCerts[0], "")
|
||||
if err != nil {
|
||||
return Bad, nil, err
|
||||
}
|
||||
|
||||
certSigAlgs[sigAlg.String()] = helpers.SignatureString(certs[0].SignatureAlgorithm)
|
||||
//certSigAlgs = append(certSigAlgs, certs[0].SignatureAlgorithm)
|
||||
}
|
||||
}
|
||||
|
||||
if len(certSigAlgs) > 0 {
|
||||
grade = Good
|
||||
output = certSigAlgs
|
||||
} else {
|
||||
err = errors.New("no SigAlgs supported")
|
||||
}
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
// certSigAlgScan returns the server certificate with various ciphers in the ClientHello
|
||||
func certSigAlgsScanByCipher(addr, hostname string) (grade Grade, output Output, err error) {
|
||||
var certSigAlgs = make(map[string]string)
|
||||
for cipherID := range tls.CipherSuites {
|
||||
_, _, derCerts, e := sayHello(addr, hostname, []uint16{cipherID}, nil, tls.VersionTLS12, []tls.SignatureAndHash{})
|
||||
if e == nil {
|
||||
if len(derCerts) == 0 {
|
||||
return Bad, nil, errors.New("no certs returned")
|
||||
}
|
||||
certs, _, err := helpers.ParseCertificatesDER(derCerts[0], "")
|
||||
if err != nil {
|
||||
return Bad, nil, err
|
||||
}
|
||||
|
||||
certSigAlgs[tls.CipherSuites[cipherID].Name] = helpers.SignatureString(certs[0].SignatureAlgorithm)
|
||||
//certSigAlgs = append(certSigAlgs, certs[0].SignatureAlgorithm)
|
||||
}
|
||||
}
|
||||
|
||||
if len(certSigAlgs) > 0 {
|
||||
grade = Good
|
||||
output = certSigAlgs
|
||||
} else {
|
||||
err = errors.New("no cipher supported")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ecCurveScan returns the elliptic curves supported by the host.
|
||||
func ecCurveScan(addr, hostname string) (grade Grade, output Output, err error) {
|
||||
allCurves := allCurvesIDs()
|
||||
curves := make([]tls.CurveID, len(allCurves))
|
||||
copy(curves, allCurves)
|
||||
var supportedCurves []string
|
||||
for len(curves) > 0 {
|
||||
var curveIndex int
|
||||
_, curveIndex, _, err = sayHello(addr, hostname, allECDHECiphersIDs(), curves, tls.VersionTLS12, nil)
|
||||
if err != nil {
|
||||
// This case is expected, because eventually we ask only for curves the server doesn't support
|
||||
if err == errHelloFailed {
|
||||
err = nil
|
||||
break
|
||||
}
|
||||
return
|
||||
}
|
||||
curveID := curves[curveIndex]
|
||||
supportedCurves = append(supportedCurves, tls.Curves[curveID])
|
||||
curves = append(curves[:curveIndex], curves[curveIndex+1:]...)
|
||||
}
|
||||
output = supportedCurves
|
||||
grade = Good
|
||||
return
|
||||
}
|
Reference in New Issue
Block a user