Skip to content

Commit 4904e98

Browse files
committed
Add some example binaries
This adds some example binaries which are useful for manual testing: - activate-volume: An example that makes use of ActivateVolumeWithTPMSealedKey and ActivateVolumeWithRecoveryKey. - change-pin: An example that makes use of ChangePIN. - provision-status: An example that makes use of ProvisionStatus. - provision-tpm: An example that makes use of ProvistionTPM. - seal-key: An example that makes use of SealKeyToTPM to seal a key to PCR7 on Ubuntu classic systems. - unseal-key: An example that makes use of SealedKeyObject.UnsealFromTPM.
1 parent 337f350 commit 4904e98

File tree

9 files changed

+686
-10
lines changed

9 files changed

+686
-10
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,7 @@
1+
examples/activate-volume/activate-volume
2+
examples/change-pin/change-pin
3+
examples/provision-status/provision-status
4+
examples/provision-tpm/provision-tpm
5+
examples/seal-key/seal-key
6+
examples/unseal-key/unseal-key
17
vendor/*/

crypt_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -846,7 +846,7 @@ func (s *cryptSuite) testActivateVolumeWithRecoveryKeyUsingKeyReader(c *C, data
846846
func (s *cryptSuite) TestActivateVolumeWithRecoveryKeyUsingKeyReader1(c *C) {
847847
// Test with the correct recovery key supplied via a io.Reader, with a hyphen separating each group of 5 digits.
848848
s.testActivateVolumeWithRecoveryKeyUsingKeyReader(c, &testActivateVolumeWithRecoveryKeyUsingKeyReaderData{
849-
tries: 1,
849+
tries: 1,
850850
recoveryKeyFileContents: strings.Join(s.recoveryKeyAscii, "-") + "\n",
851851
sdCryptsetupCalls: 1,
852852
})
@@ -855,7 +855,7 @@ func (s *cryptSuite) TestActivateVolumeWithRecoveryKeyUsingKeyReader1(c *C) {
855855
func (s *cryptSuite) TestActivateVolumeWithRecoveryKeyUsingKeyReader2(c *C) {
856856
// Test with the correct recovery key supplied via a io.Reader, without a hyphen separating each group of 5 digits.
857857
s.testActivateVolumeWithRecoveryKeyUsingKeyReader(c, &testActivateVolumeWithRecoveryKeyUsingKeyReaderData{
858-
tries: 1,
858+
tries: 1,
859859
recoveryKeyFileContents: strings.Join(s.recoveryKeyAscii, "") + "\n",
860860
sdCryptsetupCalls: 1,
861861
})
@@ -864,7 +864,7 @@ func (s *cryptSuite) TestActivateVolumeWithRecoveryKeyUsingKeyReader2(c *C) {
864864
func (s *cryptSuite) TestActivateVolumeWithRecoveryKeyUsingKeyReader3(c *C) {
865865
// Test with the correct recovery key supplied via a io.Reader when the key doesn't end in a newline.
866866
s.testActivateVolumeWithRecoveryKeyUsingKeyReader(c, &testActivateVolumeWithRecoveryKeyUsingKeyReaderData{
867-
tries: 1,
867+
tries: 1,
868868
recoveryKeyFileContents: strings.Join(s.recoveryKeyAscii, "-"),
869869
sdCryptsetupCalls: 1,
870870
})
@@ -873,7 +873,7 @@ func (s *cryptSuite) TestActivateVolumeWithRecoveryKeyUsingKeyReader3(c *C) {
873873
func (s *cryptSuite) TestActivateVolumeWithRecoveryKeyUsingKeyReader4(c *C) {
874874
// Test that falling back to requesting a recovery key works if the one provided by the io.Reader is incorrect.
875875
s.testActivateVolumeWithRecoveryKeyUsingKeyReader(c, &testActivateVolumeWithRecoveryKeyUsingKeyReaderData{
876-
tries: 2,
876+
tries: 2,
877877
recoveryKeyFileContents: "00000-00000-00000-00000-00000-00000-00000-00000\n",
878878
recoveryPassphrases: []string{strings.Join(s.recoveryKeyAscii, "-")},
879879
sdCryptsetupCalls: 2,
@@ -883,7 +883,7 @@ func (s *cryptSuite) TestActivateVolumeWithRecoveryKeyUsingKeyReader4(c *C) {
883883
func (s *cryptSuite) TestActivateVolumeWithRecoveryKeyUsingKeyReader5(c *C) {
884884
// Test that falling back to requesting a recovery key works if the one provided by the io.Reader is badly formatted.
885885
s.testActivateVolumeWithRecoveryKeyUsingKeyReader(c, &testActivateVolumeWithRecoveryKeyUsingKeyReaderData{
886-
tries: 2,
886+
tries: 2,
887887
recoveryKeyFileContents: "5678\n",
888888
recoveryPassphrases: []string{strings.Join(s.recoveryKeyAscii, "-")},
889889
sdCryptsetupCalls: 1,

examples/activate-volume/main.go

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
// -*- Mode: Go; indent-tabs-mode: t -*-
2+
3+
/*
4+
* Copyright (C) 2019 Canonical Ltd
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License version 3 as
8+
* published by the Free Software Foundation.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*
18+
*/
19+
20+
package main
21+
22+
import (
23+
"flag"
24+
"fmt"
25+
"io"
26+
"os"
27+
"strconv"
28+
"strings"
29+
30+
"github.com/snapcore/secboot"
31+
)
32+
33+
func run() int {
34+
args := flag.Args()
35+
if len(args) == 0 {
36+
fmt.Printf("Usage: activate-volume VOLUME SOURCE-DEVICE SEALED-KEY-FILE [AUTH-FILE] [OPTIONS]\n")
37+
return 0
38+
}
39+
40+
if len(args) < 3 {
41+
fmt.Fprintf(os.Stderr, "Cannot activate device: insufficient arguments\n")
42+
return 1
43+
}
44+
45+
volume := args[0]
46+
sourceDevice := args[1]
47+
48+
var keyFilePath string
49+
if args[2] != "" && args[2] != "-" && args[2] != "none" {
50+
keyFilePath = args[2]
51+
}
52+
53+
var authFilePath string
54+
if len(args) >= 4 && args[3] != "" && args[3] != "-" && args[3] != "none" {
55+
authFilePath = args[3]
56+
}
57+
58+
var lock bool
59+
var forceRecovery bool
60+
pinTries := 1
61+
recoveryTries := 1
62+
var activateOptions []string
63+
64+
if len(args) >= 5 && args[4] != "" && args[4] != "-" && args[4] != "none" {
65+
opts := strings.Split(args[4], ",")
66+
for _, opt := range opts {
67+
switch {
68+
case opt == "lock":
69+
lock = true
70+
case opt == "force-recovery":
71+
forceRecovery = true
72+
case strings.HasPrefix(opt, "pin-tries="):
73+
u, err := strconv.ParseUint(strings.TrimPrefix(opt, "pin-tries="), 10, 8)
74+
if err != nil {
75+
fmt.Fprintf(os.Stderr, "Cannot activate device %s: invalid value for \"recovery-tries=\"\n", sourceDevice)
76+
return 1
77+
}
78+
pinTries = int(u)
79+
case strings.HasPrefix(opt, "recovery-tries="):
80+
u, err := strconv.ParseUint(strings.TrimPrefix(opt, "recovery-tries="), 10, 8)
81+
if err != nil {
82+
fmt.Fprintf(os.Stderr, "Cannot activate device %s: invalid value for \"recovery-tries=\"\n", sourceDevice)
83+
return 1
84+
}
85+
recoveryTries = int(u)
86+
default:
87+
activateOptions = append(activateOptions, opt)
88+
}
89+
}
90+
}
91+
92+
var authReader io.Reader
93+
if authFilePath != "" {
94+
f, err := os.Open(authFilePath)
95+
if err != nil {
96+
fmt.Fprintf(os.Stderr, "Cannot open auth file: %v\n", err)
97+
return 1
98+
}
99+
defer f.Close()
100+
authReader = f
101+
}
102+
103+
if !forceRecovery {
104+
tpm, err := secboot.ConnectToDefaultTPM()
105+
if err != nil {
106+
fmt.Fprintf(os.Stderr, "Cannot connect to TPM: %v\n", err)
107+
return 1
108+
}
109+
defer tpm.Close()
110+
111+
options := secboot.ActivateWithTPMSealedKeyOptions{
112+
PINTries: pinTries,
113+
RecoveryKeyTries: recoveryTries,
114+
ActivateOptions: activateOptions,
115+
LockSealedKeyAccess: lock}
116+
if success, err := secboot.ActivateVolumeWithTPMSealedKey(tpm, volume, sourceDevice, keyFilePath, authReader, &options); err != nil {
117+
if !success {
118+
fmt.Fprintf(os.Stderr, "Activation failed: %v\n", err)
119+
return 1
120+
}
121+
fmt.Printf("Activation succeeded with fallback recovery key: %v\n", err)
122+
}
123+
} else {
124+
options := secboot.ActivateWithRecoveryKeyOptions{
125+
Tries: recoveryTries,
126+
ActivateOptions: activateOptions}
127+
if err := secboot.ActivateVolumeWithRecoveryKey(volume, sourceDevice, authReader, &options); err != nil {
128+
fmt.Fprintf(os.Stderr, "Activation with recovery key failed: %v\n", err)
129+
return 1
130+
}
131+
}
132+
133+
return 0
134+
}
135+
136+
func main() {
137+
flag.Parse()
138+
os.Exit(run())
139+
}

examples/change-pin/main.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// -*- Mode: Go; indent-tabs-mode: t -*-
2+
3+
/*
4+
* Copyright (C) 2019 Canonical Ltd
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License version 3 as
8+
* published by the Free Software Foundation.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*
18+
*/
19+
20+
package main
21+
22+
import (
23+
"flag"
24+
"fmt"
25+
"os"
26+
27+
"github.com/snapcore/secboot"
28+
)
29+
30+
var keyFile string
31+
var currentPin string
32+
33+
func init() {
34+
flag.StringVar(&currentPin, "current-pin", "", "")
35+
flag.StringVar(&keyFile, "key-file", "", "")
36+
}
37+
38+
func run() int {
39+
if keyFile == "" {
40+
fmt.Fprintf(os.Stderr, "Cannot change PIN: missing -key-file\n")
41+
return 1
42+
}
43+
44+
args := flag.Args()
45+
var pin string
46+
if len(args) > 0 {
47+
pin = args[0]
48+
}
49+
50+
tpm, err := secboot.ConnectToDefaultTPM()
51+
if err != nil {
52+
fmt.Fprintf(os.Stderr, "Cannot connect to TPM: %v\n", err)
53+
return 1
54+
}
55+
defer tpm.Close()
56+
57+
if err := secboot.ChangePIN(tpm, keyFile, currentPin, pin); err != nil {
58+
fmt.Fprintf(os.Stderr, "Cannot change PIN: %v\n", err)
59+
return 1
60+
}
61+
62+
return 0
63+
}
64+
65+
func main() {
66+
flag.Parse()
67+
os.Exit(run())
68+
}

examples/provision-status/main.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// -*- Mode: Go; indent-tabs-mode: t -*-
2+
3+
/*
4+
* Copyright (C) 2019 Canonical Ltd
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License version 3 as
8+
* published by the Free Software Foundation.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*
18+
*/
19+
20+
package main
21+
22+
import (
23+
"fmt"
24+
"os"
25+
26+
"github.com/snapcore/secboot"
27+
)
28+
29+
func run() int {
30+
tpm, err := secboot.ConnectToDefaultTPM()
31+
if err != nil {
32+
fmt.Fprintf(os.Stderr, "Cannot connect to TPM: %v\n", err)
33+
return 1
34+
}
35+
defer tpm.Close()
36+
37+
status, err := secboot.ProvisionStatus(tpm)
38+
if err != nil {
39+
fmt.Fprintf(os.Stderr, "Cannot determine status: %v\n", err)
40+
return 1
41+
}
42+
43+
if status&secboot.AttrValidSRK > 0 {
44+
fmt.Println("Valid SRK found in TPM")
45+
} else {
46+
fmt.Println("** ERROR: TPM does not have a valid SRK **")
47+
}
48+
49+
if status&secboot.AttrValidEK > 0 {
50+
fmt.Println("Valid EK found in TPM")
51+
} else {
52+
fmt.Println("** ERROR: TPM does not have a valid EK **")
53+
}
54+
55+
if status&secboot.AttrDAParamsOK > 0 {
56+
fmt.Println("TPM's DA parameters are correct")
57+
} else {
58+
fmt.Println("** ERROR: TPM's DA parameters are not the values set during provisioning **")
59+
}
60+
61+
if status&secboot.AttrOwnerClearDisabled > 0 {
62+
fmt.Println("TPM does not allow clearing with the lockout hierarchy authorization")
63+
} else {
64+
fmt.Println("** ERROR: TPM allows clearing with the lockout hierarchy authorization **")
65+
}
66+
67+
if status&secboot.AttrLockoutAuthSet > 0 {
68+
fmt.Println("The lockout hierarchy authorization is set")
69+
} else {
70+
fmt.Println("** ERROR: The lockout hierarchy authorization is not set **")
71+
}
72+
73+
if status&secboot.AttrValidLockNVIndex > 0 {
74+
fmt.Println("Valid lock NV index found in TPM")
75+
} else {
76+
fmt.Println("** ERROR: TPM does not have a valid lock NV index **")
77+
}
78+
79+
return 0
80+
}
81+
82+
func main() {
83+
os.Exit(run())
84+
}

0 commit comments

Comments
 (0)