From f464673307596d9cea6207ac8877c06daa52cbfc Mon Sep 17 00:00:00 2001 From: Joy Latten Date: Tue, 18 Jul 2023 15:43:39 -0500 Subject: [PATCH] Add subcommand "computePCR7" to compute pcr7 for a keyset This subcommand takes the keysetName as an argument. It computes the expected pcr7 value based on expected order of tpm events that occur during a secureboot boot. Expected uefi secureboot variables, including key databases, and certificates known to extend into pcr7 during boot are generated according to tpm specs using the specified keyset and measured to produce expected pcr7 value. Should additional drivers and uefi programs be added to the boot, then this implementation would need to be revisited to include those certificates that would be extended into pcr7. The DBX hash and guid is hardcoded from the DBX value in current ovmf_vars.fd from bootkit. Should this change or when we decide how to manage DBX, this code will need to be revisited. Because the mos shim includes 3 uki keys, "computePCR7" returns 3 pcr7 values, one for each key in the order, pcr7 value, for production, limited, tpm. Signed-off-by: Joy Latten --- cmd/trust/computepcr.go | 273 ++++++++++++++++++++++++++++++++++++++++ cmd/trust/main.go | 1 + go.mod | 14 ++- go.sum | 44 +++++-- 4 files changed, 315 insertions(+), 17 deletions(-) create mode 100644 cmd/trust/computepcr.go diff --git a/cmd/trust/computepcr.go b/cmd/trust/computepcr.go new file mode 100644 index 0000000..cd405fb --- /dev/null +++ b/cmd/trust/computepcr.go @@ -0,0 +1,273 @@ +package main + +import ( + "bytes" + "crypto" + "encoding/hex" + "encoding/pem" + "errors" + "fmt" + "os" + "path/filepath" + "strings" + + "github.com/canonical/go-efilib" + "github.com/canonical/tcglog-parser" + "github.com/urfave/cli" +) + +const ShimLockGUID = "605dab50-e046-4300-abb6-3dd810dd8b23" +const vendordbGUID = "00000000-0000-0000-0000-000000000000" +const SBAT = "sbat,1,2021030218\012" +// Using DBX data from current ovmf_vars.fd in bootkit. +// Revisit if ovmf or dbx changes. We need to eventually manage dbx. +const DBX = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" +const DBXGuid = "a3a8baa01d04a848bc87c36d121b5e3d" + +var computePCR7Cmd = cli.Command{ + Name: "computePCR7", + Usage: "Compute PCR7 value for a given keyset", + ArgsUsage: "", + Action: doComputePCR7, +} + +func doComputePCR7(ctx *cli.Context) error { + args := ctx.Args() + if len(args) != 1 { + return errors.New("Required argument: keysetName") + } + keysetName := args[0] + if keysetName == "" { + return errors.New("Please specify a keyset name") + } + pcr7prod, pcr7lim, pcr7tpm, err := computepcr7(keysetName) + if err != nil { + return fmt.Errorf("Failed to generate pcr7 values for %s keyset: (%w)\n", keysetName, err) + } + fmt.Printf("uki-production: %x\nuki-limited: %x\nuki-tpm: %x\n", pcr7prod, pcr7lim, pcr7tpm) + + return nil +} + +type efiVarInfo struct { + varguid efi.GUID + hashed []byte +} + +func getCert(certfile string) ([]byte, error) { + // read cert data from certfile and put in DER + certData, err := os.ReadFile(certfile) + if err != nil { + return nil, fmt.Errorf("Failed to read %q: (%w)", certfile, err) + } + + block, _ := pem.Decode(certData) + if block == nil { + return nil, errors.New("failed to pem.Decode cert") + } + return block.Bytes, nil +} + +func getCertGUID(guidfile string) (efi.GUID, error) { + // Read and decode the guid for the cert + cGuid, err := os.ReadFile(guidfile) + if err != nil { + return efi.GUID{}, fmt.Errorf("Failed to read %q: (%w)", guidfile, err) + } + certGuid, err := efi.DecodeGUIDString(string(cGuid)) + if err != nil { + return efi.GUID{}, fmt.Errorf("Failed to decode the guid in %q: (%w)", guidfile, err) + } + + return certGuid, nil +} + +func createSigData(unicodeName string, varGUID efi.GUID, certfile, guidfile string) ([]byte, error) { + // Read cert.pem and guid + certBytes, err := getCert(certfile) + if err != nil { + return nil, err + } + certGuid, err := getCertGUID(guidfile) + if err != nil { + return nil, err + } + + // Create SignatureData + sd := efi.SignatureData{Owner: certGuid, Data: certBytes} + var b bytes.Buffer + sd.Write(&b) + return tcglog.ComputeEFIVariableDataDigest(crypto.SHA256, unicodeName, varGUID, b.Bytes()), nil +} + +func createESLfromCert(unicodeName string, varGUID efi.GUID, certfile, guidfile string) ([]byte, error) { + // Read cert.pem and guid + certBytes, err := getCert(certfile) + if err != nil { + return nil, err + } + certGuid, err := getCertGUID(guidfile) + if err != nil { + return nil, err + } + + // create a SignatureList + sl := efi.SignatureList{Type: efi.CertX509Guid, Header: []byte{}} + sl.Signatures = append(sl.Signatures, &efi.SignatureData{Owner: certGuid, Data: certBytes}) + + var b bytes.Buffer + sl.Write(&b) + return tcglog.ComputeEFIVariableDataDigest(crypto.SHA256, unicodeName, varGUID, b.Bytes()), nil +} + +func createESLfromHash(unicodeName string, varGUID efi.GUID, hdata []byte, hguid efi.GUID) ([]byte, error) { + sl := efi.SignatureList{Type: efi.CertSHA256Guid, Header: []byte{}} + sl.Signatures = append(sl.Signatures, &efi.SignatureData{Owner: hguid, Data: hdata}) + var b bytes.Buffer + sl.Write(&b) + return tcglog.ComputeEFIVariableDataDigest(crypto.SHA256, unicodeName, varGUID, b.Bytes()), nil +} + +func getHash(unicodeName string, varGuid efi.GUID, keysetPath string) ([]byte, error) { + + switch unicodeName { + case "SecureBoot", "MokListTrusted": + efiData := []byte{1} + return tcglog.ComputeEFIVariableDataDigest(crypto.SHA256, unicodeName, varGuid, efiData), nil + + case "SbatLevel": + return tcglog.ComputeEFIVariableDataDigest(crypto.SHA256, unicodeName, varGuid, []byte(SBAT)), nil + + case "PK", "KEK", "db": + dir := strings.ToLower(unicodeName) + certfile := filepath.Join(keysetPath, "uefi-"+dir+"/cert.pem") + guidfile := filepath.Join(keysetPath, "uefi-"+dir+"/guid") + + hashed, err := createESLfromCert(unicodeName, varGuid, certfile, guidfile) + if err != nil { + return nil, err + } + return hashed, nil + + case "dbx": + hdata, err := hex.DecodeString(DBX) + if err != nil { + return nil, err + } + + guiddata, err := hex.DecodeString(DBXGuid) + if err != nil { + return nil, fmt.Errorf("Failed to decode the dbx guid: (%w)", err) + } + + r := bytes.NewReader(guiddata) + hguid, err := efi.ReadGUID(r) + if err != nil { + return nil, err + } + + hashed, err := createESLfromHash(unicodeName, varGuid, hdata, hguid) + if err != nil { + return nil, err + } + return hashed, nil + + case "separator": + return tcglog.ComputeSeparatorEventDigest(crypto.SHA256, tcglog.SeparatorEventNormalValue), nil + + case "shim-cert": + certfile := filepath.Join(keysetPath, "uefi-db/cert.pem") + guidfile := filepath.Join(keysetPath, "uefi-db/guid") + hashed, err := createSigData("db", varGuid, certfile, guidfile) + if err != nil { + return nil, err + } + return hashed, nil + + case "production", "tpm", "limited": + certfile := filepath.Join(keysetPath, "uki-"+unicodeName, "cert.pem") + certBytes, err := getCert(certfile) + if err != nil { + return nil, err + } + + certGuid, err := efi.DecodeGUIDString(vendordbGUID) + if err != nil { + return nil, err + } + + // Create SignatureData + sd := efi.SignatureData{Owner: certGuid, Data: certBytes} + var b bytes.Buffer + sd.Write(&b) + return tcglog.ComputeEFIVariableDataDigest(crypto.SHA256, "vendor_db", varGuid, b.Bytes()), nil + + default: + return nil, nil + } +} + +func computepcr7(keysetName string) ([]byte, []byte, []byte, error) { + var pcr7Val = []byte{00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00} + + // List of uefi Secure boot vars that get measured. + // It includes certs that get measured at boot. UKI certs are measured + // separately since we have 3 possible. Also measured in this order. + var uefiMeasured = []string{"SecureBoot", "PK", "KEK", "db", "dbx", "separator", "shim-cert", "SbatLevel", "MokListTrusted" } + + shimLockGuid, err := efi.DecodeGUIDString(ShimLockGUID) + if err != nil { + return nil, nil, nil, err + } + var efiSBInfo = map[string]*efiVarInfo{ + "SecureBoot": {efi.GlobalVariable, nil}, + "PK": {efi.GlobalVariable, nil}, + "KEK": {efi.GlobalVariable, nil}, + "db": {efi.ImageSecurityDatabaseGuid, nil}, + "dbx": {efi.ImageSecurityDatabaseGuid, nil}, + "separator": {hashed: nil}, + "shim-cert": {efi.ImageSecurityDatabaseGuid, nil}, + "SbatLevel": {shimLockGuid, nil}, + "MokListTrusted": {shimLockGuid, nil}, + } + + // List of UKI certs that can get measured. + // The value will be the resulting pcr7 value when the cert is extended. + var ukiKeys = map[string][]byte{"production": nil, "limited": nil, "tpm": nil} + + moskeysetPath, err := getMosKeyPath() + if err != nil { + return nil, nil, nil, err + } + + keysetPath := filepath.Join(moskeysetPath, keysetName) + if !PathExists(keysetPath) { + return nil, nil, nil, fmt.Errorf("Unknown keyset '%s', cannot find keyset at path: %q", keysetName, keysetPath) + } + + // First calculate the uefi vars and certs in order they are extended into pcr7. + for _, k := range uefiMeasured { + efiSBInfo[k].hashed, err = getHash(k, efiSBInfo[k].varguid, keysetPath) + if err != nil { + return nil, nil, nil, err + } + h := crypto.SHA256.New() + h.Write(pcr7Val) + h.Write(efiSBInfo[k].hashed) + pcr7Val = h.Sum(nil) + } + + // Now extend in the 3 different possible uki signing keys. + // This will result in 3 different pcr7 values, one for each possible uki key. + for uki, _ := range ukiKeys { + ukiHash, err := getHash(uki, efi.ImageSecurityDatabaseGuid, keysetPath) + if err != nil { + return nil, nil, nil, err + } + h := crypto.SHA256.New() + h.Write(pcr7Val) + h.Write(ukiHash) + ukiKeys[uki] = h.Sum(nil) + } + return ukiKeys["production"], ukiKeys["limited"], ukiKeys["tpm"], nil +} diff --git a/cmd/trust/main.go b/cmd/trust/main.go index ff6c006..f242a0e 100644 --- a/cmd/trust/main.go +++ b/cmd/trust/main.go @@ -26,6 +26,7 @@ func main() { provisionCmd, tpmPolicyGenCmd, extendPCR7Cmd, + computePCR7Cmd, // keyset keysetCmd, diff --git a/go.mod b/go.mod index 9ca33ce..bc3f89d 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,8 @@ module github.com/project-machine/trust require ( github.com/anuvu/disko v0.0.11 github.com/apex/log v1.9.0 - github.com/canonical/go-tpm2 v0.0.0-20220823192114-7a7993f0fa1f + github.com/canonical/go-efilib v0.9.4 + 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 github.com/go-git/go-git/v5 v5.4.2 @@ -17,6 +18,7 @@ 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 @@ -33,19 +35,19 @@ require ( github.com/sergi/go-diff v1.1.0 // indirect github.com/spf13/afero v1.9.3 // indirect github.com/xanzy/ssh-agent v0.3.0 // indirect - golang.org/x/crypto v0.6.0 // indirect - golang.org/x/net v0.6.0 // indirect - golang.org/x/text v0.7.0 // indirect + golang.org/x/crypto v0.9.0 // indirect + golang.org/x/net v0.10.0 // indirect + golang.org/x/text v0.9.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect ) require ( - github.com/canonical/go-sp800.108-kdf v0.0.0-20210314145419-a3359f2d21b9 // indirect + github.com/canonical/go-sp800.108-kdf v0.0.0-20210315104021-ead800bbf9a0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect github.com/jsipprell/keyctl v1.0.4 github.com/russross/blackfriday/v2 v2.0.1 // indirect github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect - golang.org/x/sys v0.6.0 // indirect + golang.org/x/sys v0.8.0 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect ) diff --git a/go.sum b/go.sum index efb9cd5..ec4c0d4 100644 --- a/go.sum +++ b/go.sum @@ -58,10 +58,18 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= 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/canonical/go-sp800.108-kdf v0.0.0-20210314145419-a3359f2d21b9 h1:USzKjrfWo/ESzozv2i3OMM7XDgxrZRvaHFrKkIKRtwU= +github.com/bsiegert/ranges v0.0.0-20111221115336-19303dc7aa63/go.mod h1:8z71/aZjDHLs4ihK/5nD5wZVQxm/W4eRDnxQZcJmVD4= +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-tpm2 v0.0.0-20220823192114-7a7993f0fa1f h1:gTa91oCtyAWRWlXVsD8XfpEF3toAlpAXjKmxWFGmMHo= -github.com/canonical/go-tpm2 v0.0.0-20220823192114-7a7993f0fa1f/go.mod h1:vG41hdbBjV4+/fkubTT1ENBBqSkLwLr7mCeW9Y6kpZY= +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/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= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= @@ -70,6 +78,7 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -106,6 +115,7 @@ github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -165,6 +175,7 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/hallyn/keyctl v1.0.4-0.20211206210026-67b989e45620 h1:oj7YhbaGdd6o3u+pld/dy3ig/Vr9MpPddxDrbCY/ocE= github.com/hallyn/keyctl v1.0.4-0.20211206210026-67b989e45620/go.mod h1:Oehu2vePSY7daRvgeCQZ1QdS2B4CbcTLCbu2W1rCmaU= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -210,6 +221,7 @@ github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= 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/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= @@ -247,8 +259,10 @@ github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9 github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4SauJk4cUOwJs= 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/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= github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk= github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -277,6 +291,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 h1:A/5uWzF44DlIgdm/PQFwfMkW0JX+cIcQi/SwLAmZP5M= +go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -293,8 +308,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= -golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -362,8 +377,8 @@ golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= -golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -424,18 +439,20 @@ golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -490,6 +507,7 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= @@ -583,18 +601,22 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637 h1:yiW+nvdHb9LVqSHQBXfZCieqV4fzYhNBql77zY0ykqs= gopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637/go.mod h1:BHsqpu/nsuzkT5BpiH1EMZPLyqSMM8JbIavyFACoFNk= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c h1:grhR+C34yXImVGp7EzNk+DTIk+323eIUWOmEevy6bDo= gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=