-
Notifications
You must be signed in to change notification settings - Fork 1
/
pin_policy.go
78 lines (64 loc) · 1.72 KB
/
pin_policy.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
// SPDX-FileCopyrightText: 2020 Google LLC
// SPDX-License-Identifier: Apache-2.0
package piv
import (
"errors"
"fmt"
iso "cunicu.li/go-iso7816"
)
//nolint:gochecknoglobals
var (
pinPolicyMap = map[PINPolicy]byte{
PINPolicyNever: 0x01,
PINPolicyOnce: 0x02,
PINPolicyAlways: 0x03,
}
pinPolicyMapInv = map[byte]PINPolicy{
0x01: PINPolicyNever,
0x02: PINPolicyOnce,
0x03: PINPolicyAlways,
}
)
// PINPolicy represents PIN requirements when signing or decrypting with an
// asymmetric key in a given slot.
type PINPolicy int
// PIN policies supported by this package.
//
// BUG(ericchiang): Caching for PINPolicyOnce isn't supported on YubiKey
// versions older than 4.3.0 due to issues with verifying if a PIN is needed.
// If specified, a PIN will be required for every operation.
const (
PINPolicyNever PINPolicy = iota + 1
PINPolicyOnce
PINPolicyAlways
)
func pinPolicy(c *Card, slot Slot) (PINPolicy, error) {
v, _ := iso.ParseVersion("4.3.0")
if !v.Less(c.Version()) {
md, err := c.Metadata(slot)
if err != nil {
return 0, fmt.Errorf("failed to get key info: %w", err)
}
return md.PINPolicy, nil
}
cert, err := c.Attest(slot)
if err != nil {
var e *iso.Code
if errors.As(err, &e) && *e == iso.ErrUnsupportedInstruction {
// Attestation cert command not supported, probably an older YubiKey.
// Guess PINPolicyAlways.
//
// See https://cunicu.li/go-piv/issues/55
return PINPolicyAlways, nil
}
return 0, fmt.Errorf("failed to get attestation cert: %w", err)
}
a, err := parseAttestation(cert)
if err != nil {
return 0, fmt.Errorf("failed to parse attestation cert: %w", err)
}
if _, ok := pinPolicyMap[a.PINPolicy]; ok {
return a.PINPolicy, nil
}
return PINPolicyOnce, nil
}