Skip to content
This repository has been archived by the owner on Sep 6, 2023. It is now read-only.

Commit

Permalink
Generate tpm policies use go-tpm2 package.
Browse files Browse the repository at this point in the history
This commit replaces tpm-tools commands with golang
go-tpm2 module to generate tpm ea policies.

Signed-off-by: Joy Latten <[email protected]>
  • Loading branch information
Joy Latten committed Jul 25, 2023
1 parent f464673 commit 1e37e28
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 83 deletions.
56 changes: 31 additions & 25 deletions cmd/trust/policygen.go
Original file line number Diff line number Diff line change
@@ -1,54 +1,60 @@
package main

import (
"github.com/project-machine/trust/pkg/trust"
"errors"

"github.com/urfave/cli"
"github.com/project-machine/trust/pkg/trust"
)

var tpmPolicyGenCmd = cli.Command{
Name: "tpm-policy-gen",
Usage: "Generate tpm policy",
Usage: "Generate tpm policy for a keyset",
Action: doTpmPolicygen,
ArgsUsage: "<keyset-name>",
Flags: []cli.Flag{
cli.StringFlag{
Name: "pf,passwd-policy-file",
Name: "pf, passwd-policy-file",
Usage: "File to which to write password policy",
Value: "passwd_policy.out",
},
cli.StringFlag{
Name: "lf,luks-policy-file",
Name: "lf, luks-policy-file",
Usage: "File to which to write luks policy",
Value: "luks_policy.out",
},
cli.StringFlag{
Name: "pp,passwd-pcr7-file",
Usage: "File from which to read password pcr7",
Value: "passwd_pcr7.bin",
Name: "pcr7-tpm",
Usage: "File from which to read uki-tpm pcr7 value",
Value: "sha256 pcr7 value",
},
cli.StringFlag{
Name: "lp,production-pcr7-file,luks-pcr7-file",
Usage: "File from which to read production pcr7",
Value: "luks_pcr7.bin",
},
cli.IntFlag{
Name: "pv,policy-version",
Usage: "Policy version",
Value: 1,
Name: "pcr7-production",
Usage: "File from which to read uki-production pcr7 value",
Value: "sha256 pcr7 value",
},
cli.StringFlag{
Name: "pk,passwd-pubkey-file",
Usage: "File from which to read password policy pubkey",
Value: "passwd_pubkey.pem",
},
cli.StringFlag{
Name: "lk,luks-pubkey-file",
Usage: "File from which read write luks policy pubkey",
Value: "luks_pubkey.pem",
Name: "pv, policy-version",
Usage: "A four digit policy version, i.e. 0001",
Value: "0001",
},
},
}

func doTpmPolicygen(ctx *cli.Context) error {
return trust.TpmGenPolicy(ctx)
}
args := ctx.Args()
if len(args) != 1 {
return errors.New("Missing argument: <keyset-name>")
}
keysetName := args[0]

pData := trust.PolicyData{
Pcr7Prod: ctx.String("pcr7-production"),
Pcr7Tpm: ctx.String("pcr7-tpm"),
LuksOutFile: ctx.String("luks-policy-file"),
TpmpassOutFile: ctx.String("passwd-policy-file"),
PolicyVersion: ctx.String("policy-version"),
}

return trust.TpmGenPolicy(keysetName, pData)
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ require (
github.com/anuvu/disko v0.0.11
github.com/apex/log v1.9.0
github.com/canonical/go-efilib v0.9.4
github.com/canonical/go-tpm2 v1.0.0
github.com/canonical/tcglog-parser v0.0.0-20230429160108-0d6d239de69d
github.com/fatih/color v1.15.0
github.com/foxboron/go-uefi v0.0.0-20230218004016-d1bb9a12f92c
Expand All @@ -18,7 +19,6 @@ require (
github.com/Microsoft/go-winio v0.4.16 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 // indirect
github.com/acomagu/bufpipe v1.0.3 // indirect
github.com/canonical/go-tpm2 v0.1.0 // indirect
github.com/emirpasic/gods v1.12.0 // indirect
github.com/go-git/gcfg v1.5.0 // indirect
github.com/go-git/go-billy/v5 v5.3.1 // indirect
Expand Down
6 changes: 5 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,17 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkY
github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I=
github.com/bsiegert/ranges v0.0.0-20111221115336-19303dc7aa63/go.mod h1:8z71/aZjDHLs4ihK/5nD5wZVQxm/W4eRDnxQZcJmVD4=
github.com/canonical/go-efilib v0.3.0/go.mod h1:9b2PNAuPcZsB76x75/uwH99D8CyH/A2y4rq1/+bvplg=
github.com/canonical/go-efilib v0.3.1-0.20220314143719-95d50e8afc82/go.mod h1:9b2PNAuPcZsB76x75/uwH99D8CyH/A2y4rq1/+bvplg=
github.com/canonical/go-efilib v0.9.4 h1:cD6oNSWeQSgeSeJZMCxhGEW4GoLSxFhIJ12Hg3vFCtU=
github.com/canonical/go-efilib v0.9.4/go.mod h1:tHjv3Mni7hEpNSUNd1KJEV/AZJsFSH6LX/EQ0I75AZE=
github.com/canonical/go-sp800.108-kdf v0.0.0-20210314145419-a3359f2d21b9/go.mod h1:Zrs3YjJr+w51u0R/dyLh/oWt/EcBVdLPCVFYC4daW5s=
github.com/canonical/go-sp800.108-kdf v0.0.0-20210315104021-ead800bbf9a0 h1:ZE2XMRFHcwlib3uU9is37+pKkkMloVoEPWmgQ6GK1yo=
github.com/canonical/go-sp800.108-kdf v0.0.0-20210315104021-ead800bbf9a0/go.mod h1:Zrs3YjJr+w51u0R/dyLh/oWt/EcBVdLPCVFYC4daW5s=
github.com/canonical/go-sp800.90a-drbg v0.0.0-20210314144037-6eeb1040d6c3/go.mod h1:qdP0gaj0QtgX2RUZhnlVrceJ+Qln8aSlDyJwelLLFeM=
github.com/canonical/go-tpm2 v0.1.0 h1:2mXU+Hy+zYSxmuYys2NtPEO6NwT3Qr9Sygwtops7NYk=
github.com/canonical/go-tpm2 v0.1.0/go.mod h1:vG41hdbBjV4+/fkubTT1ENBBqSkLwLr7mCeW9Y6kpZY=
github.com/canonical/go-tpm2 v1.0.0 h1:g03/robj/c+98Hm2GEkkBnKkkhy0xgFZ7GWE/4HzbwM=
github.com/canonical/go-tpm2 v1.0.0/go.mod h1:zKG2ng7qzxp+siDIa1Scd3h/cXF5Di13Havf5ZwfaVY=
github.com/canonical/tcglog-parser v0.0.0-20230429160108-0d6d239de69d h1:TAe+Vi2UduW6+Ie8SPJROhkCEPo15CLY/gZqrA9viwk=
github.com/canonical/tcglog-parser v0.0.0-20230429160108-0d6d239de69d/go.mod h1:AoJVV7tUwDDGPZkKqwqAMGdPiH7x45JLNmxFrxfoxcs=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
Expand Down Expand Up @@ -222,6 +224,7 @@ github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyex
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mvo5/goconfigparser v0.0.0-20201015074339-50f22f44deb5/go.mod h1:xmt4k1xLDl8Tdan+0S/jmMK2uSUBSzTc18+5GN5Vea8=
github.com/mvo5/goconfigparser v0.0.0-20221018104758-434073381f37/go.mod h1:inxjKzuGbpMDmdoI7kogueqBVRdf6fPAG5dAsU3gu60=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
Expand Down Expand Up @@ -260,6 +263,7 @@ github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4S
github.com/snapcore/go-gettext v0.0.0-20191107141714-82bbea49e785 h1:PaunR+BhraKSLxt2awQ42zofkP+NKh/VjQ0PjIMk/y4=
github.com/snapcore/go-gettext v0.0.0-20191107141714-82bbea49e785/go.mod h1:D3SsWAXK7wCCBZu+Vk5hc1EuKj/L3XN1puEMXTU4LrQ=
github.com/snapcore/secboot v0.0.0-20211207204151-239d06c34009/go.mod h1:72paVOkm4sJugXt+v9ItmnjXgO921D8xqsbH2OekouY=
github.com/snapcore/secboot v0.0.0-20221114180054-b4be60e68879/go.mod h1:72paVOkm4sJugXt+v9ItmnjXgO921D8xqsbH2OekouY=
github.com/snapcore/snapd v0.0.0-20201005140838-501d14ac146e h1:vqDZWKPBL9RKPA8KyOuTaSuXXlmRwn/ndvOkZaAmLJs=
github.com/snapcore/snapd v0.0.0-20201005140838-501d14ac146e/go.mod h1:3xrn7QDDKymcE5VO2rgWEQ5ZAUGb9htfwlXnoel6Io8=
github.com/snapcore/squashfuse v0.0.0-20171220165323-319f6d41a041/go.mod h1:8loYitFPSdoeCXBs/XjO0fyGcpgLAybOHLUsGwgMq90=
Expand Down
131 changes: 75 additions & 56 deletions pkg/trust/tpmpolicy.go
Original file line number Diff line number Diff line change
@@ -1,85 +1,104 @@
package trust

import (
"path/filepath"

"github.com/pkg/errors"
"github.com/urfave/cli"
"os"
"errors"

"github.com/canonical/go-tpm2"
"github.com/canonical/go-tpm2/util"
)

type PolicyData struct {
Pcr7Prod string
Pcr7Tpm string
LuksOutFile string
TpmpassOutFile string
PolicyVersion string
}

// genLuksPolicy creates a policy for reading the LUKS password
// while booted under a production key.
func genLuksPolicy(ctx *cli.Context) error {
workd, err := os.MkdirTemp("", "lukspol")
func genLuksPolicy(keysetName string, pData PolicyData) error {
// Read the uki-production pcr7 value.
luksPcr7, err := os.ReadFile(pData.Pcr7Prod)
if err != nil {
return errors.Wrapf(err, "Error creating tempdir")
}
defer os.RemoveAll(workd)

sessName := filepath.Join(workd, "tpm_session_b")

if err := RunCommand("tpm2_startauthsession", "-S", sessName); err != nil {
return errors.Wrapf(err, "Failed creating auth session");
return err
}
defer RunCommand("tpm2_flushcontext", sessName)

cmd := []string{
"tpm2_policypcr",
"-S", sessName,
"-l", "sha256:7",
"-f", ctx.String("passwd-pcr7-file"),
// Put the pcr7 value in a tpm2.PCRSValues structure so we can compute its digest.
values := make(tpm2.PCRValues)
err = values.SetValue(tpm2.HashAlgorithmSHA256, 7, luksPcr7)
if err != nil {
return err
}
if err := RunCommand(cmd...); err != nil {
return errors.Wrapf(err, "Failed running policypcr")
pcrDigest, err := util.ComputePCRDigest(tpm2.HashAlgorithmSHA256, tpm2.PCRSelectionList{{Hash: tpm2.HashAlgorithmSHA256, Select: []int{7}}}, values)
if err != nil {
return err
}

cmd = []string{
"tpm2_policynv", "-i-",
"-S", sessName,
TPM2IndexEAVersion.String(), "eq",
"-L", ctx.String("luks-policy-file"),
}
if err := runWithStdin(PolicyVersion.String(), cmd...); err != nil {
return errors.Wrapf(err, "Failed running policynv")
}
// Create a tpm2.NVPublic structure that resembles what we would have
// done via an nvwrite of the policy version to the index.
// Include TPMA_NV_WRITTEN attribute indicating the index has been written to.
nvpub := tpm2.NVPublic{Index: tpm2.Handle(TPM2IndexEAVersion), NameAlg: tpm2.HashAlgorithmSHA256, Attrs: tpm2.NVTypeOrdinary.WithAttrs(tpm2.AttrNVOwnerWrite|tpm2.AttrNVOwnerRead|tpm2.AttrNVAuthRead|tpm2.AttrNVWritten), Size: 4}

return nil
trial := util.ComputeAuthPolicy(tpm2.HashAlgorithmSHA256)
trial.PolicyPCR(pcrDigest, tpm2.PCRSelectionList{{Hash: tpm2.HashAlgorithmSHA256, Select: []int{7}}})
trial.PolicyNV(nvpub.Name(), []byte(pData.PolicyVersion), 0, tpm2.OpEq)
policyDigest := trial.GetDigest()
return os.WriteFile(pData.LuksOutFile, policyDigest, 0400)
}

func genPasswdPolicy(ctx *cli.Context) error {
workd, err := os.MkdirTemp("", "passpol")
func genPasswdPolicy(keysetName string, pData PolicyData) error {
// Read the uki-tpm pcr7 value.
Pcr7Pwd, err := os.ReadFile(pData.Pcr7Tpm)
if err != nil {
return errors.Wrapf(err, "Error creating tempdir")
return err
}
defer os.RemoveAll(workd)

sessName := filepath.Join(workd, "tpm_session_a")

if err := RunCommand("tpm2_startauthsession", "-S", sessName); err != nil {
return errors.Wrapf(err, "Failed creating auth session");
// Put the pcr7 value in a tpm2.PCRSValues structure so we can compute its digest.
values := make(tpm2.PCRValues)
err = values.SetValue(tpm2.HashAlgorithmSHA256, 7, Pcr7Pwd)
if err != nil {
return err
}
pcrDigest, err := util.ComputePCRDigest(tpm2.HashAlgorithmSHA256, tpm2.PCRSelectionList{{Hash: tpm2.HashAlgorithmSHA256, Select: []int{7}}}, values)
if err != nil {
return err
}
defer RunCommand("tpm2_flushcontext", sessName)

cmd := []string{
"tpm2_policypcr",
"-S", sessName,
"-l", "sha256:7",
"-f", ctx.String("passwd-pcr7-file"),
"-L", ctx.String("passwd-policy-file"),
// Use a "trial" session to compute the policy digest.
trial := util.ComputeAuthPolicy(tpm2.HashAlgorithmSHA256)
trial.PolicyPCR(pcrDigest, tpm2.PCRSelectionList{{Hash: tpm2.HashAlgorithmSHA256, Select: []int{7}}})
policyDigest := trial.GetDigest()
return os.WriteFile(pData.TpmpassOutFile, policyDigest, 0400)
}

func TpmGenPolicy(keysetName string, pData PolicyData) error {
// Check inputs
if keysetName == "" {
return errors.New("Missing keyset name")
}
if err := RunCommand(cmd...); err != nil {
return errors.Wrapf(err, "Failed running policypcr")
if pData.Pcr7Prod == "" || pData.Pcr7Tpm == "" || pData.LuksOutFile == "" || pData.TpmpassOutFile == "" {
return errors.New("Missing either a pcr7 value or an output file")
}

return nil
}
// Check inputs:
// Policy Version if given must be 4 digits. Otherwise use a default of "0001".
if pData.PolicyVersion == "" {
pData.PolicyVersion = PolicyVersion.String()
} else {
if len(pData.PolicyVersion) != 4 {
return errors.New("Policy version should be a four digit string. i.e. 0001")
}
for _, c := range pData.PolicyVersion {
if c < '0' || c > '9' {
return errors.New("Policy version should be a four digit string. i.e. 0001")
}
}
}

func TpmGenPolicy(ctx *cli.Context) error {
if err := genLuksPolicy(ctx); err != nil {
if err := genLuksPolicy(keysetName, pData); err != nil {
return err
}
if err := genPasswdPolicy(ctx); err != nil {
if err := genPasswdPolicy(keysetName, pData); err != nil {
return err
}
return nil
Expand Down

0 comments on commit 1e37e28

Please sign in to comment.