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

Generate tpm policies use go-tpm2 package. #52

Merged
merged 1 commit into from
Jul 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 26 additions & 25 deletions cmd/trust/policygen.go
Original file line number Diff line number Diff line change
@@ -1,54 +1,55 @@
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,
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",
},
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-tpm",
Usage: "File from which to read uki-tpm pcr7 value",
},
cli.StringFlag{
Name: "pk,passwd-pubkey-file",
Usage: "File from which to read password policy pubkey",
Value: "passwd_pubkey.pem",
Name: "pcr7-production",
Usage: "File from which to read uki-production pcr7 value",
},
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) != 0 {
return errors.New("Usage: extra arguments")
}

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

return trust.TpmGenPolicy(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: 77 additions & 54 deletions pkg/trust/tpmpolicy.go
Original file line number Diff line number Diff line change
@@ -1,85 +1,108 @@
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
PasswdOutFile 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(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(pData PolicyData) error {
// Read the uki-tpm pcr7 value.
Pcr7Pwd, err := os.ReadFile(pData.Pcr7Tpm)
if err != nil {
return err
}
// 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 errors.Wrapf(err, "Error creating tempdir")
return err
}
defer os.RemoveAll(workd)

sessName := filepath.Join(workd, "tpm_session_a")
// 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.PasswdOutFile, policyDigest, 0400)
}

if err := RunCommand("tpm2_startauthsession", "-S", sessName); err != nil {
return errors.Wrapf(err, "Failed creating auth session");
func TpmGenPolicy(pData PolicyData) error {
// Check inputs
if pData.Pcr7Prod == "" || pData.Pcr7Tpm == "" {
return errors.New("Missing pcr7 value(s).")
}
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"),
if pData.LuksOutFile == "" {
pData.LuksOutFile = "luks_policy.out"
}
if err := RunCommand(cmd...); err != nil {
return errors.Wrapf(err, "Failed running policypcr")

if pData.PasswdOutFile == "" {
pData.PasswdOutFile = "passwd_policy.out"
}

return nil
}
// 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(pData); err != nil {
return err
}
if err := genPasswdPolicy(ctx); err != nil {
if err := genPasswdPolicy(pData); err != nil {
return err
}
return nil
Expand Down
Loading