Files
external-signer-tpm/generate.go
2025-05-29 23:18:01 +08:00

137 lines
3.3 KiB
Go

package main
import (
"crypto/sha1"
"crypto/x509"
"encoding/base64"
"encoding/json"
"fmt"
"os"
"strconv"
"strings"
"github.com/google/go-tpm/tpm"
"github.com/urfave/cli/v2"
)
func buildGenerateKeyCommand() *cli.Command {
return &cli.Command{
Name: "generate_key",
Usage: "Generate key",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "parameter",
Usage: "The path to the TPM device to use",
DefaultText: "/dev/tpm0",
},
&cli.StringFlag{
Name: "keyblob",
Usage: "Output path of the generated keyblob",
DefaultText: "keyblob",
},
&cli.StringFlag{
Name: "public-key",
Usage: "Output path of the generated keyblob's public key",
DefaultText: "publickey",
},
&cli.StringFlag{
Name: "pcrs",
Usage: "A comma-separated list of PCR numbers against which the generated key will be bound. If blank, it will not be bound to any PCR values.",
},
},
Action: func(ctx *cli.Context) error {
tpmname := ctx.String("tpmname")
keyblob := ctx.String("keyblob")
publicKey := ctx.String("public-key")
pcrs := ctx.String("pcrs")
generateAction(tpmname, keyblob, publicKey, pcrs)
return nil
},
}
}
func generateAction(tpmname, keyblobPath, pubKeyPath, pcrsStr string) {
var pcrs []int
if pcrsStr != "" {
for _, pcr := range strings.Split(pcrsStr, ",") {
pcrNum, err := strconv.Atoi(pcr)
if err != nil {
fmt.Fprintf(os.Stderr, "Bad value in pcrs argument: %s\n", pcr)
return
}
pcrs = append(pcrs, pcrNum)
}
}
rwc, err := tpm.OpenTPM(tpmname)
if err != nil {
fmt.Fprintf(os.Stderr, "Couldn't open the TPM file %s: %s\n", tpmname, err)
return
}
defer rwc.Close()
// Compute the auth values as needed.
var srkAuth [20]byte
srkInput := os.Getenv(srkAuthEnvVar)
if srkInput != "" {
sa := sha1.Sum([]byte(srkInput))
copy(srkAuth[:], sa[:])
}
var usageAuth [20]byte
usageInput := os.Getenv(usageAuthEnvVar)
if usageInput != "" {
ua := sha1.Sum([]byte(usageInput))
copy(usageAuth[:], ua[:])
}
var migrationAuth [20]byte
migrationInput := os.Getenv(migrationAuthEnvVar)
if migrationInput != "" {
ma := sha1.Sum([]byte(migrationInput))
copy(migrationAuth[:], ma[:])
}
keyblob, err := tpm.CreateWrapKey(rwc, srkAuth[:], usageAuth, migrationAuth, pcrs)
if err != nil {
fmt.Fprintf(os.Stderr, "Couldn't make a new signing key: %s\n", err)
return
}
fmt.Printf("Writing keyblob to %s\n", keyblobPath)
if err = os.WriteFile(keyblobPath, keyblob, 0644); err != nil {
fmt.Fprintf(os.Stderr, "Error writing keyblob file: %s\n", err)
return
}
pubKey, err := tpm.UnmarshalRSAPublicKey(keyblob)
if err != nil {
fmt.Fprintf(os.Stderr, "Could not get public key: %s\n", err)
return
}
pubKeyBytes, err := x509.MarshalPKIXPublicKey(pubKey)
if err != nil {
fmt.Fprintf(os.Stderr, "Could not marshal public key: %s\n", err)
return
}
fmt.Printf("Writing public key to %s\n", pubKeyPath)
if err = os.WriteFile(pubKeyPath, pubKeyBytes, 0644); err != nil {
fmt.Fprintf(os.Stderr, "Error writing public key file: %s\n", err)
return
}
tpmKey := &TpmKey{
Tpm: tpmname,
Keyblob: base64.StdEncoding.EncodeToString(keyblob),
}
tpmKeyJson, err := json.Marshal(&tpmKey)
if err != nil {
fmt.Fprintf(os.Stderr, "Error marshal tmp key: %s\n", err)
return
}
println(base64.StdEncoding.EncodeToString(tpmKeyJson))
}