forked from google/go-tpm-tools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
seal.go
148 lines (128 loc) · 4.01 KB
/
seal.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
package cmd
import (
"fmt"
"io/ioutil"
"github.com/spf13/cobra"
"github.com/ProsaicSatsuma/go-tpm-tools/client"
tpmpb "github.com/ProsaicSatsuma/go-tpm-tools/proto"
"github.com/google/go-tpm/tpm2"
)
var sealCmd = &cobra.Command{
Use: "seal",
Short: "Seal some data to the TPM",
Long: `Encrypt the input data using the TPM
TPMs support a "sealing" operation that allows some secret data to be encrypted
by a particular TPM. This data can only be decrypted by the same TPM that did
the encryption.
Optionally (using the --pcrs flag), this decryption can be furthur restricted to
only work if certain Platform Control Registers (PCRs) are in the correct state.
This allows a key (i.e. a disk encryption key) to be bound to specific machine
state (like Secure Boot).`,
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
rwc, err := openTpm()
if err != nil {
return err
}
defer rwc.Close()
fmt.Fprintln(debugOutput(), "Loading SRK")
srk, err := getSRK(rwc)
if err != nil {
return err
}
defer srk.Close()
fmt.Fprintln(debugOutput(), "Reading sealed data")
secret, err := ioutil.ReadAll(dataInput())
if err != nil {
return err
}
sel := getSelection()
fmt.Fprintf(debugOutput(), "Sealing to PCRs: %v\n", sel.PCRs)
var sOpt client.SealOpt
if len(sel.PCRs) > 0 {
sOpt = client.SealCurrent{PCRSelection: sel}
}
sealed, err := srk.Seal(secret, sOpt)
if err != nil {
return fmt.Errorf("sealing data: %w", err)
}
fmt.Fprintln(debugOutput(), "Writing sealed data")
var output []byte
if output, err = marshalOptions.Marshal(sealed); err != nil {
return err
}
if _, err = dataOutput().Write(output); err != nil {
return err
}
fmt.Fprintf(debugOutput(), "Sealed data to PCRs: %v\n", sel.PCRs)
return nil
},
}
var unsealCmd = &cobra.Command{
Use: "unseal",
Short: "Unseal some data previously sealed to the TPM",
Long: `Decrypt the input data using the TPM
The opposite of "gotpm seal". This takes in some sealed input and decrypts it
using the TPM. This operation will fail if used on a different TPM, or if the
Platform Control Registers (PCRs) are in the incorrect state.
All the necessary data to decrypt the sealed input is present in the input blob.
We do not need to specify the PCRs used for unsealing.
We do support an optional "certification" process. A list of PCRs may be
provided with --pcrs, and the unwrapping will fail if the PCR values when
sealing differ from the current PCR values. This allows for verification of the
machine state when sealing took place.
`,
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
rwc, err := openTpm()
if err != nil {
return err
}
defer rwc.Close()
fmt.Fprintln(debugOutput(), "Reading sealed data")
data, err := ioutil.ReadAll(dataInput())
if err != nil {
return err
}
var sealed tpmpb.SealedBytes
if err := unmarshalOptions.Unmarshal(data, &sealed); err != nil {
return err
}
fmt.Fprintln(debugOutput(), "Loading SRK")
keyAlgo = tpm2.Algorithm(sealed.GetSrk())
srk, err := getSRK(rwc)
if err != nil {
return err
}
defer srk.Close()
fmt.Fprintln(debugOutput(), "Unsealing data")
certifySel := tpm2.PCRSelection{Hash: client.CertifyHashAlgTpm, PCRs: pcrs}
var cOpt client.CertifyOpt
if len(certifySel.PCRs) > 0 {
cOpt = client.CertifyCurrent{PCRSelection: certifySel}
}
secret, err := srk.Unseal(&sealed, cOpt)
if err != nil {
return fmt.Errorf("unsealing data: %w", err)
}
fmt.Fprintln(debugOutput(), "Writing secret data")
if _, err := dataOutput().Write(secret); err != nil {
return fmt.Errorf("writing secret data: %w", err)
}
fmt.Fprintln(debugOutput(), "Unsealed data using TPM")
return nil
},
}
func init() {
RootCmd.AddCommand(sealCmd)
RootCmd.AddCommand(unsealCmd)
addInputFlag(sealCmd)
addInputFlag(unsealCmd)
addOutputFlag(sealCmd)
addOutputFlag(unsealCmd)
// PCRs and hash algorithm only used for sealing
addPCRsFlag(sealCmd)
addHashAlgoFlag(sealCmd)
addPCRsFlag(unsealCmd)
addPublicKeyAlgoFlag(sealCmd)
}