-
Notifications
You must be signed in to change notification settings - Fork 73
/
tls_verify.go
61 lines (52 loc) · 1.77 KB
/
tls_verify.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
58
59
60
61
package spiffe
import (
"crypto/x509"
"errors"
"fmt"
"github.com/spiffe/go-spiffe/internal"
)
// VerifyPeerCertificate verifies the provided peer certificate chain using the
// set trust domain roots. The expectPeerFn callback is used to check the peer
// ID after the chain of trust has been verified to assert that the chain
// belongs to the intended peer.
func VerifyPeerCertificate(peerChain []*x509.Certificate, trustDomainRoots map[string]*x509.CertPool, expectPeerFn ExpectPeerFunc) ([][]*x509.Certificate, error) {
switch {
case len(peerChain) == 0:
return nil, errors.New("no peer certificates")
case len(trustDomainRoots) == 0:
return nil, errors.New("at least one trust domain root is required")
case expectPeerFn == nil:
return nil, errors.New("expectPeerFn callback is required")
}
peer := peerChain[0]
peerID, trustDomainID, err := getIDsFromCertificate(peer)
if err != nil {
return nil, err
}
if peer.IsCA {
return nil, errors.New("cannot validate peer which is a CA")
}
if peer.KeyUsage&x509.KeyUsageCertSign > 0 {
return nil, errors.New("cannot validate peer with KeyCertSign key usage")
}
if peer.KeyUsage&x509.KeyUsageCRLSign > 0 {
return nil, errors.New("cannot validate peer with KeyCrlSign key usage")
}
roots, ok := trustDomainRoots[trustDomainID]
if !ok {
return nil, fmt.Errorf("no roots for peer trust domain %q", trustDomainID)
}
verifiedChains, err := peer.Verify(x509.VerifyOptions{
Roots: roots,
Intermediates: internal.CertPoolFromCerts(peerChain[1:]),
// TODO: assert client or server depending on role?
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny},
})
if err != nil {
return nil, err
}
if err := expectPeerFn(peerID, verifiedChains); err != nil {
return nil, err
}
return verifiedChains, nil
}