Skip to content

Commit 60adf13

Browse files
authored
attest: ActivateCredentialWithEK() method that can be used with non-default EKs. (#340)
1 parent a56e8c4 commit 60adf13

File tree

3 files changed

+69
-7
lines changed

3 files changed

+69
-7
lines changed

attest/attest.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,13 +131,24 @@ func (k *AK) Marshal() ([]byte, error) {
131131
}
132132

133133
// ActivateCredential decrypts the secret using the key to prove that the AK
134-
// was generated on the same TPM as the EK.
134+
// was generated on the same TPM as the EK. This method can be used with TPMs
135+
// that have the default EK, i.e. RSA EK with handle 0x81010001.
135136
//
136137
// This operation is synonymous with TPM2_ActivateCredential.
137138
func (k *AK) ActivateCredential(tpm *TPM, in EncryptedCredential) (secret []byte, err error) {
138139
return k.ak.activateCredential(tpm.tpm, in, k.ek)
139140
}
140141

142+
// ActivateCredential decrypts the secret using the key to prove that the AK
143+
// was generated on the same TPM as the EK. This method can be used with TPMs
144+
// that have an ECC EK. The 'ek' argument must be one of EKs returned from
145+
// TPM.EKs() or TPM.EKCertificates().
146+
//
147+
// This operation is synonymous with TPM2_ActivateCredential.
148+
func (k *AK) ActivateCredentialWithEK(tpm *TPM, in EncryptedCredential, ek EK) (secret []byte, err error) {
149+
return k.ak.activateCredential(tpm.tpm, in, &ek)
150+
}
151+
141152
// Quote returns a quote over the platform state, signed by the AK.
142153
//
143154
// This is a low-level API. Consumers seeking to attest the state of the

attest/attest_simulated_tpm20_test.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,7 @@ func testActivateCredential(t *testing.T, useEK bool) {
115115
}
116116
ek := chooseEK(t, EKs)
117117

118-
var akConfig *AKConfig
119-
if useEK {
120-
akConfig = &AKConfig{EK: &ek}
121-
}
122-
ak, err := tpm.NewAK(akConfig)
118+
ak, err := tpm.NewAK(nil)
123119
if err != nil {
124120
t.Fatalf("NewAK() failed: %v", err)
125121
}
@@ -135,7 +131,12 @@ func testActivateCredential(t *testing.T, useEK bool) {
135131
t.Fatalf("Generate() failed: %v", err)
136132
}
137133

138-
decryptedSecret, err := ak.ActivateCredential(tpm, *challenge)
134+
var decryptedSecret []byte
135+
if useEK {
136+
decryptedSecret, err = ak.ActivateCredentialWithEK(tpm, *challenge, ek)
137+
} else {
138+
decryptedSecret, err = ak.ActivateCredential(tpm, *challenge)
139+
}
139140
if err != nil {
140141
t.Errorf("ak.ActivateCredential() failed: %v", err)
141142
}

attest/example_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,62 @@ func ExampleAK_credentialActivation() {
9191
}
9292
}
9393

94+
func ExampleAK_credentialActivationWithEK() {
95+
tpm, err := attest.OpenTPM(nil)
96+
if err != nil {
97+
log.Fatalf("Failed to open TPM: %v", err)
98+
}
99+
defer tpm.Close()
100+
101+
// Create a new AK.
102+
ak, err := tpm.NewAK(nil)
103+
if err != nil {
104+
log.Fatalf("Failed to create AK: %v", err)
105+
}
106+
defer ak.Close(tpm)
107+
108+
// Read the EK certificates.
109+
ekCerts, err := tpm.EKCertificates()
110+
if err != nil {
111+
log.Fatalf("Failed to enumerate EKs: %v", err)
112+
}
113+
114+
// Read parameters necessary to generate a challenge.
115+
ap := ak.AttestationParameters()
116+
117+
// Try activating with each EK certificate.
118+
for _, ek := range ekCerts {
119+
// Generate a credential activation challenge (usually done on the server).
120+
activation := attest.ActivationParameters{
121+
TPMVersion: tpm.Version(),
122+
EK: ek.Public,
123+
AK: ap,
124+
}
125+
secret, challenge, err := activation.Generate()
126+
if err != nil {
127+
log.Fatalf("Failed to generate activation challenge: %v", err)
128+
}
129+
130+
// Challenge the AK & EK properties to recieve the decrypted secret.
131+
decrypted, err := ak.ActivateCredentialWithEK(tpm, *challenge, ek)
132+
if err != nil {
133+
log.Fatalf("Failed to activate credential: %v", err)
134+
}
135+
136+
// Check that the AK completed the challenge (usually done on the server).
137+
if subtle.ConstantTimeCompare(secret, decrypted) == 0 {
138+
log.Fatal("Activation response did not match secret")
139+
}
140+
}
141+
}
142+
94143
func TestExampleAK(t *testing.T) {
95144
if !*testExamples {
96145
t.SkipNow()
97146
}
98147
ExampleAK()
99148
ExampleAK_credentialActivation()
149+
ExampleAK_credentialActivationWithEK()
100150
}
101151

102152
func TestExampleTPM(t *testing.T) {

0 commit comments

Comments
 (0)