forked from google/go-tpm-tools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
flags.go
203 lines (173 loc) · 4.68 KB
/
flags.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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
package cmd
import (
"errors"
"io"
"os"
"strconv"
"strings"
"github.com/ProsaicSatsuma/go-tpm-tools/client"
"github.com/google/go-tpm/tpm2"
"github.com/spf13/cobra"
)
var (
output string
input string
nvIndex uint32
keyAlgo = tpm2.AlgRSA
pcrs []int
hashAlgo = tpm2.AlgSHA256
)
type pcrsFlag struct {
value *[]int
}
func (f *pcrsFlag) Set(val string) error {
for _, d := range strings.Split(val, ",") {
pcr, err := strconv.Atoi(d)
if err != nil {
return err
}
if pcr < 0 || pcr >= client.NumPCRs {
return errors.New("pcr out of range")
}
*f.value = append(*f.value, pcr)
}
return nil
}
func (f *pcrsFlag) Type() string {
return "pcrs"
}
func (f *pcrsFlag) String() string {
return "" // Don't display a default value
}
var algos = map[tpm2.Algorithm]string{
tpm2.AlgRSA: "rsa",
tpm2.AlgECC: "ecc",
tpm2.AlgSHA1: "sha1",
tpm2.AlgSHA256: "sha256",
tpm2.AlgSHA384: "sha384",
tpm2.AlgSHA512: "sha512",
}
type algoFlag struct {
value *tpm2.Algorithm
allowed []tpm2.Algorithm
}
func (f *algoFlag) Set(val string) error {
present := false
for _, algo := range f.allowed {
if algos[algo] == val {
*f.value = algo
present = true
}
}
if !present {
return errors.New("unknown algorithm")
}
return nil
}
func (f *algoFlag) Type() string {
return "algo"
}
func (f *algoFlag) String() string {
return algos[*f.value]
}
// Allowed gives a string list of the permitted algorithm values for this flag.
func (f *algoFlag) Allowed() string {
out := make([]string, len(f.allowed))
for i, a := range f.allowed {
out[i] = algos[a]
}
return strings.Join(out, ", ")
}
// Disable the "help" subcommand (and just use the -h/--help flags).
// This should be called on all commands with subcommands.
// See https://github.com/spf13/cobra/issues/587 for why this is needed.
func hideHelp(cmd *cobra.Command) {
cmd.SetHelpCommand(&cobra.Command{Hidden: true})
}
// Lets this command specify an output file, for use with dataOutput().
func addOutputFlag(cmd *cobra.Command) {
cmd.PersistentFlags().StringVar(&output, "output", "",
"output file (defaults to stdout)")
}
// Lets this command specify an input file, for use with dataInput().
func addInputFlag(cmd *cobra.Command) {
cmd.PersistentFlags().StringVar(&input, "input", "",
"input file (defaults to stdin)")
}
// Lets this command specify an NVDATA index, for use with nvIndex.
func addIndexFlag(cmd *cobra.Command) {
cmd.PersistentFlags().Uint32Var(&nvIndex, "index", 0,
"NVDATA index, cannot be 0")
}
// Lets this command specify some number of PCR arguments, check if in range.
func addPCRsFlag(cmd *cobra.Command) {
cmd.PersistentFlags().Var(&pcrsFlag{&pcrs}, "pcrs", "comma separated list of PCR numbers")
}
// Lets this command specify the public key algorithm.
func addPublicKeyAlgoFlag(cmd *cobra.Command) {
f := algoFlag{&keyAlgo, []tpm2.Algorithm{tpm2.AlgRSA, tpm2.AlgECC}}
cmd.PersistentFlags().Var(&f, "algo", "public key algorithm: "+f.Allowed())
}
func addHashAlgoFlag(cmd *cobra.Command) {
f := algoFlag{&hashAlgo, []tpm2.Algorithm{tpm2.AlgSHA1, tpm2.AlgSHA256, tpm2.AlgSHA384, tpm2.AlgSHA512}}
cmd.PersistentFlags().Var(&f, "hash-algo", "hash algorithm: "+f.Allowed())
}
// alwaysError implements io.ReadWriter by always returning an error
type alwaysError struct {
error
}
func (ae alwaysError) Write([]byte) (int, error) {
return 0, ae.error
}
func (ae alwaysError) Read(p []byte) (n int, err error) {
return 0, ae.error
}
// Handle to output data file. If there is an issue opening the file, the Writer
// returned will return the error upon any call to Write()
func dataOutput() io.Writer {
if output == "" {
return os.Stdout
}
file, err := os.Create(output)
if err != nil {
return alwaysError{err}
}
return file
}
// Handle to input data file. If there is an issue opening the file, the Reader
// returned will return the error upon any call to Read()
func dataInput() io.Reader {
if input == "" {
return os.Stdin
}
file, err := os.Open(input)
if err != nil {
return alwaysError{err}
}
return file
}
func getSelection() tpm2.PCRSelection {
return tpm2.PCRSelection{Hash: hashAlgo, PCRs: pcrs}
}
// Load SRK based on tpm2.Algorithm set in the global flag vars.
func getSRK(rwc io.ReadWriter) (*client.Key, error) {
switch keyAlgo {
case tpm2.AlgRSA:
return client.StorageRootKeyRSA(rwc)
case tpm2.AlgECC:
return client.StorageRootKeyECC(rwc)
default:
panic("unexpected keyAlgo")
}
}
// Load EK based on tpm2.Algorithm set in the global flag vars.
func getEK(rwc io.ReadWriter) (*client.Key, error) {
switch keyAlgo {
case tpm2.AlgRSA:
return client.EndorsementKeyRSA(rwc)
case tpm2.AlgECC:
return client.EndorsementKeyECC(rwc)
default:
panic("unexpected keyAlgo")
}
}