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"
26 "crypto/x509"
27 "github.com/miekg/pkcs11"
28 "github.com/pkg/errors"
29 )
30
31 const maxHandlePerFind = 20
32
33
34 var errNoCkaId = errors.New("private key has no CKA_ID")
35
36
37 var errNoPublicHalf = errors.New("could not find public key to match private key")
38
39 func findKeysWithAttributes(session *pkcs11Session, template []*pkcs11.Attribute) (handles []pkcs11.ObjectHandle, err error) {
40 if err = session.ctx.FindObjectsInit(session.handle, template); err != nil {
41 return nil, err
42 }
43 defer func() {
44 finalErr := session.ctx.FindObjectsFinal(session.handle)
45 if err == nil {
46 err = finalErr
47 }
48 }()
49
50 newhandles, _, err := session.ctx.FindObjects(session.handle, maxHandlePerFind)
51 if err != nil {
52 return nil, err
53 }
54
55 for len(newhandles) > 0 {
56 handles = append(handles, newhandles...)
57
58 newhandles, _, err = session.ctx.FindObjects(session.handle, maxHandlePerFind)
59 if err != nil {
60 return nil, err
61 }
62 }
63
64 return handles, nil
65 }
66
67
68
69 func findKeys(session *pkcs11Session, id []byte, label []byte, keyclass *uint, keytype *uint) (handles []pkcs11.ObjectHandle, err error) {
70 var template []*pkcs11.Attribute
71
72 if keyclass != nil {
73 template = append(template, pkcs11.NewAttribute(pkcs11.CKA_CLASS, *keyclass))
74 }
75 if keytype != nil {
76 template = append(template, pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, *keytype))
77 }
78 if id != nil {
79 template = append(template, pkcs11.NewAttribute(pkcs11.CKA_ID, id))
80 }
81 if label != nil {
82 template = append(template, pkcs11.NewAttribute(pkcs11.CKA_LABEL, label))
83 }
84
85 if handles, err = findKeysWithAttributes(session, template); err != nil {
86 return nil, err
87 }
88
89 return handles, nil
90 }
91
92
93
94 func findKey(session *pkcs11Session, id []byte, label []byte, keyclass *uint, keytype *uint) (obj *pkcs11.ObjectHandle, err error) {
95 handles, err := findKeys(session, id, label, keyclass, keytype)
96 if err != nil {
97 return nil, err
98 }
99
100 if len(handles) == 0 {
101 return nil, nil
102 }
103 return &handles[0], nil
104 }
105
106
107
108 func (c *Context) makeKeyPair(session *pkcs11Session, privHandle *pkcs11.ObjectHandle) (signer Signer, certificate *x509.Certificate, err error) {
109 attributes := []*pkcs11.Attribute{
110 pkcs11.NewAttribute(pkcs11.CKA_ID, nil),
111 pkcs11.NewAttribute(pkcs11.CKA_LABEL, nil),
112 pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, 0),
113 }
114 if attributes, err = session.ctx.GetAttributeValue(session.handle, *privHandle, attributes); err != nil {
115 return nil, nil, err
116 }
117 id := attributes[0].Value
118 label := attributes[1].Value
119 keyType := bytesToUlong(attributes[2].Value)
120
121
122 if id == nil || len(id) == 0 {
123 return nil, nil, errNoCkaId
124 }
125
126 var pubHandle *pkcs11.ObjectHandle
127
128
129 pubHandle, err = findKey(session, id, label, uintPtr(pkcs11.CKO_PUBLIC_KEY), &keyType)
130 if err != nil {
131 p11Err, ok := err.(pkcs11.Error)
132
133 if len(label) == 0 && ok && p11Err == pkcs11.CKR_TEMPLATE_INCONSISTENT {
134
135
136
137
138 pubHandles, err := findKeys(session, id, nil, uintPtr(pkcs11.CKO_PUBLIC_KEY), &keyType)
139 if err != nil {
140 return nil, nil, err
141 }
142
143 for _, handle := range pubHandles {
144 template := []*pkcs11.Attribute{pkcs11.NewAttribute(pkcs11.CKA_LABEL, nil)}
145 template, err = session.ctx.GetAttributeValue(session.handle, handle, template)
146 if err != nil {
147 return nil, nil, err
148 }
149 if len(template[0].Value) == 0 {
150 pubHandle = &handle
151 break
152 }
153 }
154 } else {
155 return nil, nil, err
156 }
157 }
158
159 if pubHandle == nil {
160
161 pubHandle, err = findKey(session, id, nil, uintPtr(pkcs11.CKO_PUBLIC_KEY), &keyType)
162 }
163
164 resultPkcs11PrivateKey := pkcs11PrivateKey{
165 pkcs11Object: pkcs11Object{
166 handle: *privHandle,
167 context: c,
168 },
169 }
170
171 var pub crypto.PublicKey
172 certificate, _ = findCertificate(session, id, nil, nil)
173 if certificate != nil && pubHandle == nil {
174 pub = certificate.PublicKey
175 }
176
177 if pub == nil && pubHandle == nil {
178
179 return nil, nil, errNoPublicHalf
180 }
181
182 switch keyType {
183 case pkcs11.CKK_DSA:
184 result := &pkcs11PrivateKeyDSA{pkcs11PrivateKey: resultPkcs11PrivateKey}
185 if pubHandle != nil {
186 if pub, err = exportDSAPublicKey(session, *pubHandle); err != nil {
187 return nil, nil, err
188 }
189 result.pkcs11PrivateKey.pubKeyHandle = *pubHandle
190 }
191
192 result.pkcs11PrivateKey.pubKey = pub
193 return result, certificate, nil
194
195 case pkcs11.CKK_RSA:
196 result := &pkcs11PrivateKeyRSA{pkcs11PrivateKey: resultPkcs11PrivateKey}
197 if pubHandle != nil {
198 if pub, err = exportRSAPublicKey(session, *pubHandle); err != nil {
199 return nil, nil, err
200 }
201 result.pkcs11PrivateKey.pubKeyHandle = *pubHandle
202 }
203
204 result.pkcs11PrivateKey.pubKey = pub
205 return result, certificate, nil
206
207 case pkcs11.CKK_ECDSA:
208 result := &pkcs11PrivateKeyECDSA{pkcs11PrivateKey: resultPkcs11PrivateKey}
209 if pubHandle != nil {
210 if pub, err = exportECDSAPublicKey(session, *pubHandle); err != nil {
211 return nil, nil, err
212 }
213 result.pkcs11PrivateKey.pubKeyHandle = *pubHandle
214 }
215
216 result.pkcs11PrivateKey.pubKey = pub
217 return result, certificate, nil
218
219 default:
220 return nil, nil, errors.Errorf("unsupported key type: %X", keyType)
221 }
222 }
223
224
225
226
227
228
229
230 func (c *Context) FindKeyPair(id []byte, label []byte) (Signer, error) {
231 if c.closed.Get() {
232 return nil, errClosed
233 }
234
235 result, err := c.FindKeyPairs(id, label)
236 if err != nil {
237 return nil, err
238 }
239
240 if len(result) == 0 {
241 return nil, nil
242 }
243
244 return result[0], nil
245 }
246
247
248
249
250
251
252
253 func (c *Context) FindKeyPairs(id []byte, label []byte) (signer []Signer, err error) {
254 if c.closed.Get() {
255 return nil, errClosed
256 }
257
258 if id == nil && label == nil {
259 return nil, errors.New("id and label cannot both be nil")
260 }
261
262 attributes := NewAttributeSet()
263
264 if id != nil {
265 err = attributes.Set(CkaId, id)
266 if err != nil {
267 return nil, err
268 }
269 }
270 if label != nil {
271 err = attributes.Set(CkaLabel, label)
272 if err != nil {
273 return nil, err
274 }
275 }
276
277 return c.FindKeyPairsWithAttributes(attributes)
278 }
279
280
281
282
283
284
285
286
287 func (c *Context) FindKeyPairWithAttributes(attributes AttributeSet) (Signer, error) {
288 if c.closed.Get() {
289 return nil, errClosed
290 }
291
292 result, err := c.FindKeyPairsWithAttributes(attributes)
293 if err != nil {
294 return nil, err
295 }
296
297 if len(result) == 0 {
298 return nil, nil
299 }
300
301 return result[0], nil
302 }
303
304
305
306
307
308
309
310
311 func (c *Context) FindKeyPairsWithAttributes(attributes AttributeSet) (signer []Signer, err error) {
312 if c.closed.Get() {
313 return nil, errClosed
314 }
315
316 var keys []Signer
317
318 if _, ok := attributes[CkaClass]; ok {
319 return nil, errors.Errorf("keypair attribute set must not contain CkaClass")
320 }
321
322 err = c.withSession(func(session *pkcs11Session) error {
323
324 privAttributes := attributes.Copy()
325 err = privAttributes.Set(CkaClass, pkcs11.CKO_PRIVATE_KEY)
326 if err != nil {
327 return err
328 }
329
330 privHandles, err := findKeysWithAttributes(session, privAttributes.ToSlice())
331 if err != nil {
332 return err
333 }
334
335 for _, privHandle := range privHandles {
336 k, _, err := c.makeKeyPair(session, &privHandle)
337
338 if err == errNoCkaId || err == errNoPublicHalf {
339 continue
340 }
341 if err != nil {
342 return err
343 }
344
345 keys = append(keys, k)
346 }
347
348 return nil
349 })
350
351 if err != nil {
352 return nil, err
353 }
354
355 return keys, nil
356 }
357
358
359
360
361
362 func (c *Context) FindAllKeyPairs() ([]Signer, error) {
363 if c.closed.Get() {
364 return nil, errClosed
365 }
366
367 return c.FindKeyPairsWithAttributes(NewAttributeSet())
368 }
369
370
371
372
373
374
375 func (k pkcs11PrivateKey) Public() crypto.PublicKey {
376 return k.pubKey
377 }
378
379
380
381
382 func (c *Context) FindKey(id []byte, label []byte) (*SecretKey, error) {
383 if c.closed.Get() {
384 return nil, errClosed
385 }
386
387 result, err := c.FindKeys(id, label)
388 if err != nil {
389 return nil, err
390 }
391
392 if len(result) == 0 {
393 return nil, nil
394 }
395
396 return result[0], nil
397 }
398
399
400
401
402 func (c *Context) FindKeys(id []byte, label []byte) (key []*SecretKey, err error) {
403 if c.closed.Get() {
404 return nil, errClosed
405 }
406
407 if id == nil && label == nil {
408 return nil, errors.New("id and label cannot both be nil")
409 }
410
411 attributes := NewAttributeSet()
412
413 if id != nil {
414 err = attributes.Set(CkaId, id)
415 if err != nil {
416 return nil, err
417 }
418 }
419 if label != nil {
420 err = attributes.Set(CkaLabel, label)
421 if err != nil {
422 return nil, err
423 }
424 }
425
426 return c.FindKeysWithAttributes(attributes)
427 }
428
429
430 func (c *Context) FindKeyWithAttributes(attributes AttributeSet) (*SecretKey, error) {
431 if c.closed.Get() {
432 return nil, errClosed
433 }
434
435 result, err := c.FindKeysWithAttributes(attributes)
436 if err != nil {
437 return nil, err
438 }
439
440 if len(result) == 0 {
441 return nil, nil
442 }
443
444 return result[0], nil
445 }
446
447
448 func (c *Context) FindKeysWithAttributes(attributes AttributeSet) ([]*SecretKey, error) {
449 if c.closed.Get() {
450 return nil, errClosed
451 }
452
453 var keys []*SecretKey
454
455 if _, ok := attributes[CkaClass]; ok {
456 return nil, errors.Errorf("key attribute set must not contain CkaClass")
457 }
458
459 err := c.withSession(func(session *pkcs11Session) error {
460
461 privAttributes := attributes.Copy()
462 err := privAttributes.Set(CkaClass, pkcs11.CKO_SECRET_KEY)
463 if err != nil {
464 return err
465 }
466
467 privHandles, err := findKeysWithAttributes(session, privAttributes.ToSlice())
468 if err != nil {
469 return err
470 }
471
472 for _, privHandle := range privHandles {
473 attributes := []*pkcs11.Attribute{
474 pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, 0),
475 }
476 if attributes, err = session.ctx.GetAttributeValue(session.handle, privHandle, attributes); err != nil {
477 return err
478 }
479 keyType := bytesToUlong(attributes[0].Value)
480
481 if cipher, ok := Ciphers[int(keyType)]; ok {
482 k := &SecretKey{pkcs11Object{privHandle, c}, cipher}
483 keys = append(keys, k)
484 } else {
485 return errors.Errorf("unsupported key type: %X", keyType)
486 }
487 }
488
489 return nil
490 })
491
492 if err != nil {
493 return nil, err
494 }
495 return keys, nil
496 }
497
498
499 func (c *Context) FindAllKeys() ([]*SecretKey, error) {
500 if c.closed.Get() {
501 return nil, errClosed
502 }
503
504 return c.FindKeysWithAttributes(NewAttributeSet())
505 }
506
507 func uintPtr(i uint) *uint { return &i }
508
509 func (c *Context) getAttributes(handle pkcs11.ObjectHandle, attributes []AttributeType) (a AttributeSet, err error) {
510 values := NewAttributeSet()
511
512 err = c.withSession(func(session *pkcs11Session) error {
513 var attrs []*pkcs11.Attribute
514 for _, a := range attributes {
515 attrs = append(attrs, pkcs11.NewAttribute(a, nil))
516 }
517
518 p11values, err := session.ctx.GetAttributeValue(session.handle, handle, attrs)
519 if err != nil {
520 return err
521 }
522
523 values.AddIfNotPresent(p11values)
524
525 return nil
526 })
527
528 return values, err
529 }
530
531
532
533
534
535 func (c *Context) GetAttributes(key interface{}, attributes []AttributeType) (a AttributeSet, err error) {
536 if c.closed.Get() {
537 return nil, errClosed
538 }
539
540 var handle pkcs11.ObjectHandle
541
542 switch k := (key).(type) {
543 case *pkcs11PrivateKeyDSA:
544 handle = k.handle
545 case *pkcs11PrivateKeyRSA:
546 handle = k.handle
547 case *pkcs11PrivateKeyECDSA:
548 handle = k.handle
549 case *SecretKey:
550 handle = k.handle
551 default:
552 return nil, errors.Errorf("not a PKCS#11 key")
553 }
554
555 return c.getAttributes(handle, attributes)
556 }
557
558
559
560
561
562 func (c *Context) GetAttribute(key interface{}, attribute AttributeType) (a *Attribute, err error) {
563 if c.closed.Get() {
564 return nil, errClosed
565 }
566
567 set, err := c.GetAttributes(key, []AttributeType{attribute})
568 if err != nil {
569 return nil, err
570 }
571
572 return set[attribute], nil
573 }
574
575
576
577
578 func (c *Context) GetPubAttributes(key interface{}, attributes []AttributeType) (a AttributeSet, err error) {
579 if c.closed.Get() {
580 return nil, errClosed
581 }
582
583 var handle pkcs11.ObjectHandle
584
585 switch k := (key).(type) {
586 case *pkcs11PrivateKeyDSA:
587 handle = k.pubKeyHandle
588 case *pkcs11PrivateKeyRSA:
589 handle = k.pubKeyHandle
590 case *pkcs11PrivateKeyECDSA:
591 handle = k.pubKeyHandle
592 default:
593 return nil, errors.Errorf("not an asymmetric PKCS#11 key")
594 }
595
596 return c.getAttributes(handle, attributes)
597 }
598
599
600
601
602 func (c *Context) GetPubAttribute(key interface{}, attribute AttributeType) (a *Attribute, err error) {
603 if c.closed.Get() {
604 return nil, errClosed
605 }
606
607 set, err := c.GetPubAttributes(key, []AttributeType{attribute})
608 if err != nil {
609 return nil, err
610 }
611
612 return set[attribute], nil
613 }
614
View as plain text