Skip to content

Commit

Permalink
Merge branch 'herman/windows-hacking' into surrogate
Browse files Browse the repository at this point in the history
  • Loading branch information
hslatman committed Jun 27, 2023
2 parents e172914 + ce1f4b5 commit cf579e5
Show file tree
Hide file tree
Showing 23 changed files with 537 additions and 234 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/golangci-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
8 changes: 4 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -62,7 +62,7 @@ jobs:
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
Expand Down
4 changes: 2 additions & 2 deletions attest/activation.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand Down
12 changes: 4 additions & 8 deletions attest/application_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,17 +72,13 @@ 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

// QualifyingData is data provided from outside to the TPM when an attestation
// operation is performed. The TPM doesn't interpret the data, but does sign over
// it. It can be used as a nonce to ensure freshness of an attestation.
QualifyingData []byte

// Name is used to specify a name for the key, instead of generating
// a random one. If provided, the Prefix will be ignored. This property
// is only used on Windows.
// a random one. This property is only used on Windows.
Name string

// Prefix is used to specify a custom prefix for the key, instead of
// using the default `app`. This property is only used on Windows.
Prefix string
}

// defaultConfig is used when no other configuration is specified.
Expand Down
2 changes: 1 addition & 1 deletion attest/attest-tool/internal/internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
package internal

import (
"github.com/google/go-tpm/tpm2"
"github.com/google/go-tpm/legacy/tpm2"
"github.com/smallstep/go-attestation/attest"
)

Expand Down
40 changes: 28 additions & 12 deletions attest/attest.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -101,8 +102,8 @@ const (
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{}, qualifyingData []byte) (*CertificationParameters, error)
blobs() ([]byte, []byte, error)
Expand All @@ -111,6 +112,10 @@ type ak interface {
// AK represents a key which can be used for attestation.
type AK struct {
ak ak

// The EK that will be used for attestation.
// If nil, an RSA EK with handle 0x81010001 will be used.
ek *EK
}

// Close unloads the AK from the system.
Expand All @@ -131,15 +136,24 @@ func (k *AK) Marshal() ([]byte, error) {
//
// 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, k.ek)
}

// Quote returns a quote over the platform state, signed by the AK.
//
// 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
Expand All @@ -161,17 +175,16 @@ func (k *AK) Blobs() (pub, priv []byte, err error) {
return k.ak.blobs()
}

// 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 {
// Name is used to specify a name for the key, instead of generating
// a random one. If provided, the Prefix will be ignored. This property
// is only used on Windows.
// a random one. This property is only used on Windows.
Name string

// Prefix is used to specify a custom prefix for the key, instead of
// using the default `app`. This property is only used on Windows.
Prefix string
// The EK that will be used for attestation.
// If nil, an RSA EK with handle 0x81010001 will be used.
// If not nil, it must be one of EKs returned from TPM.EKs().
EK *EK
}

// EncryptedCredential represents encrypted parameters which must be activated
Expand Down Expand Up @@ -219,6 +232,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
Expand Down
77 changes: 61 additions & 16 deletions attest/attest_simulated_tpm20_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,25 +98,37 @@ 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)

var akConfig *AKConfig
if useEK {
akConfig = &AKConfig{EK: &ek}
}
ak, err := tpm.NewAK(akConfig)
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 {
Expand Down Expand Up @@ -246,24 +258,57 @@ func TestSimTPM20PCRs(t *testing.T) {
}
}

func TestSimTPM20Persistence(t *testing.T) {
func TestSimTPM20PersistenceSRK(t *testing.T) {
sim, tpm := setupSimulatedTPM(t)
defer sim.Close()

ekHnd, _, err := tpm.tpm.(*wrappedTPM20).getPrimaryKeyHandle(commonEkEquivalentHandle)
srkHnd, _, err := tpm.tpm.(*wrappedTPM20).getStorageRootKeyHandle(commonSrkEquivalentHandle)
if err != nil {
t.Fatalf("getStorageRootKeyHandle() failed: %v", err)
}
if srkHnd != commonSrkEquivalentHandle {
t.Fatalf("bad SRK-equivalent handle: got 0x%x, wanted 0x%x", srkHnd, commonSrkEquivalentHandle)
}

srkHnd, p, err := tpm.tpm.(*wrappedTPM20).getStorageRootKeyHandle(commonSrkEquivalentHandle)
if err != nil {
t.Fatalf("second getStorageRootKeyHandle() failed: %v", err)
}
if srkHnd != commonSrkEquivalentHandle {
t.Fatalf("bad SRK-equivalent handle: got 0x%x, wanted 0x%x", srkHnd, commonSrkEquivalentHandle)
}
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")
Expand Down
9 changes: 4 additions & 5 deletions attest/attest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ package attest

import (
"bytes"
"crypto"
"flag"
"fmt"
"reflect"
Expand Down Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion attest/attest_tpm12_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Loading

0 comments on commit cf579e5

Please sign in to comment.