File: example_test.go

package info (click to toggle)
golang-github-google-go-attestation 0.5.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,260 kB
  • sloc: sh: 158; makefile: 22
file content (199 lines) | stat: -rw-r--r-- 5,054 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
package attest_test

import (
	"crypto/subtle"
	"flag"
	"log"
	"testing"

	"github.com/google/go-attestation/attest"
)

var (
	testExamples = flag.Bool("test-examples", false, "Enable tests for examples.")
)

func ExampleAK() {
	tpm, err := attest.OpenTPM(nil)
	if err != nil {
		log.Fatalf("Failed to open the 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)
	}
	// Save a re-loadable representation to blob.
	blob, err := ak.Marshal()
	if err != nil {
		log.Fatalf("Failed to marshal AK: %v", err)
	}
	// Close our handle to the AK.
	if err := ak.Close(tpm); err != nil {
		log.Fatalf("Failed to close AK: %v", err)
	}

	// Re-load the created AK from the blob.
	ak, err = tpm.LoadAK(blob)
	if err != nil {
		log.Fatalf("Failed to load AK: %v", err)
	}
	if err := ak.Close(tpm); err != nil {
		log.Fatalf("Failed to close AK: %v", err)
	}
}

func ExampleAK_credentialActivation() {
	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.
	ek, err := tpm.EKs()
	if err != nil {
		log.Fatalf("Failed to enumerate EKs: %v", err)
	}

	// Read parameters necessary to generate a challenge.
	ap := ak.AttestationParameters()

	// Generate a credential activation challenge (usually done on the server).
	activation := attest.ActivationParameters{
		TPMVersion: tpm.Version(),
		EK:         ek[0].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.ActivateCredential(tpm, *challenge)
	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 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) {
	if !*testExamples {
		t.SkipNow()
	}
	ExampleTPM_AttestPlatform()
}

func ExampleTPM_AttestPlatform() {
	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)

	// The nonce would typically be provided by the server.
	nonce := []byte{1, 2, 3, 4, 5, 6, 7, 8}

	// Perform an attestation against the state of the plaform. Usually, you
	// would pass a nil config, and the event log would be read from the
	// platform. To ensure this example runs on platforms without event logs,
	// we pass a fake EventLog value.
	att, err := tpm.AttestPlatform(ak, nonce, &attest.PlatformAttestConfig{
		EventLog: []byte{0},
	})
	if err != nil {
		log.Fatalf("Failed to attest the platform state: %v", err)
	}

	// Construct an AKPublic struct from the parameters of the key. This
	// will be used to  verify the quote signatures.
	pub, err := attest.ParseAKPublic(tpm.Version(), ak.AttestationParameters().Public)
	if err != nil {
		log.Fatalf("Failed to parse AK public: %v", err)
	}

	for i, q := range att.Quotes {
		if err := pub.Verify(q, att.PCRs, nonce); err != nil {
			log.Fatalf("quote[%d] verification failed: %v", i, err)
		}
	}
}