1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package certloader
18
19 import (
20 "bytes"
21 "crypto"
22 "crypto/ecdsa"
23 "crypto/rsa"
24 "crypto/tls"
25 "crypto/x509"
26 "encoding/pem"
27 "errors"
28 "fmt"
29 "io/ioutil"
30
31 "golang.org/x/crypto/openpgp"
32 "golang.org/x/crypto/openpgp/packet"
33
34 "github.com/sassoftware/relic/lib/pkcs7"
35 "github.com/sassoftware/relic/lib/pkcs9"
36 "github.com/sassoftware/relic/lib/x509tools"
37 )
38
39 const asn1Magic = 0x30
40 var pkcs7SignedData = []byte{0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02}
41
42
43 type Certificate struct {
44 Leaf *x509.Certificate
45 Certificates []*x509.Certificate
46 PgpKey *openpgp.Entity
47 PrivateKey crypto.PrivateKey
48 Timestamper pkcs9.Timestamper
49 KeyName string
50 }
51
52
53 func (s *Certificate) Chain() []*x509.Certificate {
54 var chain []*x509.Certificate
55 if s.Leaf != nil {
56
57 chain = append(chain, s.Leaf)
58 }
59 for i, cert := range s.Certificates {
60 if i > 0 && bytes.Equal(cert.RawIssuer, cert.RawSubject) {
61
62 continue
63 } else if cert == s.Leaf {
64
65 continue
66 }
67 chain = append(chain, cert)
68 }
69 return chain
70 }
71
72
73 func (s *Certificate) Issuer() *x509.Certificate {
74 if s.Leaf == nil {
75 return nil
76 }
77 for _, cert := range s.Certificates {
78 if bytes.Equal(cert.RawSubject, s.Leaf.RawIssuer) {
79 return cert
80 }
81 }
82 return nil
83 }
84
85
86 func (s *Certificate) Signer() crypto.Signer {
87 if s.PrivateKey == nil {
88 return nil
89 }
90 return s.PrivateKey.(crypto.Signer)
91 }
92
93
94
95 func (s *Certificate) TLS() tls.Certificate {
96 var raw [][]byte
97 for _, cert := range s.Certificates {
98 raw = append(raw, cert.Raw)
99 }
100 return tls.Certificate{Leaf: s.Leaf, Certificate: raw, PrivateKey: s.PrivateKey}
101 }
102
103
104
105 func parsePrivateKey(der []byte) (crypto.PrivateKey, error) {
106 if key, err := x509.ParsePKCS1PrivateKey(der); err == nil {
107 return key, nil
108 }
109 if key, err := x509.ParsePKCS8PrivateKey(der); err == nil {
110 switch key := key.(type) {
111 case *rsa.PrivateKey, *ecdsa.PrivateKey:
112 return key, nil
113 default:
114 return nil, errors.New("tls: found unknown private key type in PKCS#8 wrapping")
115 }
116 }
117 if key, err := x509.ParseECPrivateKey(der); err == nil {
118 return key, nil
119 }
120
121 return nil, errors.New("tls: failed to parse private key")
122 }
123
124
125 func parseCertificates(pemData []byte) (*Certificate, error) {
126 if len(pemData) >= 1 && pemData[0] == asn1Magic {
127
128 return parseCertificatesDer(pemData)
129 }
130 var certs []*x509.Certificate
131 for {
132 var block *pem.Block
133 block, pemData = pem.Decode(pemData)
134 if block == nil {
135 break
136 } else if block.Type == "CERTIFICATE" || block.Type == "PKCS7" {
137 newcerts, err := parseCertificatesDer(block.Bytes)
138 if err != nil {
139 return nil, err
140 }
141 certs = append(certs, newcerts.Certificates...)
142 }
143 }
144 if len(certs) == 0 {
145 return nil, ErrNoCerts
146 }
147 return &Certificate{Leaf: certs[0], Certificates: certs}, nil
148 }
149
150
151 func parseCertificatesDer(der []byte) (*Certificate, error) {
152 var certs []*x509.Certificate
153 var err error
154 if bytes.Contains(der[:32], pkcs7SignedData) {
155 psd, err := pkcs7.Unmarshal(der)
156 if err != nil {
157 return nil, err
158 }
159 certs, err = psd.Content.Certificates.Parse()
160 } else {
161 certs, err = x509.ParseCertificates(der)
162 }
163 if err != nil {
164 return nil, err
165 } else if len(certs) == 0 {
166 return nil, ErrNoCerts
167 } else {
168 return &Certificate{Leaf: certs[0], Certificates: certs}, nil
169 }
170 }
171
172
173 func ParseX509Certificates(blob []byte) ([]*x509.Certificate, error) {
174 cert, err := parseCertificates(blob)
175 if err != nil {
176 return nil, err
177 }
178 return cert.Certificates, nil
179 }
180
181
182 func LoadX509KeyPair(certFile, keyFile string) (*Certificate, error) {
183 keyblob, err := ioutil.ReadFile(keyFile)
184 if err != nil {
185 return nil, err
186 }
187 certblob, err := ioutil.ReadFile(certFile)
188 if err != nil {
189 return nil, err
190 }
191 key, err := ParseAnyPrivateKey(keyblob, nil)
192 if err != nil {
193 return nil, err
194 }
195 cert, err := parseCertificates(certblob)
196 if err != nil {
197 return nil, err
198 }
199 if !x509tools.SameKey(cert.Leaf.PublicKey, key) {
200 return nil, errors.New("Private key does not match certificate")
201 }
202 cert.PrivateKey = key
203 return cert, nil
204 }
205
206
207
208 func LoadTokenCertificates(key crypto.PrivateKey, x509cert, pgpcert string) (*Certificate, error) {
209 var cert *Certificate
210 if x509cert != "" {
211 blob, err := ioutil.ReadFile(x509cert)
212 if err != nil {
213 return nil, err
214 }
215 cert, err = parseCertificates(blob)
216 if err != nil {
217 return nil, err
218 }
219 if !x509tools.SameKey(key, cert.Leaf.PublicKey) {
220 return nil, errors.New("certificate does not match key in token")
221 }
222 cert.PrivateKey = key
223 } else {
224 cert = &Certificate{PrivateKey: key}
225 }
226 if pgpcert != "" {
227 blob, err := ioutil.ReadFile(pgpcert)
228 if err != nil {
229 return nil, err
230 }
231 keyring, err := parsePGP(blob)
232 if err != nil {
233 return nil, err
234 }
235 if len(keyring) != 1 {
236 return nil, fmt.Errorf("expected exactly 1 entity in pgp certificate %s", pgpcert)
237 }
238 entity := keyring[0]
239 priv := &packet.PrivateKey{
240 PublicKey: *entity.PrimaryKey,
241 Encrypted: false,
242 PrivateKey: key,
243 }
244 if !x509tools.SameKey(key, priv.PublicKey.PublicKey) {
245 return nil, errors.New("certificate does not match key in token")
246 }
247 entity.PrivateKey = priv
248 cert.PgpKey = entity
249 }
250 return cert, nil
251 }
252
253 type errNoCerts struct{}
254
255 func (errNoCerts) Error() string {
256 return "failed to find any certificates in PEM file"
257 }
258
259 var ErrNoCerts = errNoCerts{}
260
View as plain text