-
Notifications
You must be signed in to change notification settings - Fork 53
/
tls.go
57 lines (53 loc) · 1.38 KB
/
tls.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package pkp
import (
"crypto/tls"
"errors"
"fmt"
)
var (
ErrNoPins = errors.New("no pins provided")
ErrCertValidationFailed = errors.New("peer certificate validation failed")
)
func TLSConfig(pins []*PublicKeyPin) (*tls.Config, error) {
if len(pins) == 0 {
return nil, ErrNoPins
}
copiedPins := make([]*PublicKeyPin, len(pins))
for i, pin := range pins {
if err := pin.Validate(); err != nil {
return nil, err
}
copiedPins[i] = pin.DeepCopy()
}
/* #nosec G402 -- InsecureSkipVerify allowed in conjunction with VerifyConnection */
return &tls.Config{
MinVersion: tls.VersionTLS13,
InsecureSkipVerify: true,
VerifyConnection: func(cs tls.ConnectionState) error {
peerCerts := cs.PeerCertificates
// Validate the peer's certificate chain.
for i := 0; i < len(peerCerts)-1; i++ {
if err := peerCerts[i].CheckSignatureFrom(peerCerts[i+1]); err != nil {
return fmt.Errorf("%w: %s", ErrCertValidationFailed, err)
}
}
// Check each peer certificate for a matching pin.
pinnedCert := -1
CERTS:
for i, peerCert := range peerCerts {
for _, pin := range copiedPins {
peerCertPin, _ := New(peerCert, pin.Algorithm)
if pin.Equal(peerCertPin) {
// Found a match
pinnedCert = i
break CERTS
}
}
}
if pinnedCert == -1 {
return ErrCertValidationFailed
}
return nil
},
}, nil
}