@@ -7,20 +7,17 @@ import (
7
7
"encoding/asn1"
8
8
"errors"
9
9
"fmt"
10
- "math/big"
11
10
"strings"
12
11
13
12
"github.com/go-webauthn/webauthn/metadata"
14
13
"github.com/go-webauthn/webauthn/protocol/webauthncose"
15
-
16
- "github.com/go-webauthn/webauthn/protocol/googletpm"
14
+ "github.com/google/go-tpm/tpm2"
17
15
)
18
16
19
17
var tpmAttestationKey = "tpm"
20
18
21
19
func init () {
22
20
RegisterAttestationFormat (tpmAttestationKey , verifyTPMFormat )
23
- googletpm .UseTPM20LengthPrefixSize ()
24
21
}
25
22
26
23
func verifyTPMFormat (att AttestationObject , clientDataHash []byte ) (string , []interface {}, error ) {
@@ -74,27 +71,26 @@ func verifyTPMFormat(att AttestationObject, clientDataHash []byte) (string, []in
74
71
75
72
// Verify that the public key specified by the parameters and unique fields of pubArea
76
73
// is identical to the credentialPublicKey in the attestedCredentialData in authenticatorData.
77
- pubArea , err := googletpm .DecodePublic (pubAreaBytes )
74
+ pubArea , err := tpm2 .DecodePublic (pubAreaBytes )
78
75
if err != nil {
79
76
return "" , nil , ErrAttestationFormat .WithDetails ("Unable to decode TPMT_PUBLIC in attestation statement" )
80
77
}
81
78
82
79
key , err := webauthncose .ParsePublicKey (att .AuthData .AttData .CredentialPublicKey )
83
80
if err != nil {
84
- return tpmAttestationKey , nil , err
81
+ return "" , nil , err
85
82
}
86
83
switch key := key .(type ) {
87
84
case webauthncose.EC2PublicKeyData :
88
85
if pubArea .ECCParameters .CurveID != key .TPMCurveID () ||
89
- pubArea .ECCParameters .Point .X . Cmp ( new (big. Int ). SetBytes ( key .XCoord )) != 0 ||
90
- pubArea .ECCParameters .Point .Y . Cmp ( new (big. Int ). SetBytes ( key .YCoord )) != 0 {
91
- return tpmAttestationKey , nil , ErrAttestationFormat .WithDetails ("Mismatch between ECCParameters in pubArea and credentialPublicKey" )
86
+ ! bytes . Equal ( pubArea .ECCParameters .Point .XRaw , key .XCoord ) ||
87
+ ! bytes . Equal ( pubArea .ECCParameters .Point .YRaw , key .YCoord ) {
88
+ return "" , nil , ErrAttestationFormat .WithDetails ("Mismatch between ECCParameters in pubArea and credentialPublicKey" )
92
89
}
93
90
case webauthncose.RSAPublicKeyData :
94
- mod := new (big.Int ).SetBytes (key .Modulus )
95
91
exp := uint32 (key .Exponent [0 ]) + uint32 (key .Exponent [1 ])<< 8 + uint32 (key .Exponent [2 ])<< 16
96
- if pubArea .RSAParameters .Modulus . Cmp ( mod ) != 0 ||
97
- pubArea .RSAParameters .Exponent != exp {
92
+ if ! bytes . Equal ( pubArea .RSAParameters .ModulusRaw , key . Modulus ) ||
93
+ pubArea .RSAParameters .Exponent () != exp {
98
94
return "" , nil , ErrAttestationFormat .WithDetails ("Mismatch between RSAParameters in pubArea and credentialPublicKey" )
99
95
}
100
96
default :
@@ -105,34 +101,34 @@ func verifyTPMFormat(att AttestationObject, clientDataHash []byte) (string, []in
105
101
attToBeSigned := append (att .RawAuthData , clientDataHash ... )
106
102
107
103
// Validate that certInfo is valid:
108
- certInfo , err := googletpm .DecodeAttestationData (certInfoBytes )
104
+ // 1/4 Verify that magic is set to TPM_GENERATED_VALUE, handled here
105
+ certInfo , err := tpm2 .DecodeAttestationData (certInfoBytes )
109
106
if err != nil {
110
- return tpmAttestationKey , nil , err
111
- }
112
- // 1/4 Verify that magic is set to TPM_GENERATED_VALUE.
113
- if certInfo .Magic != 0xff544347 {
114
- return "" , nil , ErrAttestationFormat .WithDetails ("Magic is not set to TPM_GENERATED_VALUE" )
107
+ return "" , nil , err
115
108
}
109
+
116
110
// 2/4 Verify that type is set to TPM_ST_ATTEST_CERTIFY.
117
- if certInfo .Type != googletpm .TagAttestCertify {
111
+ if certInfo .Type != tpm2 .TagAttestCertify {
118
112
return "" , nil , ErrAttestationFormat .WithDetails ("Type is not set to TPM_ST_ATTEST_CERTIFY" )
119
113
}
120
114
// 3/4 Verify that extraData is set to the hash of attToBeSigned using the hash algorithm employed in "alg".
121
115
f := webauthncose .HasherFromCOSEAlg (coseAlg )
122
116
h := f ()
123
117
h .Write (attToBeSigned )
124
118
if ! bytes .Equal (certInfo .ExtraData , h .Sum (nil )) {
125
- return tpmAttestationKey , nil , ErrAttestationFormat .WithDetails ("ExtraData is not set to hash of attToBeSigned" )
119
+ return "" , nil , ErrAttestationFormat .WithDetails ("ExtraData is not set to hash of attToBeSigned" )
126
120
}
127
121
// 4/4 Verify that attested contains a TPMS_CERTIFY_INFO structure as specified in
128
122
// [TPMv2-Part2] section 10.12.3, whose name field contains a valid Name for pubArea,
129
123
// as computed using the algorithm in the nameAlg field of pubArea
130
124
// using the procedure specified in [TPMv2-Part1] section 16.
131
- f , err = certInfo .AttestedCertifyInfo .Name .Digest .Alg .HashConstructor ()
132
- h = f ()
133
- h .Write (pubAreaBytes )
134
- if ! bytes .Equal (h .Sum (nil ), certInfo .AttestedCertifyInfo .Name .Digest .Value ) {
135
- return tpmAttestationKey , nil , ErrAttestationFormat .WithDetails ("Hash value mismatch attested and pubArea" )
125
+ matches , err := certInfo .AttestedCertifyInfo .Name .MatchesPublic (pubArea )
126
+ if err != nil {
127
+ return "" , nil , err
128
+ }
129
+
130
+ if ! matches {
131
+ return "" , nil , ErrAttestationFormat .WithDetails ("Hash value mismatch attested and pubArea" )
136
132
}
137
133
138
134
// Note that the remaining fields in the "Standard Attestation Structure"
@@ -176,7 +172,7 @@ func verifyTPMFormat(att AttestationObject, clientDataHash []byte) (string, []in
176
172
if ext .Id .Equal ([]int {2 , 5 , 29 , 17 }) {
177
173
manufacturer , model , version , err = parseSANExtension (ext .Value )
178
174
if err != nil {
179
- return tpmAttestationKey , nil , err
175
+ return "" , nil , err
180
176
}
181
177
}
182
178
}
@@ -186,7 +182,7 @@ func verifyTPMFormat(att AttestationObject, clientDataHash []byte) (string, []in
186
182
}
187
183
188
184
if ! isValidTPMManufacturer (manufacturer ) {
189
- return tpmAttestationKey , nil , ErrAttestationFormat .WithDetails ("Invalid TPM manufacturer" )
185
+ return "" , nil , ErrAttestationFormat .WithDetails ("Invalid TPM manufacturer" )
190
186
}
191
187
192
188
// 4/6 The Extended Key Usage extension MUST contain the "joint-iso-itu-t(2) internationalorganizations(23) 133 tcg-kp(8) tcg-kp-AIKCertificate(3)" OID.
@@ -202,7 +198,7 @@ func verifyTPMFormat(att AttestationObject, clientDataHash []byte) (string, []in
202
198
}
203
199
}
204
200
if ! ekuValid {
205
- return tpmAttestationKey , nil , ErrAttestationFormat .WithDetails ("AIK certificate missing EKU" )
201
+ return "" , nil , ErrAttestationFormat .WithDetails ("AIK certificate missing EKU" )
206
202
}
207
203
208
204
// 5/6 The Basic Constraints extension MUST have the CA component set to false.
@@ -221,7 +217,7 @@ func verifyTPMFormat(att AttestationObject, clientDataHash []byte) (string, []in
221
217
}
222
218
}
223
219
if constraints .IsCA {
224
- return tpmAttestationKey , nil , ErrAttestationFormat .WithDetails ("AIK certificate basic constraints missing or CA is true" )
220
+ return "" , nil , ErrAttestationFormat .WithDetails ("AIK certificate basic constraints missing or CA is true" )
225
221
}
226
222
// 6/6 An Authority Information Access (AIA) extension with entry id-ad-ocsp and a CRL Distribution Point
227
223
// extension [RFC5280] are both OPTIONAL as the status of many attestation certificates is available
0 commit comments