go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/network/resources/certificates/cert.go (about)

     1  // Copyright (c) Mondoo, Inc.
     2  // SPDX-License-Identifier: BUSL-1.1
     3  
     4  package certificates
     5  
     6  import (
     7  	"crypto/md5"
     8  	"crypto/sha1"
     9  	"crypto/sha256"
    10  	"crypto/tls"
    11  	"crypto/x509"
    12  	"encoding/hex"
    13  	"fmt"
    14  	"net"
    15  	"time"
    16  )
    17  
    18  var cipherSuites = map[string]uint16{
    19  	// TLS 1.0 - 1.2 cipher suites.
    20  	"TLS_RSA_WITH_RC4_128_SHA":                      tls.TLS_RSA_WITH_RC4_128_SHA,
    21  	"TLS_RSA_WITH_3DES_EDE_CBC_SHA":                 tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
    22  	"TLS_RSA_WITH_AES_128_CBC_SHA":                  tls.TLS_RSA_WITH_AES_128_CBC_SHA,
    23  	"TLS_RSA_WITH_AES_256_CBC_SHA":                  tls.TLS_RSA_WITH_AES_256_CBC_SHA,
    24  	"TLS_RSA_WITH_AES_128_CBC_SHA256":               tls.TLS_RSA_WITH_AES_128_CBC_SHA256,
    25  	"TLS_RSA_WITH_AES_128_GCM_SHA256":               tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
    26  	"TLS_RSA_WITH_AES_256_GCM_SHA384":               tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
    27  	"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA":              tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
    28  	"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA":          tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
    29  	"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA":          tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
    30  	"TLS_ECDHE_RSA_WITH_RC4_128_SHA":                tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
    31  	"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA":           tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
    32  	"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA":            tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
    33  	"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA":            tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
    34  	"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256":       tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
    35  	"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256":         tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
    36  	"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256":         tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
    37  	"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256":       tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
    38  	"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384":         tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
    39  	"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384":       tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
    40  	"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256":   tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
    41  	"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256": tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
    42  
    43  	// TLS 1.3 cipher suites.
    44  	"TLS_AES_128_GCM_SHA256": tls.TLS_AES_128_GCM_SHA256,
    45  	"TLS_AES_256_GCM_SHA384": tls.TLS_AES_256_GCM_SHA384,
    46  }
    47  
    48  var userTempl string
    49  
    50  var TimeoutSeconds = 3
    51  
    52  func cipherSuite(suite string) ([]uint16, error) {
    53  	if suite == "" {
    54  		return nil, nil
    55  	}
    56  
    57  	var cs []uint16
    58  	cs = []uint16{cipherSuites[suite]}
    59  	if cs[0] == 0 {
    60  		return nil, fmt.Errorf("%s is unsupported cipher suite or tls1.3 cipher suite.", suite)
    61  	}
    62  	return cs, nil
    63  }
    64  
    65  func tlsVersion(suite string) uint16 {
    66  	if suite != "" {
    67  		return tls.VersionTLS12
    68  	}
    69  	// Currently TLS 1.3
    70  	return 0
    71  }
    72  
    73  var gatherPeerCertificates = func(host, port string, ciphersuite string, insecureskipverify bool) ([]*x509.Certificate, error) {
    74  	d := &net.Dialer{
    75  		Timeout: time.Duration(TimeoutSeconds) * time.Second,
    76  	}
    77  
    78  	cs, err := cipherSuite(ciphersuite)
    79  	if err != nil {
    80  		return nil, err
    81  	}
    82  
    83  	conn, err := tls.DialWithDialer(d, "tcp", host+":"+port, &tls.Config{
    84  		InsecureSkipVerify: insecureskipverify,
    85  		CipherSuites:       cs,
    86  		MaxVersion:         tlsVersion(ciphersuite),
    87  	})
    88  	if err != nil {
    89  		return nil, err
    90  	}
    91  	defer conn.Close()
    92  
    93  	// addr := conn.RemoteAddr()
    94  	// ip, _, _ := net.SplitHostPort(addr.String())
    95  	cert := conn.ConnectionState().PeerCertificates
    96  
    97  	return cert, nil
    98  }
    99  
   100  func Fetch(hostport string) ([]*x509.Certificate, error) {
   101  	host, port, err := net.SplitHostPort(hostport)
   102  	if err != nil {
   103  		return nil, err
   104  	}
   105  
   106  	return gatherPeerCertificates(host, port, "", true)
   107  }
   108  
   109  func HexEncodeToHumanString(b []byte) string {
   110  	if len(b) == 0 {
   111  		return ""
   112  	}
   113  	buf := make([]byte, 0, 3*len(b))
   114  	x := buf[1*len(b) : 3*len(b)]
   115  	hex.Encode(x, b)
   116  	for i := 0; i < len(x); i += 2 {
   117  		buf = append(buf, x[i], x[i+1], ':')
   118  	}
   119  	return string(buf[:len(buf)-1])
   120  }
   121  
   122  func Sha1Hash(cert *x509.Certificate) []byte {
   123  	h := sha1.New()
   124  	if cert != nil {
   125  		h.Write(cert.Raw)
   126  	}
   127  	return h.Sum(nil)
   128  }
   129  
   130  func Sha256Hash(cert *x509.Certificate) []byte {
   131  	h := sha256.New()
   132  	if cert != nil {
   133  		h.Write(cert.Raw)
   134  	}
   135  	return h.Sum(nil)
   136  }
   137  
   138  func Md5Hash(cert *x509.Certificate) []byte {
   139  	h := md5.New()
   140  	if cert != nil {
   141  		h.Write(cert.Raw)
   142  	}
   143  	return h.Sum(nil)
   144  }
   145  
   146  func Fingerprints(cert *x509.Certificate) map[string]interface{} {
   147  	return map[string]interface{}{
   148  		"sha1":   hex.EncodeToString(Sha1Hash(cert)),
   149  		"sha256": hex.EncodeToString(Sha256Hash(cert)),
   150  		"md5":    hex.EncodeToString(Md5Hash(cert)),
   151  	}
   152  }