forked from google/go-tpm-tools
/
pubkey.go
100 lines (86 loc) · 2.62 KB
/
pubkey.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
package cmd
import (
"crypto"
"crypto/x509"
"encoding/pem"
"fmt"
"io"
"github.com/ThalesIgnite/go-tpm-tools/client"
"github.com/google/go-tpm/tpmutil"
"github.com/google/go-tpm/tpm2"
"github.com/spf13/cobra"
)
var hierarchyNames = map[string]tpmutil.Handle{
"endorsement": tpm2.HandleEndorsement,
"owner": tpm2.HandleOwner,
"platform": tpm2.HandlePlatform,
"null": tpm2.HandleNull,
}
var pubkeyCmd = &cobra.Command{
Use: "pubkey <endorsement | owner | platform | null>",
Short: "Retrieve a public key from the TPM",
Long: `Get the PEM-formatted public component of a TPM's primary key
A TPM can create a primary asymmetric key in one of 4 hierarchies:
endorsement - used for remote attestation, privacy sensitive
owner - used for local signing/encryption, reset on TPM2_Clear
platform - rarely used
null - all keys are ephemeral, reset on every boot
Furthermore, this key is based on a template containing parameters like
algorithms and key sizes. By default, this command uses a standard template
defined in the TPM2 spec. If --index is provided, the template is read from
NVDATA instead (and --algo is ignored).`,
ValidArgs: func() []string {
// The keys from the hierarchyNames map are our valid arguments
keys := make([]string, len(hierarchyNames))
for k := range hierarchyNames {
keys = append(keys, k)
}
return keys
}(),
Args: cobra.ExactValidArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
rwc, err := openTpm()
if err != nil {
return err
}
defer rwc.Close()
key, err := getKey(rwc, hierarchyNames[args[0]], keyAlgo)
if err != nil {
return err
}
defer key.Close()
return writeKey(key.PublicKey())
},
}
func init() {
RootCmd.AddCommand(pubkeyCmd)
addIndexFlag(pubkeyCmd)
addOutputFlag(pubkeyCmd)
addPublicKeyAlgoFlag(pubkeyCmd)
}
func getKey(rw io.ReadWriter, hierarchy tpmutil.Handle, algo tpm2.Algorithm) (*client.Key, error) {
fmt.Fprintf(debugOutput(), "Using hierarchy 0x%x\n", hierarchy)
if nvIndex != 0 {
fmt.Fprintf(debugOutput(), "Reading from NVDATA index %d\n", nvIndex)
return client.KeyFromNvIndex(rw, hierarchy, nvIndex)
}
switch hierarchy {
case tpm2.HandleEndorsement:
return getEK(rw)
case tpm2.HandleOwner:
return getSRK(rw)
default:
return nil, fmt.Errorf("there is no default key for the given hierarchy: 0x%x", hierarchy)
}
}
func writeKey(pubKey crypto.PublicKey) error {
fmt.Fprintf(debugOutput(), "Got key: %+v\n", pubKey)
asn1Bytes, err := x509.MarshalPKIXPublicKey(pubKey)
if err != nil {
return err
}
return pem.Encode(dataOutput(), &pem.Block{
Type: "PUBLIC KEY",
Bytes: asn1Bytes,
})
}