/
signing_material.go
137 lines (114 loc) · 3.19 KB
/
signing_material.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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package pki
import (
"crypto"
"crypto/x509"
"encoding/asn1"
"fmt"
"github.com/anchore/quill/quill/pki/apple"
"github.com/anchore/quill/quill/pki/certchain"
"github.com/anchore/quill/quill/pki/load"
)
type SigningMaterial struct {
Signer crypto.Signer
Certs []*x509.Certificate
TimestampServer string
}
func NewSigningMaterialFromPEMs(certFile, privateKeyPath, password string, failWithoutFullChain bool) (*SigningMaterial, error) {
var certs []*x509.Certificate
var privateKey crypto.PrivateKey
var err error
switch {
case certFile != "" && privateKeyPath != "":
certs, err = load.Certificates(certFile)
if err != nil {
return nil, err
}
if len(certs) > 0 {
if err := certchain.VerifyForCodeSigning(certs, failWithoutFullChain); err != nil {
return nil, err
}
}
privateKey, err = load.PrivateKey(privateKeyPath, password)
if err != nil {
return nil, err
}
default:
return nil, nil
}
signer, ok := privateKey.(crypto.Signer)
if !ok {
return nil, fmt.Errorf("unable to derive signer from private key")
}
return &SigningMaterial{
Signer: signer,
Certs: certchain.Sort(certs),
}, nil
}
func NewSigningMaterialFromP12(p12Content load.P12Contents, failWithoutFullChain bool) (*SigningMaterial, error) {
if p12Content.PrivateKey == nil {
return nil, fmt.Errorf("no private key found in the p12")
}
if p12Content.Certificate == nil {
return nil, fmt.Errorf("no signing certificate found in the p12")
}
allCerts := append([]*x509.Certificate{p12Content.Certificate}, p12Content.Certificates...)
signer, ok := p12Content.PrivateKey.(crypto.Signer)
if !ok {
return nil, fmt.Errorf("unable to derive signer from private key")
}
if len(allCerts) > 0 {
if err := certchain.VerifyForCodeSigning(allCerts, failWithoutFullChain); err != nil {
store := certchain.NewCollection().WithStores(apple.GetEmbeddedCertStore())
// verification failed, try again but attempt to find more certs from the embedded certs in quill
remainingCerts, err := certchain.Find(store, p12Content.Certificate)
if err != nil {
return nil, fmt.Errorf("unable to find remaining chain certificates: %w", err)
}
allCerts = append(allCerts, remainingCerts...)
if err := certchain.VerifyForCodeSigning(allCerts, failWithoutFullChain); err != nil {
return nil, err
}
}
}
return &SigningMaterial{
Signer: signer,
Certs: certchain.Sort(allCerts),
}, nil
}
func (sm *SigningMaterial) HasCertWithOrg(org string) bool {
for _, cert := range sm.Certs {
if len(cert.Subject.Organization) == 0 {
continue
}
if cert.Subject.Organization[0] == org {
return true
}
}
return false
}
func (sm *SigningMaterial) CertWithExtension(oid asn1.ObjectIdentifier) (int, *x509.Certificate) {
for i, cert := range sm.Certs {
for _, ext := range cert.Extensions {
if ext.Id.Equal(oid) {
return i, cert
}
}
}
return -1, nil
}
func (sm *SigningMaterial) Root() *x509.Certificate {
if len(sm.Certs) > 0 && sm.Certs[0].IsCA {
return sm.Certs[0]
}
return nil
}
func (sm *SigningMaterial) Leaf() *x509.Certificate {
if len(sm.Certs) == 0 {
return nil
}
leaf := sm.Certs[len(sm.Certs)-1]
if leaf.IsCA {
return nil
}
return leaf
}