-
Notifications
You must be signed in to change notification settings - Fork 1
/
cert.go
68 lines (56 loc) · 1.86 KB
/
cert.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
// SPDX-FileCopyrightText: 2020 Google LLC
// SPDX-License-Identifier: Apache-2.0
package piv
import (
"crypto/x509"
"fmt"
"cunicu.li/go-iso7816/encoding/tlv"
)
// Certificate returns the certificate object stored in a given slot.
//
// If a certificate hasn't been set in the provided slot, the returned error
// wraps ErrNotFound.
func (c *Card) Certificate(slot Slot) (*x509.Certificate, error) {
resp, err := sendTLV(c.tx, insGetData, 0x3f, 0xff, slot.Object.TagValue())
if err != nil {
return nil, fmt.Errorf("failed to execute command: %w", err)
}
data, _, ok := resp.Get(0x53)
if !ok {
return nil, errUnmarshal
}
tvsCert, err := tlv.DecodeBER(data)
if err != nil {
return nil, errUnmarshal
}
// https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-73-4.pdf#page=85
certDER, _, ok := tvsCert.Get(0x70)
if !ok {
return nil, fmt.Errorf("failed to unmarshal response: %w", err)
}
cert, err := x509.ParseCertificate(certDER)
if err != nil {
return nil, fmt.Errorf("%w: %w", errParseCert, err)
}
return cert, nil
}
// SetCertificate stores a certificate object in the provided slot. Setting a
// certificate isn't required to use the associated key for signing or
// decryption.
func (c *Card) SetCertificate(key ManagementKey, slot Slot, cert *x509.Certificate) error {
if err := c.authenticate(key); err != nil {
return fmt.Errorf("failed to authenticate with management key: %w", err)
}
if _, err := sendTLV(c.tx, insPutData, 0x3f, 0xff,
slot.Object.TagValue(),
tlv.New(0x53,
// https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-73-4.pdf#page=40
tlv.New(tagCertificate, cert.Raw),
tlv.New(tagCertInfo, 0x00), // "for a certificate encoded in uncompressed form CertInfo shall be 0x00"
tlv.New(tagErrorDetectionCode),
),
); err != nil {
return fmt.Errorf("failed to execute command: %w", err)
}
return nil
}