diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 876de83b..76caa79b 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -10,9 +10,9 @@ jobs: steps: - uses: actions/setup-go@v3 with: - go-version: 1.19.3 + go-version: 1.20.x - uses: actions/checkout@v3 - name: golangci-lint uses: golangci/golangci-lint-action@v3 with: - version: v1.50.1 + version: v1.53.3 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1aafe884..7a7a986f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,7 +13,7 @@ jobs: test-linux: strategy: matrix: - go-version: [1.16.x, 1.17.x, 1.18.x] + go-version: [1.20.x] runs-on: ubuntu-latest steps: - name: Install Go @@ -27,7 +27,7 @@ jobs: test-linux-tpm12: strategy: matrix: - go-version: [1.16.x, 1.17.x, 1.18.x] + go-version: [1.20.x] runs-on: ubuntu-latest steps: - name: Install Go @@ -43,7 +43,7 @@ jobs: test-macos: strategy: matrix: - go-version: [1.16.x, 1.17.x, 1.18.x] + go-version: [1.20.x] runs-on: macos-latest steps: - name: Install Go @@ -53,16 +53,12 @@ jobs: - name: Checkout code uses: actions/checkout@v2 # See https://github.com/google/go-tpm-tools#macos-dev - - name: Install openssl - run: brew install openssl@1.1 - - name: Link openssl - run: sudo ln -s $(brew --prefix openssl@1.1)/include/openssl /usr/local/include - name: Test run: C_INCLUDE_PATH="$(brew --prefix openssl@1.1)/include" LIBRARY_PATH="$(brew --prefix openssl@1.1)/lib" go test ./... test-windows: strategy: matrix: - go-version: [1.16.x, 1.17.x, 1.18.x] + go-version: [1.20.x] runs-on: windows-latest steps: - name: Install Go diff --git a/attest/activation.go b/attest/activation.go index 752968ea..0cd884b6 100644 --- a/attest/activation.go +++ b/attest/activation.go @@ -9,11 +9,11 @@ import ( "fmt" "io" + "github.com/google/go-tpm/legacy/tpm2" tpm1 "github.com/google/go-tpm/tpm" - "github.com/google/go-tpm/tpm2" // TODO(jsonp): Move activation generation code to internal package. - "github.com/google/go-tpm/tpm2/credactivation" + "github.com/google/go-tpm/legacy/tpm2/credactivation" "github.com/google/go-tspi/verification" ) diff --git a/attest/application_key.go b/attest/application_key.go index 2ee710d0..71163b8a 100644 --- a/attest/application_key.go +++ b/attest/application_key.go @@ -72,6 +72,10 @@ type KeyConfig struct { // Size is used to specify the bit size of the key or elliptic curve. For // example, '256' is used to specify curve P-256. Size int + // Parent describes the Storage Root Key that will be used as a parent. + // If nil, the default SRK (i.e. RSA with handle 0x81000001) is assumed. + // Supported only by TPM 2.0 on Linux. + Parent *ParentKeyConfig } // defaultConfig is used when no other configuration is specified. diff --git a/attest/attest-tool/attest-tool.go b/attest/attest-tool/attest-tool.go index fa00e88e..2e192fa4 100644 --- a/attest/attest-tool/attest-tool.go +++ b/attest/attest-tool/attest-tool.go @@ -140,7 +140,7 @@ func runCommand(tpm *attest.TPM) error { fmt.Printf("Version: %d\n", info.Version) fmt.Printf("Interface: %d\n", info.Interface) fmt.Printf("VendorInfo: %x\n", info.VendorInfo) - fmt.Printf("Manufactorer: %v\n", info.Manufacturer) + fmt.Printf("Manufacturer: %v\n", info.Manufacturer) case "make-ak", "make-aik": k, err := tpm.NewAK(nil) diff --git a/attest/attest-tool/internal/internal.go b/attest/attest-tool/internal/internal.go index 1bb38c99..3ec8bc32 100644 --- a/attest/attest-tool/internal/internal.go +++ b/attest/attest-tool/internal/internal.go @@ -3,7 +3,7 @@ package internal import ( "github.com/google/go-attestation/attest" - "github.com/google/go-tpm/tpm2" + "github.com/google/go-tpm/legacy/tpm2" ) // Dump describes the layout of serialized information from the dump command. diff --git a/attest/attest.go b/attest/attest.go index c2adb2f4..fb9b6b25 100644 --- a/attest/attest.go +++ b/attest/attest.go @@ -23,8 +23,9 @@ import ( "io" "strings" + "github.com/google/go-tpm/legacy/tpm2" "github.com/google/go-tpm/tpm" - "github.com/google/go-tpm/tpm2" + "github.com/google/go-tpm/tpmutil" ) // TPMVersion is used to configure a preference in @@ -98,11 +99,23 @@ const ( keyEncodingParameterized ) +// ParentKeyConfig describes the Storage Root Key that is used +// as a parent for new keys. +type ParentKeyConfig struct { + Algorithm Algorithm + Handle tpmutil.Handle +} + +var defaultParentConfig = ParentKeyConfig{ + Algorithm: RSA, + Handle: 0x81000001, +} + type ak interface { close(tpmBase) error marshal() ([]byte, error) - activateCredential(tpm tpmBase, in EncryptedCredential) ([]byte, error) - quote(t tpmBase, nonce []byte, alg HashAlg) (*Quote, error) + activateCredential(tpm tpmBase, in EncryptedCredential, ek *EK) ([]byte, error) + quote(t tpmBase, nonce []byte, alg HashAlg, selectedPCRs []int) (*Quote, error) attestationParameters() AttestationParameters certify(tb tpmBase, handle interface{}) (*CertificationParameters, error) } @@ -126,11 +139,22 @@ func (k *AK) Marshal() ([]byte, error) { } // ActivateCredential decrypts the secret using the key to prove that the AK -// was generated on the same TPM as the EK. +// was generated on the same TPM as the EK. This method can be used with TPMs +// that have the default EK, i.e. RSA EK with handle 0x81010001. // // This operation is synonymous with TPM2_ActivateCredential. func (k *AK) ActivateCredential(tpm *TPM, in EncryptedCredential) (secret []byte, err error) { - return k.ak.activateCredential(tpm.tpm, in) + return k.ak.activateCredential(tpm.tpm, in, nil) +} + +// ActivateCredential decrypts the secret using the key to prove that the AK +// was generated on the same TPM as the EK. This method can be used with TPMs +// that have an ECC EK. The 'ek' argument must be one of EKs returned from +// TPM.EKs() or TPM.EKCertificates(). +// +// This operation is synonymous with TPM2_ActivateCredential. +func (k *AK) ActivateCredentialWithEK(tpm *TPM, in EncryptedCredential, ek EK) (secret []byte, err error) { + return k.ak.activateCredential(tpm.tpm, in, &ek) } // Quote returns a quote over the platform state, signed by the AK. @@ -138,7 +162,16 @@ func (k *AK) ActivateCredential(tpm *TPM, in EncryptedCredential) (secret []byte // This is a low-level API. Consumers seeking to attest the state of the // platform should use tpm.AttestPlatform() instead. func (k *AK) Quote(tpm *TPM, nonce []byte, alg HashAlg) (*Quote, error) { - return k.ak.quote(tpm.tpm, nonce, alg) + pcrs := make([]int, 24) + for pcr := range pcrs { + pcrs[pcr] = pcr + } + return k.ak.quote(tpm.tpm, nonce, alg, pcrs) +} + +// QuotePCRs is like Quote() but allows the caller to select a subset of the PCRs. +func (k *AK) QuotePCRs(tpm *TPM, nonce []byte, alg HashAlg, pcrs []int) (*Quote, error) { + return k.ak.quote(tpm.tpm, nonce, alg, pcrs) } // AttestationParameters returns information about the AK, typically used to @@ -155,9 +188,12 @@ func (k *AK) Certify(tpm *TPM, handle interface{}) (*CertificationParameters, er return k.ak.certify(tpm.tpm, handle) } -// AKConfig encapsulates parameters for minting keys. This type is defined -// now (despite being empty) for future interface compatibility. +// AKConfig encapsulates parameters for minting keys. type AKConfig struct { + // Parent describes the Storage Root Key that will be used as a parent. + // If nil, the default SRK (i.e. RSA with handle 0x81000001) is assumed. + // Supported only by TPM 2.0 on Linux. + Parent *ParentKeyConfig } // EncryptedCredential represents encrypted parameters which must be activated @@ -205,6 +241,9 @@ type EK struct { // Public key. Clients or servers can perform an HTTP GET to this URL, and // use ParseEKCertificate on the response body. CertificateURL string + + // The EK persistent handle. + handle tpmutil.Handle } // AttestationParameters describes information about a key which is necessary diff --git a/attest/attest_simulated_tpm20_test.go b/attest/attest_simulated_tpm20_test.go index 1fbb45cb..8ad2c3c6 100644 --- a/attest/attest_simulated_tpm20_test.go +++ b/attest/attest_simulated_tpm20_test.go @@ -98,32 +98,45 @@ func TestSimTPM20AKCreateAndLoad(t *testing.T) { } func TestSimTPM20ActivateCredential(t *testing.T) { + testActivateCredential(t, false) +} + +func TestSimTPM20ActivateCredentialWithEK(t *testing.T) { + testActivateCredential(t, true) +} + +func testActivateCredential(t *testing.T, useEK bool) { sim, tpm := setupSimulatedTPM(t) defer sim.Close() - ak, err := tpm.NewAK(nil) - if err != nil { - t.Fatalf("NewAK() failed: %v", err) - } - defer ak.Close(tpm) - EKs, err := tpm.EKs() if err != nil { t.Fatalf("EKs() failed: %v", err) } ek := chooseEK(t, EKs) + ak, err := tpm.NewAK(nil) + if err != nil { + t.Fatalf("NewAK() failed: %v", err) + } + defer ak.Close(tpm) + ap := ActivationParameters{ TPMVersion: TPMVersion20, AK: ak.AttestationParameters(), - EK: ek, + EK: ek.Public, } secret, challenge, err := ap.Generate() if err != nil { t.Fatalf("Generate() failed: %v", err) } - decryptedSecret, err := ak.ActivateCredential(tpm, *challenge) + var decryptedSecret []byte + if useEK { + decryptedSecret, err = ak.ActivateCredentialWithEK(tpm, *challenge, ek) + } else { + decryptedSecret, err = ak.ActivateCredential(tpm, *challenge) + } if err != nil { t.Errorf("ak.ActivateCredential() failed: %v", err) } @@ -246,24 +259,69 @@ func TestSimTPM20PCRs(t *testing.T) { } } -func TestSimTPM20Persistence(t *testing.T) { +func TestSimTPM20PersistenceSRK(t *testing.T) { + testPersistenceSRK(t, defaultParentConfig) +} + +func TestSimTPM20PersistenceECCSRK(t *testing.T) { + parentConfig := ParentKeyConfig{ + Algorithm: ECDSA, + Handle: 0x81000002, + } + testPersistenceSRK(t, parentConfig) +} + +func testPersistenceSRK(t *testing.T, parentConfig ParentKeyConfig) { sim, tpm := setupSimulatedTPM(t) defer sim.Close() - ekHnd, _, err := tpm.tpm.(*wrappedTPM20).getPrimaryKeyHandle(commonEkEquivalentHandle) + srkHnd, _, err := tpm.tpm.(*wrappedTPM20).getStorageRootKeyHandle(parentConfig) + if err != nil { + t.Fatalf("getStorageRootKeyHandle() failed: %v", err) + } + if srkHnd != parentConfig.Handle { + t.Fatalf("bad SRK-equivalent handle: got 0x%x, wanted 0x%x", srkHnd, parentConfig.Handle) + } + + srkHnd, p, err := tpm.tpm.(*wrappedTPM20).getStorageRootKeyHandle(parentConfig) + if err != nil { + t.Fatalf("second getStorageRootKeyHandle() failed: %v", err) + } + if srkHnd != parentConfig.Handle { + t.Fatalf("bad SRK-equivalent handle: got 0x%x, wanted 0x%x", srkHnd, parentConfig.Handle) + } + if p { + t.Fatalf("generated a new key the second time; that shouldn't happen") + } +} + +func TestSimTPM20PersistenceEK(t *testing.T) { + sim, tpm := setupSimulatedTPM(t) + defer sim.Close() + + eks, err := tpm.EKs() + if err != nil { + t.Errorf("EKs() failed: %v", err) + } + if len(eks) == 0 || (eks[0].Public == nil) { + t.Errorf("EKs() = %v, want at least 1 EK with populated fields", eks) + } + + ek := eks[0] + ekHnd, _, err := tpm.tpm.(*wrappedTPM20).getEndorsementKeyHandle(&ek) if err != nil { - t.Fatalf("getPrimaryKeyHandle() failed: %v", err) + t.Fatalf("getStorageRootKeyHandle() failed: %v", err) } - if ekHnd != commonEkEquivalentHandle { - t.Fatalf("bad EK-equivalent handle: got 0x%x, wanted 0x%x", ekHnd, commonEkEquivalentHandle) + if ekHnd != ek.handle { + t.Fatalf("bad EK-equivalent handle: got 0x%x, wanted 0x%x", ekHnd, ek.handle) } - ekHnd, p, err := tpm.tpm.(*wrappedTPM20).getPrimaryKeyHandle(commonEkEquivalentHandle) + ekHnd, p, err := tpm.tpm.(*wrappedTPM20).getEndorsementKeyHandle(&ek) if err != nil { - t.Fatalf("second getPrimaryKeyHandle() failed: %v", err) + t.Fatalf("second getEndorsementKeyHandle() failed: %v", err) } - if ekHnd != commonEkEquivalentHandle { - t.Fatalf("bad EK-equivalent handle: got 0x%x, wanted 0x%x", ekHnd, commonEkEquivalentHandle) + if ekHnd != ek.handle { + t.Fatalf("bad EK-equivalent handle: got 0x%x, wanted 0x%x", ekHnd, ek.handle) } if p { t.Fatalf("generated a new key the second time; that shouldn't happen") diff --git a/attest/attest_test.go b/attest/attest_test.go index 8a2b812e..2d7a2fb9 100644 --- a/attest/attest_test.go +++ b/attest/attest_test.go @@ -16,7 +16,6 @@ package attest import ( "bytes" - "crypto" "flag" "fmt" "reflect" @@ -119,16 +118,16 @@ func TestAKCreateAndLoad(t *testing.T) { } } -// chooseEK selects the EK public which will be activated against. -func chooseEK(t *testing.T, eks []EK) crypto.PublicKey { +// chooseEK selects the EK which will be activated against. +func chooseEK(t *testing.T, eks []EK) EK { t.Helper() for _, ek := range eks { - return ek.Public + return ek } t.Fatalf("No suitable EK found") - return nil + return EK{} } func TestPCRs(t *testing.T) { diff --git a/attest/attest_tpm12_test.go b/attest/attest_tpm12_test.go index 7acd1723..627de331 100644 --- a/attest/attest_tpm12_test.go +++ b/attest/attest_tpm12_test.go @@ -151,7 +151,7 @@ func TestTPMActivateCredential(t *testing.T) { ap := ActivationParameters{ TPMVersion: TPMVersion12, AK: ak.AttestationParameters(), - EK: ek, + EK: ek.Public, } secret, challenge, err := ap.Generate() if err != nil { diff --git a/attest/certification.go b/attest/certification.go index 372da046..809fac67 100644 --- a/attest/certification.go +++ b/attest/certification.go @@ -17,12 +17,14 @@ package attest import ( "bytes" "crypto" + "crypto/rand" "crypto/rsa" "errors" "fmt" "io" - "github.com/google/go-tpm/tpm2" + "github.com/google/go-tpm/legacy/tpm2" + "github.com/google/go-tpm/legacy/tpm2/credactivation" "github.com/google/go-tpm/tpmutil" ) @@ -62,6 +64,38 @@ type VerifyOpts struct { Hash crypto.Hash } +// ActivateOpts specifies options for the key certification's challenge generation. +type ActivateOpts struct { + // EK, the endorsement key, describes an asymmetric key whose + // private key is permanently bound to the TPM. + // + // Activation will verify that the provided EK is held on the same + // TPM as the key we're certifying. However, it is the caller's responsibility to + // ensure the EK they provide corresponds to the the device which + // they are trying to associate the certified key with. + EK crypto.PublicKey + // VerifierKeyNameDigest is the name digest of the public key we're using to + // verify the certification of the tpm-generated key being activated. + // The verifier key (usually the AK) that owns this digest should be the same + // key used in VerifyOpts.Public. + // Use tpm2.Public.Name() to produce the digest for a provided key. + VerifierKeyNameDigest *tpm2.HashValue +} + +// NewActivateOpts creates options for use in generating an activation challenge for a certified key. +// The computed hash is the name digest of the public key used to verify the certification of our key. +func NewActivateOpts(verifierPubKey tpm2.Public, ek crypto.PublicKey) (*ActivateOpts, error) { + pubName, err := verifierPubKey.Name() + if err != nil { + return nil, fmt.Errorf("unable to resolve a tpm2.Public Name struct from the given public key struct: %v", err) + } + + return &ActivateOpts{ + EK: ek, + VerifierKeyNameDigest: pubName.Digest, + }, nil +} + // Verify verifies the TPM2-produced certification parameters checking whether: // - the key length is secure // - the attestation parameters matched the attested key @@ -157,6 +191,51 @@ func (p *CertificationParameters) Verify(opts VerifyOpts) error { return nil } +// Generate returns a credential activation challenge, which can be provided +// to the TPM to verify the AK parameters given are authentic & the AK +// is present on the same TPM as the EK. +// +// The caller is expected to verify the secret returned from the TPM as +// as result of calling ActivateCredential() matches the secret returned here. +// The caller should use subtle.ConstantTimeCompare to avoid potential +// timing attack vectors. +func (p *CertificationParameters) Generate(rnd io.Reader, verifyOpts VerifyOpts, activateOpts ActivateOpts) (secret []byte, ec *EncryptedCredential, err error) { + if err := p.Verify(verifyOpts); err != nil { + return nil, nil, err + } + + if activateOpts.EK == nil { + return nil, nil, errors.New("no EK provided") + } + + secret = make([]byte, activationSecretLen) + if rnd == nil { + rnd = rand.Reader + } + if _, err = io.ReadFull(rnd, secret); err != nil { + return nil, nil, fmt.Errorf("error generating activation secret: %v", err) + } + + att, err := tpm2.DecodeAttestationData(p.CreateAttestation) + if err != nil { + return nil, nil, fmt.Errorf("DecodeAttestationData() failed: %v", err) + } + + if att.Type != tpm2.TagAttestCertify { + return nil, nil, fmt.Errorf("attestation does not apply to certify data, got %x", att.Type) + } + + cred, encSecret, err := credactivation.Generate(activateOpts.VerifierKeyNameDigest, activateOpts.EK, symBlockSize, secret) + if err != nil { + return nil, nil, fmt.Errorf("credactivation.Generate() failed: %v", err) + } + + return secret, &EncryptedCredential{ + Credential: cred, + Secret: encSecret, + }, nil +} + // certify uses AK's handle and the passed signature scheme to certify the key // with the `hnd` handle. func certify(tpm io.ReadWriteCloser, hnd, akHnd tpmutil.Handle, scheme tpm2.SigScheme) (*CertificationParameters, error) { diff --git a/attest/certification_test.go b/attest/certification_test.go index 8006eeac..d1c8acfc 100644 --- a/attest/certification_test.go +++ b/attest/certification_test.go @@ -20,6 +20,7 @@ package attest import ( + "bytes" "crypto" "crypto/rand" "crypto/rsa" @@ -27,7 +28,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - "github.com/google/go-tpm/tpm2" + "github.com/google/go-tpm/legacy/tpm2" ) func TestSimTPM20CertificationParameters(t *testing.T) { @@ -274,3 +275,125 @@ func testKeyCertification(t *testing.T, tpm *TPM) { }) } } + +func TestKeyActivationTPM20(t *testing.T) { + sim, tpm := setupSimulatedTPM(t) + defer sim.Close() + + ak, err := tpm.NewAK(nil) + if err != nil { + t.Fatalf("error creating a new AK using simulated TPM: %v", err) + } + akAttestParams := ak.AttestationParameters() + pub, err := tpm2.DecodePublic(akAttestParams.Public) + if err != nil { + t.Fatalf("unable to decode public struct from AK attestation params: %v", err) + } + if pub.Type != tpm2.AlgRSA { + t.Fatal("non-RSA verifying key") + } + + eks, err := tpm.EKs() + if err != nil { + t.Fatalf("unexpected error retrieving EK from tpm: %v", err) + } + + if len(eks) == 0 { + t.Fatal("expected at least one EK from the simulated TPM") + } + + pk := &rsa.PublicKey{E: int(pub.RSAParameters.Exponent()), N: pub.RSAParameters.Modulus()} + hash, err := pub.RSAParameters.Sign.Hash.Hash() + if err != nil { + t.Fatalf("unable to compute hash signature from verifying key's RSA parameters: %v", err) + } + verifyOpts := VerifyOpts{ + Public: pk, + Hash: hash, + } + + sk, err := tpm.NewKey(ak, nil) + if err != nil { + t.Fatalf("unable to create a new TPM-backed key to certify: %v", err) + } + + skCertParams := sk.CertificationParameters() + activateOpts, err := NewActivateOpts(pub, eks[0].Public) + if err != nil { + t.Fatalf("unable to create new ActivateOpts: %v", err) + } + + wrongPub, err := tpm2.DecodePublic(skCertParams.Public) + if err != nil { + t.Fatalf("unable to decode public struct from CertificationParameters: %v", err) + } + + wrongActivateOpts, err := NewActivateOpts(wrongPub, eks[0].Public) + if err != nil { + t.Fatalf("unable to create wrong ActivateOpts: %v", err) + } + + for _, test := range []struct { + name string + p *CertificationParameters + verifyOpts VerifyOpts + activateOpts ActivateOpts + generateErr error + activateErr error + }{ + { + name: "OK", + p: &skCertParams, + verifyOpts: verifyOpts, + activateOpts: *activateOpts, + generateErr: nil, + activateErr: nil, + }, + { + name: "invalid verify opts", + p: &skCertParams, + verifyOpts: VerifyOpts{}, + activateOpts: *activateOpts, + generateErr: cmpopts.AnyError, + activateErr: nil, + }, + { + name: "invalid activate opts", + p: &skCertParams, + verifyOpts: verifyOpts, + activateOpts: *wrongActivateOpts, + generateErr: nil, + activateErr: cmpopts.AnyError, + }, + } { + t.Run(test.name, func(t *testing.T) { + expectedSecret, encryptedCredentials, err := test.p.Generate(rand.Reader, test.verifyOpts, test.activateOpts) + if test.generateErr != nil { + if got, want := err, test.generateErr; !cmp.Equal(got, want, cmpopts.EquateErrors()) { + t.Errorf("p.Generate() err = %v, want = %v", got, want) + } + + return + } else if err != nil { + t.Errorf("unexpected p.Generate() error: %v", err) + return + } + + actualSecret, err := ak.ActivateCredential(tpm, *encryptedCredentials) + if test.activateErr != nil { + if got, want := err, test.activateErr; !cmp.Equal(got, want, cmpopts.EquateErrors()) { + t.Errorf("p.ActivateCredential() err = %v, want = %v", got, want) + } + + return + } else if err != nil { + t.Errorf("unexpected p.ActivateCredential() error: %v", err) + return + } + + if !bytes.Equal(expectedSecret, actualSecret) { + t.Fatalf("Unexpected bytes decoded, expected %x, but got %x", expectedSecret, actualSecret) + } + }) + } +} diff --git a/attest/eventlog.go b/attest/eventlog.go index 766a96fd..6cc7de8a 100644 --- a/attest/eventlog.go +++ b/attest/eventlog.go @@ -30,7 +30,7 @@ import ( // Ensure hashes are available. _ "crypto/sha256" - "github.com/google/go-tpm/tpm2" + "github.com/google/go-tpm/legacy/tpm2" "github.com/google/go-tpm/tpmutil" ) diff --git a/attest/eventlog_test.go b/attest/eventlog_test.go index 4d2c9a1c..36e5d78a 100644 --- a/attest/eventlog_test.go +++ b/attest/eventlog_test.go @@ -21,7 +21,7 @@ import ( "os" "testing" - "github.com/google/go-tpm/tpm2" + "github.com/google/go-tpm/legacy/tpm2" ) // Dump describes the layout of serialized information from the dump command. diff --git a/attest/example_test.go b/attest/example_test.go index 057a2370..5a8263ad 100644 --- a/attest/example_test.go +++ b/attest/example_test.go @@ -91,12 +91,62 @@ func ExampleAK_credentialActivation() { } } +func ExampleAK_credentialActivationWithEK() { + tpm, err := attest.OpenTPM(nil) + if err != nil { + log.Fatalf("Failed to open TPM: %v", err) + } + defer tpm.Close() + + // Create a new AK. + ak, err := tpm.NewAK(nil) + if err != nil { + log.Fatalf("Failed to create AK: %v", err) + } + defer ak.Close(tpm) + + // Read the EK certificates. + ekCerts, err := tpm.EKCertificates() + if err != nil { + log.Fatalf("Failed to enumerate EKs: %v", err) + } + + // Read parameters necessary to generate a challenge. + ap := ak.AttestationParameters() + + // Try activating with each EK certificate. + for _, ek := range ekCerts { + // Generate a credential activation challenge (usually done on the server). + activation := attest.ActivationParameters{ + TPMVersion: tpm.Version(), + EK: ek.Public, + AK: ap, + } + secret, challenge, err := activation.Generate() + if err != nil { + log.Fatalf("Failed to generate activation challenge: %v", err) + } + + // Challenge the AK & EK properties to recieve the decrypted secret. + decrypted, err := ak.ActivateCredentialWithEK(tpm, *challenge, ek) + if err != nil { + log.Fatalf("Failed to activate credential: %v", err) + } + + // Check that the AK completed the challenge (usually done on the server). + if subtle.ConstantTimeCompare(secret, decrypted) == 0 { + log.Fatal("Activation response did not match secret") + } + } +} + func TestExampleAK(t *testing.T) { if !*testExamples { t.SkipNow() } ExampleAK() ExampleAK_credentialActivation() + ExampleAK_credentialActivationWithEK() } func TestExampleTPM(t *testing.T) { diff --git a/attest/key_linux.go b/attest/key_linux.go index ac09e491..0afd58f7 100644 --- a/attest/key_linux.go +++ b/attest/key_linux.go @@ -52,7 +52,7 @@ func (k *trousersKey12) close(tpm tpmBase) error { return nil // No state for tpm 1.2. } -func (k *trousersKey12) activateCredential(tb tpmBase, in EncryptedCredential) ([]byte, error) { +func (k *trousersKey12) activateCredential(tb tpmBase, in EncryptedCredential, ek *EK) ([]byte, error) { t, ok := tb.(*trousersTPM) if !ok { return nil, fmt.Errorf("expected *linuxTPM, got %T", tb) @@ -65,7 +65,7 @@ func (k *trousersKey12) activateCredential(tb tpmBase, in EncryptedCredential) ( return cred, nil } -func (k *trousersKey12) quote(tb tpmBase, nonce []byte, alg HashAlg) (*Quote, error) { +func (k *trousersKey12) quote(tb tpmBase, nonce []byte, alg HashAlg, selectedPCRs []int) (*Quote, error) { t, ok := tb.(*trousersTPM) if !ok { return nil, fmt.Errorf("expected *linuxTPM, got %T", tb) @@ -73,6 +73,9 @@ func (k *trousersKey12) quote(tb tpmBase, nonce []byte, alg HashAlg) (*Quote, er if alg != HashSHA1 { return nil, fmt.Errorf("only SHA1 algorithms supported on TPM 1.2, not %v", alg) } + if selectedPCRs != nil { + return nil, fmt.Errorf("selecting PCRs not supported on TPM 1.2 (parameter must be nil)") + } quote, rawSig, err := attestation.GetQuote(t.ctx, k.blob, nonce) if err != nil { diff --git a/attest/key_windows.go b/attest/key_windows.go index 62b49aac..917edaa6 100644 --- a/attest/key_windows.go +++ b/attest/key_windows.go @@ -18,28 +18,32 @@ package attest import ( + "crypto" + "crypto/ecdsa" + "crypto/rsa" + "errors" "fmt" + "github.com/google/go-tpm/legacy/tpm2" tpm1 "github.com/google/go-tpm/tpm" - "github.com/google/go-tpm/tpm2" ) -// windowsKey12 represents a Windows-managed key on a TPM1.2 TPM. -type windowsKey12 struct { +// windowsAK12 represents a Windows-managed key on a TPM1.2 TPM. +type windowsAK12 struct { hnd uintptr pcpKeyName string public []byte } -func newWindowsKey12(hnd uintptr, pcpKeyName string, public []byte) ak { - return &windowsKey12{ +func newWindowsAK12(hnd uintptr, pcpKeyName string, public []byte) ak { + return &windowsAK12{ hnd: hnd, pcpKeyName: pcpKeyName, public: public, } } -func (k *windowsKey12) marshal() ([]byte, error) { +func (k *windowsAK12) marshal() ([]byte, error) { out := serializedKey{ Encoding: keyEncodingOSManaged, TPMVersion: TPMVersion12, @@ -49,7 +53,7 @@ func (k *windowsKey12) marshal() ([]byte, error) { return out.Serialize() } -func (k *windowsKey12) activateCredential(t tpmBase, in EncryptedCredential) ([]byte, error) { +func (k *windowsAK12) activateCredential(t tpmBase, in EncryptedCredential, ek *EK) ([]byte, error) { tpm, ok := t.(*windowsTPM) if !ok { return nil, fmt.Errorf("expected *windowsTPM, got %T", t) @@ -61,7 +65,7 @@ func (k *windowsKey12) activateCredential(t tpmBase, in EncryptedCredential) ([] return decryptCredential(secretKey, in.Secret) } -func (k *windowsKey12) quote(tb tpmBase, nonce []byte, alg HashAlg) (*Quote, error) { +func (k *windowsAK12) quote(tb tpmBase, nonce []byte, alg HashAlg, selectedPCRs []int) (*Quote, error) { if alg != HashSHA1 { return nil, fmt.Errorf("only SHA1 algorithms supported on TPM 1.2, not %v", alg) } @@ -80,11 +84,6 @@ func (k *windowsKey12) quote(tb tpmBase, nonce []byte, alg HashAlg) (*Quote, err return nil, fmt.Errorf("TPMCommandInterface() failed: %v", err) } - selectedPCRs := make([]int, 24) - for pcr := range selectedPCRs { - selectedPCRs[pcr] = pcr - } - sig, pcrc, err := tpm1.Quote(tpm, tpmKeyHnd, nonce, selectedPCRs[:], wellKnownAuth[:]) if err != nil { return nil, fmt.Errorf("Quote() failed: %v", err) @@ -103,21 +102,21 @@ func (k *windowsKey12) quote(tb tpmBase, nonce []byte, alg HashAlg) (*Quote, err }, nil } -func (k *windowsKey12) close(tpm tpmBase) error { +func (k *windowsAK12) close(tpm tpmBase) error { return closeNCryptObject(k.hnd) } -func (k *windowsKey12) attestationParameters() AttestationParameters { +func (k *windowsAK12) attestationParameters() AttestationParameters { return AttestationParameters{ Public: k.public, } } -func (k *windowsKey12) certify(tb tpmBase, handle interface{}) (*CertificationParameters, error) { +func (k *windowsAK12) certify(tb tpmBase, handle interface{}) (*CertificationParameters, error) { return nil, fmt.Errorf("not implemented") } -// windowsKey20 represents a key bound to a TPM 2.0. -type windowsKey20 struct { +// windowsAK20 represents a key bound to a TPM 2.0. +type windowsAK20 struct { hnd uintptr pcpKeyName string @@ -127,8 +126,8 @@ type windowsKey20 struct { createSignature []byte } -func newWindowsKey20(hnd uintptr, pcpKeyName string, public, createData, createAttest, createSig []byte) ak { - return &windowsKey20{ +func newWindowsAK20(hnd uintptr, pcpKeyName string, public, createData, createAttest, createSig []byte) ak { + return &windowsAK20{ hnd: hnd, pcpKeyName: pcpKeyName, public: public, @@ -138,7 +137,7 @@ func newWindowsKey20(hnd uintptr, pcpKeyName string, public, createData, createA } } -func (k *windowsKey20) marshal() ([]byte, error) { +func (k *windowsAK20) marshal() ([]byte, error) { out := serializedKey{ Encoding: keyEncodingOSManaged, TPMVersion: TPMVersion20, @@ -152,7 +151,7 @@ func (k *windowsKey20) marshal() ([]byte, error) { return out.Serialize() } -func (k *windowsKey20) activateCredential(t tpmBase, in EncryptedCredential) ([]byte, error) { +func (k *windowsAK20) activateCredential(t tpmBase, in EncryptedCredential, ek *EK) ([]byte, error) { tpm, ok := t.(*windowsTPM) if !ok { return nil, fmt.Errorf("expected *windowsTPM, got %T", t) @@ -160,7 +159,7 @@ func (k *windowsKey20) activateCredential(t tpmBase, in EncryptedCredential) ([] return tpm.pcp.ActivateCredential(k.hnd, append(in.Credential, in.Secret...)) } -func (k *windowsKey20) quote(tb tpmBase, nonce []byte, alg HashAlg) (*Quote, error) { +func (k *windowsAK20) quote(tb tpmBase, nonce []byte, alg HashAlg, selectedPCRs []int) (*Quote, error) { t, ok := tb.(*windowsTPM) if !ok { return nil, fmt.Errorf("expected *windowsTPM, got %T", tb) @@ -174,14 +173,14 @@ func (k *windowsKey20) quote(tb tpmBase, nonce []byte, alg HashAlg) (*Quote, err if err != nil { return nil, fmt.Errorf("TPMCommandInterface() failed: %v", err) } - return quote20(tpm, tpmKeyHnd, alg.goTPMAlg(), nonce) + return quote20(tpm, tpmKeyHnd, alg.goTPMAlg(), nonce, selectedPCRs) } -func (k *windowsKey20) close(tpm tpmBase) error { +func (k *windowsAK20) close(tpm tpmBase) error { return closeNCryptObject(k.hnd) } -func (k *windowsKey20) attestationParameters() AttestationParameters { +func (k *windowsAK20) attestationParameters() AttestationParameters { return AttestationParameters{ Public: k.public, CreateData: k.createData, @@ -190,7 +189,7 @@ func (k *windowsKey20) attestationParameters() AttestationParameters { } } -func (k *windowsKey20) certify(tb tpmBase, handle interface{}) (*CertificationParameters, error) { +func (k *windowsAK20) certify(tb tpmBase, handle interface{}) (*CertificationParameters, error) { t, ok := tb.(*windowsTPM) if !ok { return nil, fmt.Errorf("expected *windowsTPM, got %T", tb) @@ -217,3 +216,59 @@ func (k *windowsKey20) certify(tb tpmBase, handle interface{}) (*CertificationPa } return certify(tpm, hnd, akHnd, scheme) } + +// newWindowsKey20 returns a pointer to a windowsAK20, conforming to the key interface. This +// allows the resulting windowsAK20 to be used as a signing key. +func newWindowsKey20(hnd uintptr, pcpKeyName string, public, createData, createAttest, createSig []byte) key { + return &windowsAK20{ + hnd: hnd, + pcpKeyName: pcpKeyName, + public: public, + createData: createData, + createAttestation: createAttest, + createSignature: createSig, + } +} + +func (k *windowsAK20) blobs() ([]byte, []byte, error) { + return nil, nil, errors.New("not implemented") +} + +func (k *windowsAK20) certificationParameters() CertificationParameters { + return CertificationParameters{ + Public: k.public, + CreateAttestation: k.createAttestation, + CreateSignature: k.createSignature, + } +} + +func (k *windowsAK20) decrypt(tpmBase, []byte) ([]byte, error) { + return nil, errors.New("not implemented") +} + +func (k *windowsAK20) sign(tb tpmBase, digest []byte, pub crypto.PublicKey, opts crypto.SignerOpts) ([]byte, error) { + + t, ok := tb.(*windowsTPM) + if !ok { + return nil, fmt.Errorf("expected *windowsTPM, got %T", tb) + } + + rw, err := t.pcp.TPMCommandInterface() + if err != nil { + return nil, fmt.Errorf("error getting TPM command interface: %w", err) + } + + hnd, err := t.pcp.TPMKeyHandle(k.hnd) + if err != nil { + return nil, fmt.Errorf("TPMKeyHandle() failed: %v", err) + } + + switch p := pub.(type) { + case *ecdsa.PublicKey: + return signECDSA(rw, hnd, digest, p.Curve, opts) + case *rsa.PublicKey: + return signRSA(rw, hnd, digest, opts) + } + + return nil, fmt.Errorf("unsupported signing key type: %T", pub) +} diff --git a/attest/pcp_windows.go b/attest/pcp_windows.go index b78a3812..a13efb96 100644 --- a/attest/pcp_windows.go +++ b/attest/pcp_windows.go @@ -38,8 +38,17 @@ const ( // The below is documented in this Microsoft whitepaper: // https://github.com/Microsoft/TSS.MSR/blob/master/PCPTool.v11/Using%20the%20Windows%208%20Platform%20Crypto%20Provider%20and%20Associated%20TPM%20Functionality.pdf ncryptOverwriteKeyFlag = 0x80 + // Key usage value for generic keys + nCryptPropertyPCPKeyUsagePolicyGeneric = 0x3 // Key usage value for AKs. nCryptPropertyPCPKeyUsagePolicyIdentity = 0x8 + + // PCP key magic + pcpKeyMagic = 0x4D504350 + + // TPM types from PCP_KEY_BLOB header data + tpm12 = 0x1 + tpm20 = 0x2 ) // DLL references. @@ -53,6 +62,7 @@ var ( nCryptCreatePersistedKey = nCrypt.MustFindProc("NCryptCreatePersistedKey") nCryptFinalizeKey = nCrypt.MustFindProc("NCryptFinalizeKey") nCryptDeleteKey = nCrypt.MustFindProc("NCryptDeleteKey") + nCryptExportKey = nCrypt.MustFindProc("NCryptExportKey") crypt32 = windows.MustLoadDLL("crypt32.dll") crypt32CertEnumCertificatesInStore = crypt32.MustFindProc("CertEnumCertificatesInStore") @@ -452,16 +462,15 @@ func getPCPCerts(hProv uintptr, propertyName string) ([][]byte, error) { return out, nil } -// NewAK creates a persistent attestation key of the specified name. -func (h *winPCP) NewAK(name string) (uintptr, error) { +func (h *winPCP) newKey(name string, alg string, length uint32, policy uint32) (uintptr, []byte, []byte, error) { var kh uintptr utf16Name, err := windows.UTF16FromString(name) if err != nil { - return 0, err + return 0, nil, nil, err } - utf16RSA, err := windows.UTF16FromString("RSA") + utf16RSA, err := windows.UTF16FromString(alg) if err != nil { - return 0, err + return 0, nil, nil, err } // Create a persistent RSA key of the specified name. @@ -470,45 +479,102 @@ func (h *winPCP) NewAK(name string) (uintptr, error) { if tpmErr := maybeWinErr(r); tpmErr != nil { msg = tpmErr } - return 0, fmt.Errorf("NCryptCreatePersistedKey returned %X: %v", r, msg) + return 0, nil, nil, fmt.Errorf("NCryptCreatePersistedKey returned %X: %v", r, msg) } - // Specify generated key length to be 2048 bits. - utf16Length, err := windows.UTF16FromString("Length") - if err != nil { - return 0, err + + // Set the length if provided + if length != 0 { + utf16Length, err := windows.UTF16FromString("Length") + if err != nil { + return 0, nil, nil, err + } + r, _, msg = nCryptSetProperty.Call(kh, uintptr(unsafe.Pointer(&utf16Length[0])), uintptr(unsafe.Pointer(&length)), unsafe.Sizeof(length), 0) + if r != 0 { + if tpmErr := maybeWinErr(r); tpmErr != nil { + msg = tpmErr + } + return 0, nil, nil, fmt.Errorf("NCryptSetProperty (Length) returned %X: %v", r, msg) + } + } + // Specify the generated key usage policy if appropriate + if policy != 0 { + utf16KeyPolicy, err := windows.UTF16FromString("PCP_KEY_USAGE_POLICY") + if err != nil { + return 0, nil, nil, err + } + r, _, msg = nCryptSetProperty.Call(kh, uintptr(unsafe.Pointer(&utf16KeyPolicy[0])), uintptr(unsafe.Pointer(&policy)), unsafe.Sizeof(policy), 0) + if r != 0 { + if tpmErr := maybeWinErr(r); tpmErr != nil { + msg = tpmErr + } + return 0, nil, nil, fmt.Errorf("NCryptSetProperty (PCP KeyUsage Policy) returned %X: %v", r, msg) + } } - var length uint32 = 2048 - r, _, msg = nCryptSetProperty.Call(kh, uintptr(unsafe.Pointer(&utf16Length[0])), uintptr(unsafe.Pointer(&length)), unsafe.Sizeof(length), 0) + + // Finalize (create) the key. + r, _, msg = nCryptFinalizeKey.Call(kh, 0) if r != 0 { if tpmErr := maybeWinErr(r); tpmErr != nil { msg = tpmErr } - return 0, fmt.Errorf("NCryptSetProperty (Length) returned %X: %v", r, msg) + return 0, nil, nil, fmt.Errorf("NCryptFinalizeKey returned %X: %v", r, msg) } - // Specify the generated key can only be used for identity attestation. - utf16KeyPolicy, err := windows.UTF16FromString("PCP_KEY_USAGE_POLICY") + + // Obtain the key blob. + var sz uint32 + typeString, err := windows.UTF16FromString("OpaqueKeyBlob") if err != nil { - return 0, err + return 0, nil, nil, err } - var policy uint32 = nCryptPropertyPCPKeyUsagePolicyIdentity - r, _, msg = nCryptSetProperty.Call(kh, uintptr(unsafe.Pointer(&utf16KeyPolicy[0])), uintptr(unsafe.Pointer(&policy)), unsafe.Sizeof(policy), 0) - if r != 0 { + + if r, _, err := nCryptExportKey.Call(kh, 0, uintptr(unsafe.Pointer(&typeString[0])), 0, 0, 0, uintptr(unsafe.Pointer(&sz)), 0); r != 0 { if tpmErr := maybeWinErr(r); tpmErr != nil { - msg = tpmErr + err = tpmErr } - return 0, fmt.Errorf("NCryptSetProperty (PCP KeyUsage Policy) returned %X: %v", r, msg) + return 0, nil, nil, fmt.Errorf("NCryptGetProperty for hKey blob original query returned %X (%v)", r, err) } - // Finalize (create) the key. - r, _, msg = nCryptFinalizeKey.Call(kh, 0) - if r != 0 { + keyBlob := make([]byte, sz) + + if r, _, err := nCryptExportKey.Call(kh, 0, uintptr(unsafe.Pointer(&typeString[0])), 0, uintptr(unsafe.Pointer(&keyBlob[0])), uintptr(sz), uintptr(unsafe.Pointer(&sz)), 0); r != 0 { if tpmErr := maybeWinErr(r); tpmErr != nil { - msg = tpmErr + err = tpmErr } - return 0, fmt.Errorf("NCryptFinalizeKey returned %X: %v", r, msg) + return 0, nil, nil, fmt.Errorf("NCryptGetProperty for hKey blob returned %X (%v)", r, err) + } + + pubBlob, privBlob, err := decodeKeyBlob(keyBlob) + if err != nil { + return 0, nil, nil, fmt.Errorf("decodeKeyBlob failed: %v", err) } - return kh, nil + return kh, pubBlob, privBlob, nil +} + +// NewAK creates a persistent attestation key of the specified name. +func (h *winPCP) NewAK(name string) (uintptr, error) { + // AKs need to be RSA due to platform limitations + key, _, _, err := h.newKey(name, "RSA", 2048, nCryptPropertyPCPKeyUsagePolicyIdentity) + return key, err +} + +// NewKey creates a persistent application key of the specified name. +func (h *winPCP) NewKey(name string, config *KeyConfig) (uintptr, []byte, []byte, error) { + if config.Algorithm == RSA { + return h.newKey(name, "RSA", uint32(config.Size), 0) + } else if config.Algorithm == ECDSA { + switch config.Size { + case 256: + return h.newKey(name, "ECDSA_P256", 0, 0) + case 384: + return h.newKey(name, "ECDSA_P384", 0, 0) + case 521: + return h.newKey(name, "ECDSA_P521", 0, 0) + default: + return 0, nil, nil, fmt.Errorf("unsupported ECDSA key size: %v", config.Size) + } + } + return 0, nil, nil, fmt.Errorf("unsupported algorithm type: %q", config.Algorithm) } // EKPub returns a BCRYPT_RSA_BLOB structure representing the EK. @@ -635,6 +701,98 @@ func decodeAKProps20(r *bytes.Reader) (*akProps, error) { return &out, nil } +func decodeKeyBlob(keyBlob []byte) ([]byte, []byte, error) { + r := bytes.NewReader(keyBlob) + + var magic uint32 + if err := binary.Read(r, binary.LittleEndian, &magic); err != nil { + return nil, nil, fmt.Errorf("failed to read header magic: %v", err) + } + if magic != pcpKeyMagic { + return nil, nil, fmt.Errorf("invalid header magic %X", magic) + } + + var headerSize uint32 + if err := binary.Read(r, binary.LittleEndian, &headerSize); err != nil { + return nil, nil, fmt.Errorf("failed to read header size: %v", err) + } + + var tpmType uint32 + if err := binary.Read(r, binary.LittleEndian, &tpmType); err != nil { + return nil, nil, fmt.Errorf("failed to read tpm type: %v", err) + } + + if tpmType == tpm12 { + return nil, nil, fmt.Errorf("TPM 1.2 currently unsupported") + } + + var flags uint32 + if err := binary.Read(r, binary.LittleEndian, &flags); err != nil { + return nil, nil, fmt.Errorf("failed to read key flags: %v", err) + } + + var pubLen uint32 + if err := binary.Read(r, binary.LittleEndian, &pubLen); err != nil { + return nil, nil, fmt.Errorf("failed to read length of public key: %v", err) + } + + var privLen uint32 + if err := binary.Read(r, binary.LittleEndian, &privLen); err != nil { + return nil, nil, fmt.Errorf("failed to read length of private blob: %v", err) + } + + var pubMigrationLen uint32 + if err := binary.Read(r, binary.LittleEndian, &pubMigrationLen); err != nil { + return nil, nil, fmt.Errorf("failed to read length of public migration blob: %v", err) + } + + var privMigrationLen uint32 + if err := binary.Read(r, binary.LittleEndian, &privMigrationLen); err != nil { + return nil, nil, fmt.Errorf("failed to read length of private migration blob: %v", err) + } + + var policyDigestLen uint32 + if err := binary.Read(r, binary.LittleEndian, &policyDigestLen); err != nil { + return nil, nil, fmt.Errorf("failed to read length of policy digest: %v", err) + } + + var pcrBindingLen uint32 + if err := binary.Read(r, binary.LittleEndian, &pcrBindingLen); err != nil { + return nil, nil, fmt.Errorf("failed to read length of PCR binding: %v", err) + } + + var pcrDigestLen uint32 + if err := binary.Read(r, binary.LittleEndian, &pcrDigestLen); err != nil { + return nil, nil, fmt.Errorf("failed to read length of PCR digest: %v", err) + } + + var encryptedSecretLen uint32 + if err := binary.Read(r, binary.LittleEndian, &encryptedSecretLen); err != nil { + return nil, nil, fmt.Errorf("failed to read length of hostage import symmetric key: %v", err) + } + + var tpm12HostageLen uint32 + if err := binary.Read(r, binary.LittleEndian, &tpm12HostageLen); err != nil { + return nil, nil, fmt.Errorf("failed to read length of hostage import private key: %v", err) + } + + // Skip over any padding + r.Seek(int64(headerSize), 0) + + pubKey := make([]byte, pubLen) + + if err := binary.Read(r, binary.BigEndian, &pubKey); err != nil { + return nil, nil, fmt.Errorf("failed to read public key: %v", err) + } + + privBlob := make([]byte, privLen) + if err := binary.Read(r, binary.BigEndian, &privBlob); err != nil { + return nil, nil, fmt.Errorf("failed to read private blob: %v", err) + } + + return pubKey[2:], privBlob[2:], nil +} + // LoadKeyByName returns a handle to the persistent PCP key with the specified // name. func (h *winPCP) LoadKeyByName(name string) (uintptr, error) { diff --git a/attest/tpm.go b/attest/tpm.go index 13057bf4..31217728 100644 --- a/attest/tpm.go +++ b/attest/tpm.go @@ -24,9 +24,10 @@ import ( "encoding/binary" "fmt" "io" + "net/url" "strings" - "github.com/google/go-tpm/tpm2" + "github.com/google/go-tpm/legacy/tpm2" "github.com/google/go-tpm/tpmutil" ) @@ -36,12 +37,14 @@ const ( tpmPtFwVersion1 = 0x00000100 + 11 // PT_FIXED + offset of 11 // Defined in "Registry of reserved TPM 2.0 handles and localities". - nvramCertIndex = 0x1c00002 - nvramEkNonceIndex = 0x1c00003 + nvramRSACertIndex = 0x1c00002 + nvramRSAEkNonceIndex = 0x1c00003 + nvramECCCertIndex = 0x1c0000a + nvramECCEkNonceIndex = 0x1c0000b // Defined in "Registry of reserved TPM 2.0 handles and localities", and checked on a glinux machine. - commonSrkEquivalentHandle = 0x81000001 - commonEkEquivalentHandle = 0x81010001 + commonRSAEkEquivalentHandle = 0x81010001 + commonECCEkEquivalentHandle = 0x81010002 ) var ( @@ -57,7 +60,7 @@ var ( KeyBits: 2048, }, } - defaultSRKTemplate = tpm2.Public{ + defaultRSASRKTemplate = tpm2.Public{ Type: tpm2.AlgRSA, NameAlg: tpm2.AlgSHA256, Attributes: tpm2.FlagStorageDefault | tpm2.FlagNoDA, @@ -71,9 +74,26 @@ var ( KeyBits: 2048, }, } - // Default EK template defined in: + defaultECCSRKTemplate = tpm2.Public{ + Type: tpm2.AlgECC, + NameAlg: tpm2.AlgSHA256, + Attributes: tpm2.FlagStorageDefault | tpm2.FlagNoDA, + ECCParameters: &tpm2.ECCParams{ + Symmetric: &tpm2.SymScheme{ + Alg: tpm2.AlgAES, + KeyBits: 128, + Mode: tpm2.AlgCFB, + }, + CurveID: tpm2.CurveNISTP256, + Point: tpm2.ECPoint{ + XRaw: make([]byte, 32), + YRaw: make([]byte, 32), + }, + }, + } + // Default RSA and ECC EK templates defined in: // https://trustedcomputinggroup.org/wp-content/uploads/Credential_Profile_EK_V2.0_R14_published.pdf - defaultEKTemplate = tpm2.Public{ + defaultRSAEKTemplate = tpm2.Public{ Type: tpm2.AlgRSA, NameAlg: tpm2.AlgSHA256, Attributes: tpm2.FlagFixedTPM | tpm2.FlagFixedParent | tpm2.FlagSensitiveDataOrigin | @@ -96,6 +116,32 @@ var ( ModulusRaw: make([]byte, 256), }, } + defaultECCEKTemplate = tpm2.Public{ + Type: tpm2.AlgECC, + NameAlg: tpm2.AlgSHA256, + Attributes: tpm2.FlagFixedTPM | tpm2.FlagFixedParent | tpm2.FlagSensitiveDataOrigin | + tpm2.FlagAdminWithPolicy | tpm2.FlagRestricted | tpm2.FlagDecrypt, + AuthPolicy: []byte{ + 0x83, 0x71, 0x97, 0x67, 0x44, 0x84, + 0xB3, 0xF8, 0x1A, 0x90, 0xCC, 0x8D, + 0x46, 0xA5, 0xD7, 0x24, 0xFD, 0x52, + 0xD7, 0x6E, 0x06, 0x52, 0x0B, 0x64, + 0xF2, 0xA1, 0xDA, 0x1B, 0x33, 0x14, + 0x69, 0xAA, + }, + ECCParameters: &tpm2.ECCParams{ + Symmetric: &tpm2.SymScheme{ + Alg: tpm2.AlgAES, + KeyBits: 128, + Mode: tpm2.AlgCFB, + }, + CurveID: tpm2.CurveNISTP256, + Point: tpm2.ECPoint{ + XRaw: make([]byte, 32), + YRaw: make([]byte, 32), + }, + }, + } // Basic template for an ECDSA key signing outside-TPM objects. Other // fields are populated depending on the key creation options. ecdsaKeyTemplate = tpm2.Public{ @@ -219,10 +265,10 @@ func intelEKURL(ekPub *rsa.PublicKey) string { pubHash.Write(ekPub.N.Bytes()) pubHash.Write([]byte{0x1, 0x00, 0x01}) - return intelEKCertServiceURL + base64.URLEncoding.EncodeToString(pubHash.Sum(nil)) + return intelEKCertServiceURL + url.QueryEscape(base64.URLEncoding.EncodeToString(pubHash.Sum(nil))) } -func readEKCertFromNVRAM20(tpm io.ReadWriter) (*x509.Certificate, error) { +func readEKCertFromNVRAM20(tpm io.ReadWriter, nvramCertIndex tpmutil.Handle) (*x509.Certificate, error) { // By passing nvramCertIndex as our auth handle we're using the NV index // itself as the auth hierarchy, which is the same approach // tpm2_getekcertificate takes. @@ -233,12 +279,9 @@ func readEKCertFromNVRAM20(tpm io.ReadWriter) (*x509.Certificate, error) { return ParseEKCertificate(ekCert) } -func quote20(tpm io.ReadWriter, akHandle tpmutil.Handle, hashAlg tpm2.Algorithm, nonce []byte) (*Quote, error) { - sel := tpm2.PCRSelection{Hash: hashAlg} - numPCRs := 24 - for pcr := 0; pcr < numPCRs; pcr++ { - sel.PCRs = append(sel.PCRs, pcr) - } +func quote20(tpm io.ReadWriter, akHandle tpmutil.Handle, hashAlg tpm2.Algorithm, nonce []byte, selectedPCRs []int) (*Quote, error) { + sel := tpm2.PCRSelection{Hash: hashAlg, + PCRs: selectedPCRs} quote, sig, err := tpm2.Quote(tpm, akHandle, "", "", nonce, sel, tpm2.AlgNull) if err != nil { @@ -296,11 +339,14 @@ type tpmBase interface { close() error tpmVersion() TPMVersion eks() ([]EK, error) + ekCertificates() ([]EK, error) info() (*TPMInfo, error) loadAK(opaqueBlob []byte) (*AK, error) + loadAKWithParent(opaqueBlob []byte, parent ParentKeyConfig) (*AK, error) newAK(opts *AKConfig) (*AK, error) loadKey(opaqueBlob []byte) (*Key, error) + loadKeyWithParent(opaqueBlob []byte, parent ParentKeyConfig) (*Key, error) newKey(ak *AK, opts *KeyConfig) (*Key, error) pcrs(alg HashAlg) ([]PCR, error) measurementLog() ([]byte, error) @@ -323,6 +369,12 @@ func (t *TPM) EKs() ([]EK, error) { return t.tpm.eks() } +// EKCertificates returns the endorsement key certificates burned-in to the platform. +// It is guaranteed that each EK.Certificate field will be populated. +func (t *TPM) EKCertificates() ([]EK, error) { + return t.tpm.ekCertificates() +} + // Info returns information about the TPM. func (t *TPM) Info() (*TPMInfo, error) { return t.tpm.info() @@ -336,6 +388,12 @@ func (t *TPM) LoadAK(opaqueBlob []byte) (*AK, error) { return t.tpm.loadAK(opaqueBlob) } +// LoadAKWithParent loads a previously-created ak into the TPM +// under the given parent for use. +func (t *TPM) LoadAKWithParent(opaqueBlob []byte, parent ParentKeyConfig) (*AK, error) { + return t.tpm.loadAKWithParent(opaqueBlob, parent) +} + // MeasurementLog returns the present value of the System Measurement Log. // // This is a low-level API. Consumers seeking to attest the state of the @@ -393,6 +451,7 @@ func (t *TPM) attestPCRs(ak *AK, nonce []byte, alg HashAlg) (*Quote, []PCR, erro if err != nil { return nil, nil, fmt.Errorf("failed to read %v PCRs: %v", alg, err) } + quote, err := ak.Quote(t, nonce, alg) if err != nil { return nil, nil, fmt.Errorf("failed to quote using %v: %v", alg, err) diff --git a/attest/tpm12_linux.go b/attest/tpm12_linux.go index a2eba7d2..ad568167 100644 --- a/attest/tpm12_linux.go +++ b/attest/tpm12_linux.go @@ -94,7 +94,7 @@ func readEKCertFromNVRAM12(ctx *tspi.Context) (*x509.Certificate, error) { return ParseEKCertificate(ekCert) } -func (t *trousersTPM) eks() ([]EK, error) { +func (t *trousersTPM) ekCertificates() ([]EK, error) { cert, err := readEKCertFromNVRAM12(t.ctx) if err != nil { return nil, fmt.Errorf("readEKCertFromNVRAM failed: %v", err) @@ -104,6 +104,10 @@ func (t *trousersTPM) eks() ([]EK, error) { }, nil } +func (t *trousersTPM) eks() ([]EK, error) { + return t.ekCertificates() +} + func (t *trousersTPM) newKey(*AK, *KeyConfig) (*Key, error) { return nil, fmt.Errorf("not implemented") } @@ -112,6 +116,10 @@ func (t *trousersTPM) loadKey(opaqueBlob []byte) (*Key, error) { return nil, fmt.Errorf("not implemented") } +func (t *trousersTPM) loadKeyWithParent(opaqueBlob []byte, parent ParentKeyConfig) (*Key, error) { + return nil, fmt.Errorf("not implemented") +} + func (t *trousersTPM) newAK(opts *AKConfig) (*AK, error) { pub, blob, err := attestation.CreateAIK(t.ctx) if err != nil { @@ -132,6 +140,10 @@ func (t *trousersTPM) loadAK(opaqueBlob []byte) (*AK, error) { return &AK{ak: newTrousersKey12(sKey.Blob, sKey.Public)}, nil } +func (t *trousersTPM) loadAKWithParent(opaqueBlob []byte, parent ParentKeyConfig) (*AK, error) { + return nil, fmt.Errorf("not implemented") +} + // allPCRs12 returns a map of all the PCR values on the TPM func allPCRs12(ctx *tspi.Context) (map[uint32][]byte, error) { tpm := ctx.GetTPM() diff --git a/attest/tpm_linux.go b/attest/tpm_linux.go index 00915b3f..3c5ad184 100644 --- a/attest/tpm_linux.go +++ b/attest/tpm_linux.go @@ -25,7 +25,7 @@ import ( "path" "strings" - "github.com/google/go-tpm/tpm2" + "github.com/google/go-tpm/legacy/tpm2" ) const ( diff --git a/attest/tpm_test.go b/attest/tpm_test.go index 7699a989..1a385631 100644 --- a/attest/tpm_test.go +++ b/attest/tpm_test.go @@ -8,17 +8,22 @@ import ( "testing" ) -// Generated using the following command: +// Created by downloading the base64-url encoded PEM data from +// https://ekop.intel.com/ekcertservice/WVEG2rRwkQ7m3RpXlUphgo6Y2HLxl18h6ZZkkOAdnBE%3D, +// extracting its public key, and formatting it to PEM using // -// openssl genrsa 2048|openssl rsa -outform PEM -pubout +// openssl x509 -in ekcert.pem -pubkey +// +// This is the public key from the EK cert that's used for testing tpm2-tools: +// https://github.com/tpm2-software/tpm2-tools/blob/master/test/integration/tests/getekcertificate.sh var testRSAKey = mustParseRSAKey(`-----BEGIN PUBLIC KEY----- -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq8zyTXCjVALZzjS8wgNH -nAVdt4ZGM3N450xOnLplx/RbCVwXyu83SWh0B3Ka+92aocqcHzo+j6e6Urppre/I -+7VVKTdUAr8t5gxgSLGvo+ev+zv70GF4DmJthb8JNheHCmk3RnoSFs5TnDuSdvGb -KcSzas0186LQyxvwfFjTxLweGrZKh/CTewD0/f5ozXmbTtJpl+qYrMi9GJamGlg6 -N6EsWKh1xos8J/cEmS2vbyCGGADyBwRV8Zkto5EU1HJaEli10HVZf0D06vuKzzxM -+6W7LzGqzAPeaWvHi07ezShqdr5q5y1KKhFJcy8HOpwN8iFfIw70y3FtMlrMprrU -twIDAQAB +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwyDi8kSoYBqs8+AdJsZl +JJk1Vi3h2hl+nn8HbEaWE8+2U+mOwsOG/B0TPyyMbMM4tzLwsgi9g4qHej5bvD4d +QIToNcfIkGocBbTS0w/b68HbrZUPprFlvUtqhkYDFGFkwMT1nUiQEe8fko3upukA +YfPTdeVkYnMVHvYiJSCYvhpKsB3AoSInxgn9rOsRWvQI1Gk6b0mRl3RpWwwSvBih +/3EgpzN7L7XxlR2Lt/CU1bVUwRyVI7MHKf5keH0KE7nmMEiNq039hmNKUnDscvzF +pE3GeajzKTjdgZfina6Dn1tMoPXeJ8lSLCPFThws5XhZUlEYvURwsYGA7veK5CZ7 +zQIDAQAB -----END PUBLIC KEY-----`) func mustParseRSAKey(data string) *rsa.PublicKey { @@ -45,7 +50,7 @@ func parseRSAKey(data string) (*rsa.PublicKey, error) { } func TestIntelEKURL(t *testing.T) { - want := "https://ekop.intel.com/ekcertservice/7YtWV2nT3LpvSCfJt7ENIznN1R1jYkj_3S6mez3yyzg=" + want := "https://ekop.intel.com/ekcertservice/WVEG2rRwkQ7m3RpXlUphgo6Y2HLxl18h6ZZkkOAdnBE%3D" got := intelEKURL(testRSAKey) if got != want { t.Fatalf("intelEKURL(), got=%q, want=%q", got, want) diff --git a/attest/tpm_windows.go b/attest/tpm_windows.go index 0203c767..3a4afc39 100644 --- a/attest/tpm_windows.go +++ b/attest/tpm_windows.go @@ -29,6 +29,7 @@ import ( "io" "math/big" + "github.com/google/go-tpm/legacy/tpm2" tpm1 "github.com/google/go-tpm/tpm" tpmtbs "github.com/google/go-tpm/tpmutil/tbs" "golang.org/x/sys/windows" @@ -152,6 +153,18 @@ func (t *windowsTPM) info() (*TPMInfo, error) { return &tInfo, nil } +func (t *windowsTPM) ekCertificates() ([]EK, error) { + ekCerts, err := t.pcp.EKCerts() + if err != nil { + return nil, fmt.Errorf("could not read EKCerts: %v", err) + } + var eks []EK + for _, cert := range ekCerts { + eks = append(eks, EK{Certificate: cert, Public: cert.PublicKey}) + } + return eks, nil +} + func (t *windowsTPM) eks() ([]EK, error) { ekCerts, err := t.pcp.EKCerts() if err != nil { @@ -293,9 +306,9 @@ func (t *windowsTPM) newAK(opts *AKConfig) (*AK, error) { switch t.version { case TPMVersion12: - return &AK{ak: newWindowsKey12(kh, name, props.RawPublic)}, nil + return &AK{ak: newWindowsAK12(kh, name, props.RawPublic)}, nil case TPMVersion20: - return &AK{ak: newWindowsKey20(kh, name, props.RawPublic, props.RawCreationData, props.RawAttest, props.RawSignature)}, nil + return &AK{ak: newWindowsAK20(kh, name, props.RawPublic, props.RawCreationData, props.RawAttest, props.RawSignature)}, nil default: return nil, fmt.Errorf("cannot handle TPM version: %v", t.version) } @@ -317,19 +330,88 @@ func (t *windowsTPM) loadAK(opaqueBlob []byte) (*AK, error) { switch t.version { case TPMVersion12: - return &AK{ak: newWindowsKey12(hnd, sKey.Name, sKey.Public)}, nil + return &AK{ak: newWindowsAK12(hnd, sKey.Name, sKey.Public)}, nil case TPMVersion20: - return &AK{ak: newWindowsKey20(hnd, sKey.Name, sKey.Public, sKey.CreateData, sKey.CreateAttestation, sKey.CreateSignature)}, nil + return &AK{ak: newWindowsAK20(hnd, sKey.Name, sKey.Public, sKey.CreateData, sKey.CreateAttestation, sKey.CreateSignature)}, nil default: return nil, fmt.Errorf("cannot handle TPM version: %v", t.version) } } -func (t *windowsTPM) newKey(*AK, *KeyConfig) (*Key, error) { +func (t *windowsTPM) loadAKWithParent(opaqueBlob []byte, parent ParentKeyConfig) (*AK, error) { return nil, fmt.Errorf("not implemented") } +func (t *windowsTPM) newKey(ak *AK, config *KeyConfig) (*Key, error) { + if t.version != TPMVersion20 { + return nil, fmt.Errorf("key generation on TPM version %v is unsupported", t.version) + } + k, ok := ak.ak.(*windowsAK20) + if !ok { + return nil, fmt.Errorf("expected *windowsAK20, got: %T", k) + } + + nameHex := make([]byte, 5) + if n, err := rand.Read(nameHex); err != nil || n != len(nameHex) { + return nil, fmt.Errorf("rand.Read() failed with %d/%d bytes read and error: %v", n, len(nameHex), err) + } + name := fmt.Sprintf("app-%x", nameHex) + + hnd, pub, blob, err := t.pcp.NewKey(name, config) + if err != nil { + return nil, fmt.Errorf("pcp failed to mint application key: %v", err) + } + + cp, err := k.certify(t, hnd) + if err != nil { + return nil, fmt.Errorf("ak.Certify() failed: %v", err) + } + + if !bytes.Equal(pub, cp.Public) { + return nil, fmt.Errorf("certified incorrect key, expected: %v, certified: %v", pub, cp.Public) + } + + tpmPub, err := tpm2.DecodePublic(pub) + if err != nil { + return nil, fmt.Errorf("decode public key: %v", err) + } + + pubKey, err := tpmPub.Key() + if err != nil { + return nil, fmt.Errorf("access public key: %v", err) + } + + // TODO(hslatman): do we need the blob? + _ = blob + + // Return a new windowsAK20 certified by the ak, conforming to the key interface. This allows the + // key to be verified to have been generated by the same TPM as the ak was generated with. The + // resulting key can be used for signing purposes. + return &Key{key: newWindowsKey20(hnd, name, pub, cp.CreateData, cp.CreateAttestation, cp.CreateSignature), pub: pubKey, tpm: t}, nil +} + func (t *windowsTPM) loadKey(opaqueBlob []byte) (*Key, error) { + keyData, err := deserializeKey(opaqueBlob, TPMVersion20) + if err != nil { + return nil, fmt.Errorf("deserializeKey() failed: %v", err) + } + hnd, err := t.pcp.LoadKeyByName(keyData.Name) + if err != nil { + return nil, fmt.Errorf("failed to load key: %v", err) + } + tpmPub, err := tpm2.DecodePublic(keyData.Public) + if err != nil { + return nil, fmt.Errorf("decode public key: %v", err) + } + pubKey, err := tpmPub.Key() + if err != nil { + return nil, fmt.Errorf("access public key: %v", err) + } + + return &Key{key: newWindowsKey20(hnd, keyData.Name, keyData.Public, keyData.CreateData, keyData.CreateAttestation, keyData.CreateSignature), pub: pubKey, tpm: t}, nil +} + +func (t *windowsTPM) loadKeyWithParent(opaqueBlob []byte, parent ParentKeyConfig) (*Key, error) { return nil, fmt.Errorf("not implemented") } diff --git a/attest/wrapped_tpm20.go b/attest/wrapped_tpm20.go index 5d334f89..14a7a6f0 100644 --- a/attest/wrapped_tpm20.go +++ b/attest/wrapped_tpm20.go @@ -26,32 +26,50 @@ import ( "io" "math/big" - "github.com/google/go-tpm/tpm2" + "github.com/google/go-tpm/legacy/tpm2" "github.com/google/go-tpm/tpmutil" ) // wrappedTPM20 interfaces with a TPM 2.0 command channel. type wrappedTPM20 struct { - interf TPMInterface - rwc CommandChannelTPM20 - tpmEkTemplate *tpm2.Public + interf TPMInterface + rwc CommandChannelTPM20 + tpmRSAEkTemplate *tpm2.Public + tpmECCEkTemplate *tpm2.Public } -func (t *wrappedTPM20) ekTemplate() (tpm2.Public, error) { - if t.tpmEkTemplate != nil { - return *t.tpmEkTemplate, nil +func (t *wrappedTPM20) rsaEkTemplate() tpm2.Public { + if t.tpmRSAEkTemplate != nil { + return *t.tpmRSAEkTemplate } - nonce, err := tpm2.NVReadEx(t.rwc, nvramEkNonceIndex, tpm2.HandleOwner, "", 0) + nonce, err := tpm2.NVReadEx(t.rwc, nvramRSAEkNonceIndex, tpm2.HandleOwner, "", 0) if err != nil { - t.tpmEkTemplate = &defaultEKTemplate // No nonce, use the default template + t.tpmRSAEkTemplate = &defaultRSAEKTemplate // No nonce, use the default template } else { - template := defaultEKTemplate + template := defaultRSAEKTemplate copy(template.RSAParameters.ModulusRaw, nonce) - t.tpmEkTemplate = &template + t.tpmRSAEkTemplate = &template } - return *t.tpmEkTemplate, nil + return *t.tpmRSAEkTemplate +} + +func (t *wrappedTPM20) eccEkTemplate() tpm2.Public { + if t.tpmECCEkTemplate != nil { + return *t.tpmECCEkTemplate + } + + nonce, err := tpm2.NVReadEx(t.rwc, nvramECCEkNonceIndex, tpm2.HandleOwner, "", 0) + if err != nil { + t.tpmECCEkTemplate = &defaultECCEKTemplate // No nonce, use the default template + } else { + template := defaultECCEKTemplate + copy(template.ECCParameters.Point.XRaw, nonce) + t.tpmECCEkTemplate = &template + } + + return *t.tpmECCEkTemplate } func (t *wrappedTPM20) tpmVersion() TPMVersion { @@ -83,53 +101,105 @@ func (t *wrappedTPM20) info() (*TPMInfo, error) { return &tInfo, nil } +// Return value: handle, whether we generated a new one, error. +func (t *wrappedTPM20) getEndorsementKeyHandle(ek *EK) (tpmutil.Handle, bool, error) { + var ekHandle tpmutil.Handle + var ekTemplate tpm2.Public + + if ek == nil { + // The default is RSA for backward compatibility. + ekHandle = commonRSAEkEquivalentHandle + ekTemplate = t.rsaEkTemplate() + } else { + ekHandle = ek.handle + if ekHandle == 0 { + // Assume RSA EK handle if it was not provided. + ekHandle = commonRSAEkEquivalentHandle + } + switch pub := ek.Public.(type) { + case *rsa.PublicKey: + ekTemplate = t.rsaEkTemplate() + case *ecdsa.PublicKey: + ekTemplate = t.eccEkTemplate() + default: + return 0, false, fmt.Errorf("unsupported public key type %T", pub) + } + } + + _, _, _, err := tpm2.ReadPublic(t.rwc, ekHandle) + if err == nil { + // Found the persistent handle, assume it's the key we want. + return ekHandle, false, nil + } + rerr := err // Preserve this failure for later logging, if needed + + keyHnd, _, err := tpm2.CreatePrimary(t.rwc, tpm2.HandleEndorsement, tpm2.PCRSelection{}, "", "", ekTemplate) + if err != nil { + return 0, false, fmt.Errorf("ReadPublic failed (%v), and then CreatePrimary failed: %v", rerr, err) + } + defer tpm2.FlushContext(t.rwc, keyHnd) + + err = tpm2.EvictControl(t.rwc, "", tpm2.HandleOwner, keyHnd, ekHandle) + if err != nil { + return 0, false, fmt.Errorf("EvictControl failed: %v", err) + } + + return ekHandle, true, nil +} + // Return value: handle, whether we generated a new one, error -func (t *wrappedTPM20) getPrimaryKeyHandle(pHnd tpmutil.Handle) (tpmutil.Handle, bool, error) { - _, _, _, err := tpm2.ReadPublic(t.rwc, pHnd) +func (t *wrappedTPM20) getStorageRootKeyHandle(parent ParentKeyConfig) (tpmutil.Handle, bool, error) { + srkHandle := parent.Handle + _, _, _, err := tpm2.ReadPublic(t.rwc, srkHandle) if err == nil { // Found the persistent handle, assume it's the key we want. - return pHnd, false, nil + return srkHandle, false, nil } rerr := err // Preserve this failure for later logging, if needed - var keyHnd tpmutil.Handle - switch pHnd { - case commonSrkEquivalentHandle: - keyHnd, _, err = tpm2.CreatePrimary(t.rwc, tpm2.HandleOwner, tpm2.PCRSelection{}, "", "", defaultSRKTemplate) - case commonEkEquivalentHandle: - var tmpl tpm2.Public - if tmpl, err = t.ekTemplate(); err != nil { - return 0, false, fmt.Errorf("ek template: %v", err) - } - keyHnd, _, err = tpm2.CreatePrimary(t.rwc, tpm2.HandleEndorsement, tpm2.PCRSelection{}, "", "", tmpl) + var srkTemplate tpm2.Public + switch parent.Algorithm { + case RSA: + srkTemplate = defaultRSASRKTemplate + case ECDSA: + srkTemplate = defaultECCSRKTemplate + default: + return 0, false, fmt.Errorf("unsupported SRK algorithm: %v", parent.Algorithm) } + keyHnd, _, err := tpm2.CreatePrimary(t.rwc, tpm2.HandleOwner, tpm2.PCRSelection{}, "", "", srkTemplate) if err != nil { return 0, false, fmt.Errorf("ReadPublic failed (%v), and then CreatePrimary failed: %v", rerr, err) } defer tpm2.FlushContext(t.rwc, keyHnd) - err = tpm2.EvictControl(t.rwc, "", tpm2.HandleOwner, keyHnd, pHnd) + err = tpm2.EvictControl(t.rwc, "", tpm2.HandleOwner, keyHnd, srkHandle) if err != nil { return 0, false, fmt.Errorf("EvictControl failed: %v", err) } - return pHnd, true, nil + return srkHandle, true, nil +} + +func (t *wrappedTPM20) ekCertificates() ([]EK, error) { + var res []EK + if rsaCert, err := readEKCertFromNVRAM20(t.rwc, nvramRSACertIndex); err == nil { + res = append(res, EK{Public: crypto.PublicKey(rsaCert.PublicKey), Certificate: rsaCert, handle: commonRSAEkEquivalentHandle}) + } + if eccCert, err := readEKCertFromNVRAM20(t.rwc, nvramECCCertIndex); err == nil { + res = append(res, EK{Public: crypto.PublicKey(eccCert.PublicKey), Certificate: eccCert, handle: commonECCEkEquivalentHandle}) + } + return res, nil } func (t *wrappedTPM20) eks() ([]EK, error) { - if cert, err := readEKCertFromNVRAM20(t.rwc); err == nil { + if cert, err := readEKCertFromNVRAM20(t.rwc, nvramRSACertIndex); err == nil { return []EK{ - {Public: crypto.PublicKey(cert.PublicKey), Certificate: cert}, + {Public: crypto.PublicKey(cert.PublicKey), Certificate: cert, handle: commonRSAEkEquivalentHandle}, }, nil } // Attempt to create an EK. - tmpl, err := t.ekTemplate() - if err != nil { - return nil, fmt.Errorf("ek template: %v", err) - } - - ekHnd, _, err := tpm2.CreatePrimary(t.rwc, tpm2.HandleEndorsement, tpm2.PCRSelection{}, "", "", tmpl) + ekHnd, _, err := tpm2.CreatePrimary(t.rwc, tpm2.HandleEndorsement, tpm2.PCRSelection{}, "", "", t.rsaEkTemplate()) if err != nil { return nil, fmt.Errorf("EK CreatePrimary failed: %v", err) } @@ -142,19 +212,36 @@ func (t *wrappedTPM20) eks() ([]EK, error) { if pub.RSAParameters == nil { return nil, errors.New("ECC EK not yet supported") } + + i, err := t.info() + if err != nil { + return nil, fmt.Errorf("Retrieving TPM info failed: %v", err) + } + ekPub := &rsa.PublicKey{ + E: int(pub.RSAParameters.Exponent()), + N: pub.RSAParameters.Modulus(), + } + var certificateURL string + if i.Manufacturer.String() == manufacturerIntel { + certificateURL = intelEKURL(ekPub) + } return []EK{ { - Public: &rsa.PublicKey{ - E: int(pub.RSAParameters.Exponent()), - N: pub.RSAParameters.Modulus(), - }, + Public: ekPub, + CertificateURL: certificateURL, + handle: commonRSAEkEquivalentHandle, }, }, nil } func (t *wrappedTPM20) newAK(opts *AKConfig) (*AK, error) { - // TODO(jsonp): Abstract choice of hierarchy & parent. - srk, _, err := t.getPrimaryKeyHandle(commonSrkEquivalentHandle) + var parent ParentKeyConfig + if opts != nil && opts.Parent != nil { + parent = *opts.Parent + } else { + parent = defaultParentConfig + } + srk, _, err := t.getStorageRootKeyHandle(parent) if err != nil { return nil, fmt.Errorf("failed to get SRK handle: %v", err) } @@ -226,7 +313,13 @@ func (t *wrappedTPM20) newKey(ak *AK, opts *KeyConfig) (*Key, error) { } func createKey(t *wrappedTPM20, opts *KeyConfig) (tpmutil.Handle, []byte, []byte, []byte, error) { - srk, _, err := t.getPrimaryKeyHandle(commonSrkEquivalentHandle) + var parent ParentKeyConfig + if opts != nil && opts.Parent != nil { + parent = *opts.Parent + } else { + parent = defaultParentConfig + } + srk, _, err := t.getStorageRootKeyHandle(parent) if err != nil { return 0, nil, nil, nil, fmt.Errorf("failed to get SRK handle: %v", err) } @@ -291,7 +384,7 @@ func templateFromConfig(opts *KeyConfig) (tpm2.Public, error) { return tmpl, nil } -func (t *wrappedTPM20) deserializeAndLoad(opaqueBlob []byte) (tpmutil.Handle, *serializedKey, error) { +func (t *wrappedTPM20) deserializeAndLoad(opaqueBlob []byte, parent ParentKeyConfig) (tpmutil.Handle, *serializedKey, error) { sKey, err := deserializeKey(opaqueBlob, TPMVersion20) if err != nil { return 0, nil, fmt.Errorf("deserializeKey() failed: %v", err) @@ -300,7 +393,7 @@ func (t *wrappedTPM20) deserializeAndLoad(opaqueBlob []byte) (tpmutil.Handle, *s return 0, nil, fmt.Errorf("unsupported key encoding: %x", sKey.Encoding) } - srk, _, err := t.getPrimaryKeyHandle(commonSrkEquivalentHandle) + srk, _, err := t.getStorageRootKeyHandle(parent) if err != nil { return 0, nil, fmt.Errorf("failed to get SRK handle: %v", err) } @@ -312,7 +405,11 @@ func (t *wrappedTPM20) deserializeAndLoad(opaqueBlob []byte) (tpmutil.Handle, *s } func (t *wrappedTPM20) loadAK(opaqueBlob []byte) (*AK, error) { - hnd, sKey, err := t.deserializeAndLoad(opaqueBlob) + return t.loadAKWithParent(opaqueBlob, defaultParentConfig) +} + +func (t *wrappedTPM20) loadAKWithParent(opaqueBlob []byte, parent ParentKeyConfig) (*AK, error) { + hnd, sKey, err := t.deserializeAndLoad(opaqueBlob, parent) if err != nil { return nil, fmt.Errorf("cannot load attestation key: %v", err) } @@ -320,7 +417,11 @@ func (t *wrappedTPM20) loadAK(opaqueBlob []byte) (*AK, error) { } func (t *wrappedTPM20) loadKey(opaqueBlob []byte) (*Key, error) { - hnd, sKey, err := t.deserializeAndLoad(opaqueBlob) + return t.loadKeyWithParent(opaqueBlob, defaultParentConfig) +} + +func (t *wrappedTPM20) loadKeyWithParent(opaqueBlob []byte, parent ParentKeyConfig) (*Key, error) { + hnd, sKey, err := t.deserializeAndLoad(opaqueBlob, parent) if err != nil { return nil, fmt.Errorf("cannot load signing key: %v", err) } @@ -411,7 +512,7 @@ func (k *wrappedKey20) close(t tpmBase) error { return tpm2.FlushContext(tpm.rwc, k.hnd) } -func (k *wrappedKey20) activateCredential(tb tpmBase, in EncryptedCredential) ([]byte, error) { +func (k *wrappedKey20) activateCredential(tb tpmBase, in EncryptedCredential, ek *EK) ([]byte, error) { t, ok := tb.(*wrappedTPM20) if !ok { return nil, fmt.Errorf("expected *wrappedTPM20, got %T", tb) @@ -426,7 +527,7 @@ func (k *wrappedKey20) activateCredential(tb tpmBase, in EncryptedCredential) ([ } secret := in.Secret[2:] - ekHnd, _, err := t.getPrimaryKeyHandle(commonEkEquivalentHandle) + ekHnd, _, err := t.getEndorsementKeyHandle(ek) if err != nil { return nil, err } @@ -471,12 +572,12 @@ func (k *wrappedKey20) certify(tb tpmBase, handle interface{}) (*CertificationPa return certify(t.rwc, hnd, k.hnd, scheme) } -func (k *wrappedKey20) quote(tb tpmBase, nonce []byte, alg HashAlg) (*Quote, error) { +func (k *wrappedKey20) quote(tb tpmBase, nonce []byte, alg HashAlg, selectedPCRs []int) (*Quote, error) { t, ok := tb.(*wrappedTPM20) if !ok { return nil, fmt.Errorf("expected *wrappedTPM20, got %T", tb) } - return quote20(t.rwc, k.hnd, tpm2.Algorithm(alg), nonce) + return quote20(t.rwc, k.hnd, tpm2.Algorithm(alg), nonce, selectedPCRs) } func (k *wrappedKey20) attestationParameters() AttestationParameters { @@ -503,14 +604,24 @@ func (k *wrappedKey20) sign(tb tpmBase, digest []byte, pub crypto.PublicKey, opt } switch p := pub.(type) { case *ecdsa.PublicKey: - return signECDSA(t.rwc, k.hnd, digest, p.Curve) + return signECDSA(t.rwc, k.hnd, digest, p.Curve, opts) case *rsa.PublicKey: return signRSA(t.rwc, k.hnd, digest, opts) } return nil, fmt.Errorf("unsupported signing key type: %T", pub) } -func signECDSA(rw io.ReadWriter, key tpmutil.Handle, digest []byte, curve elliptic.Curve) ([]byte, error) { +func signECDSA(rw io.ReadWriter, key tpmutil.Handle, digest []byte, curve elliptic.Curve, opts crypto.SignerOpts) ([]byte, error) { + h, err := tpm2.HashToAlgorithm(opts.HashFunc()) + if err != nil { + return nil, fmt.Errorf("incorrect hash algorithm: %v", err) + } + + scheme := &tpm2.SigScheme{ + Alg: tpm2.AlgECDSA, + Hash: h, + } + // https://cs.opensource.google/go/go/+/refs/tags/go1.19.2:src/crypto/ecdsa/ecdsa.go;l=181 orderBits := curve.Params().N.BitLen() orderBytes := (orderBits + 7) / 8 @@ -522,9 +633,11 @@ func signECDSA(rw io.ReadWriter, key tpmutil.Handle, digest []byte, curve ellipt if excess > 0 { ret.Rsh(ret, uint(excess)) } - digest = ret.Bytes() + // call ret.FillBytes() here instead of ret.Bytes() to preserve leading zeroes + // that may have been dropped when converting the digest to an integer + digest = ret.FillBytes(digest) - sig, err := tpm2.Sign(rw, key, "", digest, nil, nil) + sig, err := tpm2.Sign(rw, key, "", digest, nil, scheme) if err != nil { return nil, fmt.Errorf("cannot sign: %v", err) } diff --git a/go.mod b/go.mod index 9446478c..3aaa517b 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,16 @@ module github.com/google/go-attestation -go 1.16 +go 1.20 require ( - github.com/google/go-cmp v0.5.9 - github.com/google/go-tpm v0.3.3 - github.com/google/go-tpm-tools v0.3.9 + github.com/google/go-cmp v0.6.0 + github.com/google/go-tpm v0.9.0 + github.com/google/go-tpm-tools v0.4.2 github.com/google/go-tspi v0.3.0 - golang.org/x/sys v0.0.0-20220209214540-3681064d5158 + golang.org/x/sys v0.14.0 +) + +require ( + github.com/google/certificate-transparency-go v1.1.2 // indirect + golang.org/x/crypto v0.13.0 // indirect ) diff --git a/go.sum b/go.sum index 6603320a..6d6a8bad 100644 --- a/go.sum +++ b/go.sum @@ -15,7 +15,6 @@ cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6 cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.60.0/go.mod h1:yw2G51M9IfRboUH61Us8GqCeF1PzPblB823Mn2q2eAU= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= @@ -45,8 +44,6 @@ cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2k cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/pubsub v1.5.0/go.mod h1:ZEwJccE3z93Z2HWvstpri00jOg7oO4UZDtKhwDwqF0w= -cloud.google.com/go/spanner v1.7.0/go.mod h1:sd3K2gZ9Fd0vMPLXzeCrF6fq4i63Q7aTLW/lBIfBkIk= cloud.google.com/go/spanner v1.17.0/go.mod h1:+17t2ixFwRG4lWRwE+5kipDR9Ef07Jkmc8z0IbMDKUs= cloud.google.com/go/spanner v1.18.0/go.mod h1:LvAjUXPeJRGNuGpikMULjhLj/t9cRvdc+fxRoLiugXA= cloud.google.com/go/spanner v1.25.0/go.mod h1:kQUft3x355hzzaeFbObjsvkzZDgpDkesp3v75WBnI8w= @@ -60,7 +57,6 @@ code.gitea.io/sdk/gitea v0.11.3/go.mod h1:z3uwDV/b9Ls47NGukYM9XhnHtqPh/J+t40lsUr contrib.go.opencensus.io/exporter/aws v0.0.0-20181029163544-2befc13012d0/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA= contrib.go.opencensus.io/exporter/ocagent v0.5.0/go.mod h1:ImxhfLRpxoYiSq891pBrLVhN+qmP8BTVvdH2YLs7Gl0= contrib.go.opencensus.io/exporter/stackdriver v0.12.1/go.mod h1:iwB6wGarfphGGe/e5CWqyUk/cLzKnWsOKPVW3no6OTw= -contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= contrib.go.opencensus.io/exporter/stackdriver v0.13.5/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= contrib.go.opencensus.io/exporter/stackdriver v0.13.8/go.mod h1:huNtlWx75MwO7qMs0KrMxPZXzNNWebav1Sq/pm02JdQ= contrib.go.opencensus.io/integrations/ocsql v0.1.4/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE= @@ -97,7 +93,6 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= -github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ= github.com/apache/beam v2.28.0+incompatible/go.mod h1:/8NX3Qi8vGstDLLaeaU7+lzVEu/ACaQhYjeefzQ0y1o= @@ -121,7 +116,6 @@ github.com/aws/aws-sdk-go v1.19.45/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpi github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.25.11/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.25.37/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.37.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= @@ -167,7 +161,6 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190620071333-e64a0ec8b42a/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= @@ -200,7 +193,6 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/protoc-gen-validate v0.0.14/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.3.0-java/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/etcd-io/gofail v0.0.0-20190801230047-ad7f989257ca/go.mod h1:49H/RkXP8pKaZy4h0d+NW16rSLhyVBt4o6VLJbmOqDE= @@ -214,7 +206,6 @@ github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHqu github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fullstorydev/grpcurl v1.6.0/go.mod h1:ZQ+ayqbKMJNhzLmbpCiurTVlaK2M/3nqZCxaQ2Ze/sM= github.com/fullstorydev/grpcurl v1.8.0/go.mod h1:Mn2jWbdMrQGJQ8UD62uNyMumT2acsZUCkZIqFxsQf1o= github.com/fullstorydev/grpcurl v1.8.1/go.mod h1:3BWhvHZwNO7iLXaQlojdg5NA6SxUDePli4ecpK1N7gw= github.com/fullstorydev/grpcurl v1.8.2/go.mod h1:YvWNT3xRp2KIRuvCphFodG0fKkMXwaxA9CJgKCcyzUQ= @@ -236,11 +227,9 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM= github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= -github.com/go-redis/redis v6.15.8+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -268,7 +257,6 @@ github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= -github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -286,19 +274,17 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= -github.com/google/certificate-transparency-go v1.1.1/go.mod h1:FDKqPvSXawb2ecErVRrD+nfy23RCzyl7eqVCEmlT1Zs= github.com/google/certificate-transparency-go v1.1.2-0.20210422104406-9f33727a7a18/go.mod h1:6CKh9dscIRoqc2kC6YUFICHZMT9NrClyPrRVFrdw1QQ= github.com/google/certificate-transparency-go v1.1.2-0.20210512142713-bed466244fa6/go.mod h1:aF2dp7Dh81mY8Y/zpzyXps4fQW5zQbDu2CxfpJB6NkI= github.com/google/certificate-transparency-go v1.1.2 h1:4hE0GEId6NAW28dFpC+LrRGwQX5dtmXQGDbg8+/MZOM= github.com/google/certificate-transparency-go v1.1.2/go.mod h1:3OL+HKDqHPUfdKrHVQxO6T8nDLO0HF7LRTlkIWXaWvQ= -github.com/google/go-attestation v0.3.2/go.mod h1:N0ADdnY0cr7eLJyZ75o8kofGGTUF2XrZTJuTPo5acwk= -github.com/google/go-attestation v0.4.4-0.20220404204839-8820d49b18d9/go.mod h1:KDsPHk8a2MX9g20kYSdxB21t7je5NghSaFeVn0Zu3Ao= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -311,30 +297,24 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github/v28 v28.1.1/go.mod h1:bsqJWQX05omyWVmc00nEUql9mhQyv38lDZ8kPZcQVoM= github.com/google/go-licenses v0.0.0-20210329231322-ce1d9163b77d/go.mod h1:+TYOmkVoJOpwnS0wfdsJCV9CoD5nJYsHoFk/0CrTK4M= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-replayers/grpcreplay v0.1.0/go.mod h1:8Ig2Idjpr6gifRd6pNVggX6TC1Zw6Jx74AKp7QNH2QE= github.com/google/go-replayers/httpreplay v0.1.0/go.mod h1:YKZViNhiGgqdBlUbI2MwGpq4pXxNmhJLPHQ7cv2b5no= -github.com/google/go-tpm v0.1.2-0.20190725015402-ae6dd98980d4/go.mod h1:H9HbmUG2YgV/PHITkO7p6wxEEj/v5nlsVWIwumwH2NI= -github.com/google/go-tpm v0.3.0/go.mod h1:iVLWvrPp/bHeEkxTFi9WG6K9w0iy2yIszHwZGHPbzAw= -github.com/google/go-tpm v0.3.2/go.mod h1:j71sMBTfp3X5jPHz852ZOfQMUOf65Gb/Th8pRmp7fvg= -github.com/google/go-tpm v0.3.3 h1:P/ZFNBZYXRxc+z7i5uyd8VP7MaDteuLZInzrH2idRGo= -github.com/google/go-tpm v0.3.3/go.mod h1:9Hyn3rgnzWF9XBWVk6ml6A6hNkbWjNFlDQL51BeghL4= -github.com/google/go-tpm-tools v0.0.0-20190906225433-1614c142f845/go.mod h1:AVfHadzbdzHo54inR2x1v640jdi1YSi3NauM2DUsxk0= -github.com/google/go-tpm-tools v0.2.0/go.mod h1:npUd03rQ60lxN7tzeBJreG38RvWwme2N1reF/eeiBk4= -github.com/google/go-tpm-tools v0.2.1/go.mod h1:npUd03rQ60lxN7tzeBJreG38RvWwme2N1reF/eeiBk4= -github.com/google/go-tpm-tools v0.3.1/go.mod h1:PSg+r5hSZI5tP3X7LBQx2sW1VSZUqZHBSrKyDqrB21U= -github.com/google/go-tpm-tools v0.3.9 h1:66nkOHZtqmHXVnqonQvPDmiPRn8lcKW3FXzynJiBphg= -github.com/google/go-tpm-tools v0.3.9/go.mod h1:22JvWmHcD5w55cs+nMeqDGDxgNS15/2pDq2cLqnc3rc= -github.com/google/go-tspi v0.2.1-0.20190423175329-115dea689aad/go.mod h1:xfMGI3G0PhxCdNVcYr1C4C+EizojDg/TXuX5by8CiHI= +github.com/google/go-sev-guest v0.9.3 h1:GOJ+EipURdeWFl/YYdgcCxyPeMgQUWlI056iFkBD8UU= +github.com/google/go-tdx-guest v0.2.3-0.20231011100059-4cf02bed9d33 h1:lRlUusuieEuqljjihCXb+Mr73VNitOYPJYWXzJKtBWs= +github.com/google/go-tpm v0.9.0 h1:sQF6YqWMi+SCXpsmS3fd21oPy/vSddwZry4JnmltHVk= +github.com/google/go-tpm v0.9.0/go.mod h1:FkNVkc6C+IsvDI9Jw1OveJmxGZUUaKxtrpOS47QWKfU= +github.com/google/go-tpm-tools v0.4.2 h1:iyaCPKt2N5Rd0yz0G8ANa022SgCNZkMpp+db6QELtvI= +github.com/google/go-tpm-tools v0.4.2/go.mod h1:fGUDZu4tw3V4hUVuFHmiYgRd0c58/IXivn9v3Ea/ck4= github.com/google/go-tspi v0.3.0 h1:ADtq8RKfP+jrTyIWIZDIYcKOMecRqNJFOew2IT0Inus= github.com/google/go-tspi v0.3.0/go.mod h1:xfMGI3G0PhxCdNVcYr1C4C+EizojDg/TXuX5by8CiHI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/licenseclassifier v0.0.0-20210325184830-bb04aff29e72/go.mod h1:qsqn2hxC+vURpyBRygGUuinTO42MFRLcsmQ/P8v94+M= +github.com/google/logger v1.1.1 h1:+6Z2geNxc9G+4D4oDO9njjjn2d0wN5d7uOo0vOIW1NQ= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -346,7 +326,6 @@ github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200507031123-427632fa3b1c/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= @@ -359,7 +338,6 @@ github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLe github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/rpmpack v0.0.0-20191226140753-aa36bfddb3a0/go.mod h1:RaTPr0KUf2K7fnZYLNDrr8rxAamWs3iNywJLtQ2AzBg= github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= -github.com/google/trillian v1.3.11/go.mod h1:0tPraVHrSDkA3BO6vKX67zgLXs6SsOAbHEivX+9mPgw= github.com/google/trillian v1.3.14-0.20210409160123-c5ea3abd4a41/go.mod h1:1dPv0CUjNQVFEDuAUFhZql16pw/VlPgaX8qj+g5pVzQ= github.com/google/trillian v1.3.14-0.20210511103300-67b5f349eefa/go.mod h1:s4jO3Ai4NSvxucdvqUHON0bCqJyoya32eNw6XJwsmNc= github.com/google/trillian v1.4.0/go.mod h1:1Bja2nEgMDlEJWWRXBUemSPG9qYw84ZYX2gHRVHlR+g= @@ -367,6 +345,7 @@ github.com/google/uuid v0.0.0-20161128191214-064e2069ce9c/go.mod h1:TIyPZe4Mgqvf github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= github.com/google/wire v0.3.0/go.mod h1:i1DMg/Lu8Sz5yYl25iOdmc5CT5qusaa+zmRWs16741s= github.com/googleapis/gax-go v2.0.2+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -380,7 +359,6 @@ github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -391,7 +369,6 @@ github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.2/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.12.1/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c= github.com/grpc-ecosystem/grpc-gateway v1.14.6/go.mod h1:zdiPV4Yse/1gnckTHtghG4GkDEdKCRJduHpTxT3/jcw= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= @@ -442,7 +419,6 @@ github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHW github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jonboulle/clockwork v0.2.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= @@ -464,7 +440,6 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -477,7 +452,6 @@ github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+ github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= github.com/letsencrypt/pkcs11key/v4 v4.0.0/go.mod h1:EFUvBDay26dErnNb70Nd0/VW3tJiIbETBPTl9ATXQag= github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= @@ -493,11 +467,8 @@ github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= -github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= @@ -534,14 +505,11 @@ github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzE github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/nishanths/predeclared v0.0.0-20190419143655-18a43bb90ffc/go.mod h1:62PewwiQTlm/7Rj+cxVYqZvDIUc+JjZq6GHAC1fsObQ= github.com/nishanths/predeclared v0.0.0-20200524104333-86fad755b4d3/go.mod h1:nt3d53pc1VYcphSCIaYAJtnPYnr3Zyn8fMq2wvPGPso= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2fSBUmeGDbRWPxyQ= github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -567,6 +535,7 @@ github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw= github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= @@ -574,6 +543,7 @@ github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0 github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -612,7 +582,6 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/pseudomuto/protoc-gen-doc v1.3.2/go.mod h1:y5+P6n3iGrbKG+9O04V5ld71in3v/bX88wUwgt+U8EA= github.com/pseudomuto/protoc-gen-doc v1.4.1/go.mod h1:exDTOVwqpp30eV/EDPFLZy3Pwr2sn6hBC1WIYH/UbIg= github.com/pseudomuto/protoc-gen-doc v1.5.0/go.mod h1:exDTOVwqpp30eV/EDPFLZy3Pwr2sn6hBC1WIYH/UbIg= github.com/pseudomuto/protokit v0.2.0/go.mod h1:2PdH30hxVHsup8KpBTOXTBeMVhJZVio3Q8ViKSAXT0Q= @@ -706,11 +675,9 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= -go.etcd.io/etcd v0.0.0-20200513171258-e048e166ab9c/go.mod h1:xCI7ZzBfRuGgBXyXO6yfWfDmlWd35khcWpUa4L0xI/k= go.etcd.io/etcd/api/v3 v3.5.0-alpha.0/go.mod h1:mPcW6aZJukV6Aa81LSKpBjQXTWlXB5r74ymPoSWa3Sw= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= @@ -761,7 +728,6 @@ go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= @@ -785,9 +751,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191117063200-497ca9f6d64f/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= 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= @@ -931,7 +896,6 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191119060738-e882bf8e40c2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -960,7 +924,6 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -968,7 +931,6 @@ golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210316092937-0b90fd5c4c48/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -979,13 +941,11 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210629170331-7dc0b73dc9fb/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 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= @@ -999,7 +959,6 @@ golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxb 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= -golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1055,9 +1014,6 @@ golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200522201501-cb1345f3a375/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200626171337-aa94e735be7f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200630154851-b2d8b0336632/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200706234117-b22de6825cf7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200717024301-6ddee64345a6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= @@ -1136,7 +1092,6 @@ google.golang.org/genproto v0.0.0-20190620144150-6af8c5fc6601/go.mod h1:z3L6/3dT google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= @@ -1157,8 +1112,6 @@ google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200626011028-ee7919e894b5/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200707001353-8e8330bf89df/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -1199,13 +1152,11 @@ google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ij google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.0/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= @@ -1238,8 +1189,7 @@ google.golang.org/protobuf v1.25.1-0.20200805231151-a709e31e5d12/go.mod h1:9JNX7 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1265,7 +1215,6 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.6/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=