1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package crypto11
23
24 import (
25 "crypto/tls"
26 "crypto/x509"
27 "encoding/asn1"
28 "math/big"
29
30 "github.com/miekg/pkcs11"
31 "github.com/pkg/errors"
32 )
33
34
35
36 func findCertificate(session *pkcs11Session, id []byte, label []byte, serial *big.Int) (cert *x509.Certificate, err error) {
37
38 rawCertificate, err := findRawCertificate(session, id, label, serial)
39 if err != nil {
40 return nil, err
41 }
42
43 if rawCertificate != nil {
44 cert, err = x509.ParseCertificate(rawCertificate)
45 if err != nil {
46 return nil, err
47 }
48 }
49
50 return cert, err
51 }
52
53 func findRawCertificate(session *pkcs11Session, id []byte, label []byte, serial *big.Int) (rawCertificate []byte, err error) {
54 if id == nil && label == nil && serial == nil {
55 return nil, errors.New("id, label and serial cannot all be nil")
56 }
57
58 var template []*pkcs11.Attribute
59
60 if id != nil {
61 template = append(template, pkcs11.NewAttribute(pkcs11.CKA_ID, id))
62 }
63 if label != nil {
64 template = append(template, pkcs11.NewAttribute(pkcs11.CKA_LABEL, label))
65 }
66 if serial != nil {
67 derSerial, err := asn1.Marshal(serial)
68 if err != nil {
69 return nil, errors.WithMessage(err, "failed to encode serial")
70 }
71
72 template = append(template, pkcs11.NewAttribute(pkcs11.CKA_SERIAL_NUMBER, derSerial))
73 }
74
75 template = append(template, pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_CERTIFICATE))
76
77 if err = session.ctx.FindObjectsInit(session.handle, template); err != nil {
78 return nil, err
79 }
80 defer func() {
81 finalErr := session.ctx.FindObjectsFinal(session.handle)
82 if err == nil {
83 err = finalErr
84 }
85 }()
86
87 handles, _, err := session.ctx.FindObjects(session.handle, 1)
88 if err != nil {
89 return nil, err
90 }
91 if len(handles) == 0 {
92 return nil, nil
93 }
94
95 attributes := []*pkcs11.Attribute{
96 pkcs11.NewAttribute(pkcs11.CKA_VALUE, 0),
97 }
98
99 if attributes, err = session.ctx.GetAttributeValue(session.handle, handles[0], attributes); err != nil {
100 return nil, err
101 }
102
103 rawCertificate = attributes[0].Value
104
105 return
106 }
107
108
109
110 func (c *Context) FindCertificate(id []byte, label []byte, serial *big.Int) (*x509.Certificate, error) {
111
112 if c.closed.Get() {
113 return nil, errClosed
114 }
115
116 var cert *x509.Certificate
117 err := c.withSession(func(session *pkcs11Session) (err error) {
118 cert, err = findCertificate(session, id, label, serial)
119 return err
120 })
121
122 return cert, err
123 }
124
125 func (c *Context) FindAllPairedCertificates() (certificates []tls.Certificate, err error) {
126 if c.closed.Get() {
127 return nil, errClosed
128 }
129
130 err = c.withSession(func(session *pkcs11Session) error {
131
132 privAttributes := AttributeSet{}
133 err = privAttributes.Set(CkaClass, pkcs11.CKO_PRIVATE_KEY)
134 if err != nil {
135 return err
136 }
137
138 privHandles, err := findKeysWithAttributes(session, privAttributes.ToSlice())
139 if err != nil {
140 return err
141 }
142
143 for _, privHandle := range privHandles {
144
145 privateKey, certificate, err := c.makeKeyPair(session, &privHandle)
146
147 if err == errNoCkaId || err == errNoPublicHalf {
148 continue
149 }
150
151 if err != nil {
152 return err
153 }
154
155 if certificate == nil {
156 continue
157 }
158
159 tlsCert := tls.Certificate{
160 Leaf: certificate,
161 PrivateKey: privateKey,
162 }
163
164 tlsCert.Certificate = append(tlsCert.Certificate, certificate.Raw)
165 certificates = append(certificates, tlsCert)
166 }
167
168 return nil
169 })
170
171 if err != nil {
172 return nil, err
173 }
174
175 return
176 }
177
178
179
180 func (c *Context) ImportCertificate(id []byte, certificate *x509.Certificate) error {
181 if c.closed.Get() {
182 return errClosed
183 }
184
185 if err := notNilBytes(id, "id"); err != nil {
186 return err
187 }
188
189 template, err := NewAttributeSetWithID(id)
190 if err != nil {
191 return err
192 }
193 return c.ImportCertificateWithAttributes(template, certificate)
194 }
195
196
197
198 func (c *Context) ImportCertificateWithLabel(id []byte, label []byte, certificate *x509.Certificate) error {
199 if c.closed.Get() {
200 return errClosed
201 }
202
203 if err := notNilBytes(id, "id"); err != nil {
204 return err
205 }
206 if err := notNilBytes(label, "label"); err != nil {
207 return err
208 }
209
210 template, err := NewAttributeSetWithIDAndLabel(id, label)
211 if err != nil {
212 return err
213 }
214 return c.ImportCertificateWithAttributes(template, certificate)
215 }
216
217
218
219
220 func (c *Context) ImportCertificateWithAttributes(template AttributeSet, certificate *x509.Certificate) error {
221 if c.closed.Get() {
222 return errClosed
223 }
224
225 if certificate == nil {
226 return errors.New("certificate cannot be nil")
227 }
228
229 serial, err := asn1.Marshal(certificate.SerialNumber)
230 if err != nil {
231 return err
232 }
233
234 template.AddIfNotPresent([]*pkcs11.Attribute{
235 pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_CERTIFICATE),
236 pkcs11.NewAttribute(pkcs11.CKA_CERTIFICATE_TYPE, pkcs11.CKC_X_509),
237 pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
238 pkcs11.NewAttribute(pkcs11.CKA_PRIVATE, false),
239 pkcs11.NewAttribute(pkcs11.CKA_SUBJECT, certificate.RawSubject),
240 pkcs11.NewAttribute(pkcs11.CKA_ISSUER, certificate.RawIssuer),
241 pkcs11.NewAttribute(pkcs11.CKA_SERIAL_NUMBER, serial),
242 pkcs11.NewAttribute(pkcs11.CKA_VALUE, certificate.Raw),
243 })
244
245 err = c.withSession(func(session *pkcs11Session) error {
246 _, err = session.ctx.CreateObject(session.handle, template.ToSlice())
247 return err
248 })
249
250 return err
251 }
252
253
254
255
256 func (c *Context) DeleteCertificate(id []byte, label []byte, serial *big.Int) error {
257 if id == nil && label == nil && serial == nil {
258 return errors.New("id, label and serial cannot all be nil")
259 }
260
261 template := []*pkcs11.Attribute{
262 pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_CERTIFICATE),
263 }
264
265 if id != nil {
266 template = append(template, pkcs11.NewAttribute(pkcs11.CKA_ID, id))
267 }
268 if label != nil {
269 template = append(template, pkcs11.NewAttribute(pkcs11.CKA_LABEL, label))
270 }
271 if serial != nil {
272 asn1Serial, err := asn1.Marshal(serial)
273 if err != nil {
274 return err
275 }
276 template = append(template, pkcs11.NewAttribute(pkcs11.CKA_SERIAL_NUMBER, asn1Serial))
277 }
278
279 err := c.withSession(func(session *pkcs11Session) error {
280 err := session.ctx.FindObjectsInit(session.handle, template)
281 if err != nil {
282 return err
283 }
284 handles, _, err := session.ctx.FindObjects(session.handle, 1)
285 finalErr := session.ctx.FindObjectsFinal(session.handle)
286 if err != nil {
287 return err
288 }
289 if finalErr != nil {
290 return finalErr
291 }
292 if len(handles) == 0 {
293 return nil
294 }
295 return session.ctx.DestroyObject(session.handle, handles[0])
296 })
297
298 return err
299 }
300
View as plain text