@@ -66,6 +66,10 @@ type VerifyOpts struct {
6666 // "Calling EFI Application from Boot Option". This option is useful when
6767 // the host platform loads EFI Applications unrelated to OS boot.
6868 AllowEFIAppBeforeCallingEvent bool
69+ // HashNonce will apply the attestation key's signing scheme hash algorithm
70+ // to the input Nonce field and use the resulting digest in place of the
71+ // original Nonce.
72+ HashNonce bool
6973}
7074
7175// Bootloader refers to the second-stage bootloader that loads and transfers
@@ -114,16 +118,24 @@ func VerifyAttestation(attestation *pb.Attestation, opts VerifyOpts) (*pb.Machin
114118 return nil , fmt .Errorf ("bad options: %w" , err )
115119 }
116120
117- machineState , akPubKey , err := validateAK (attestation , opts )
121+ machineState , akPub , akPubKey , err := validateAK (attestation , opts )
118122 if err != nil {
119123 return nil , fmt .Errorf ("failed to parse and validate AK: %w" , err )
120124 }
125+ extraData := opts .Nonce
126+ if opts .HashNonce {
127+ var err error
128+ extraData , err = internal .HashNonce (akPub , extraData )
129+ if err != nil {
130+ return nil , fmt .Errorf ("failed to hash the input nonce: %w" , err )
131+ }
132+ }
121133
122134 // Attempt to replay the log against our PCRs in order of hash preference
123135 var lastErr error
124136 for _ , quote := range supportedQuotes (attestation .GetQuotes ()) {
125137 // Verify the Quote
126- if err := internal .VerifyQuote (quote , akPubKey , opts . Nonce ); err != nil {
138+ if err := internal .VerifyQuote (quote , akPubKey , extraData ); err != nil {
127139 lastErr = fmt .Errorf ("failed to verify quote: %w" , err )
128140 continue
129141 }
@@ -158,44 +170,48 @@ func VerifyAttestation(attestation *pb.Attestation, opts VerifyOpts) (*pb.Machin
158170
159171// validateAK validates AK cert in the attestation, and returns AK cert (if exists) and public key.
160172// It also pulls out the GCE Instance Info if it exists.
161- func validateAK (attestation * pb.Attestation , opts VerifyOpts ) (* pb.MachineState , crypto.PublicKey , error ) {
173+ func validateAK (attestation * pb.Attestation , opts VerifyOpts ) (* pb.MachineState , tpm2.Public , crypto.PublicKey , error ) {
174+ // If the AK Cert is not in the attestation, use the AK Public Area.
175+ akPubArea , err := tpm2 .DecodePublic (attestation .GetAkPub ())
176+ if err != nil {
177+ return nil , tpm2.Public {}, nil , fmt .Errorf ("failed to decode AK public area: %w" , err )
178+ }
179+ akPubKey , err := akPubArea .Key ()
180+ if err != nil {
181+ return nil , tpm2.Public {}, nil , fmt .Errorf ("failed to get AK public key: %w" , err )
182+ }
162183 if len (attestation .GetAkCert ()) == 0 || len (opts .TrustedRootCerts ) == 0 {
163- // If the AK Cert is not in the attestation, use the AK Public Area.
164- akPubArea , err := tpm2 .DecodePublic (attestation .GetAkPub ())
165- if err != nil {
166- return nil , nil , fmt .Errorf ("failed to decode AK public area: %w" , err )
167- }
168- akPubKey , err := akPubArea .Key ()
169- if err != nil {
170- return nil , nil , fmt .Errorf ("failed to get AK public key: %w" , err )
171- }
172184 if err := validateAKPub (akPubKey , opts ); err != nil {
173- return nil , nil , fmt .Errorf ("failed to validate AK public key: %w" , err )
185+ return nil , tpm2. Public {}, nil , fmt .Errorf ("failed to validate AK public key: %w" , err )
174186 }
175- return & pb.MachineState {}, akPubKey , nil
187+ return & pb.MachineState {}, akPubArea , akPubKey , nil
176188 }
177189
178190 // If AK Cert is presented, ignore the AK Public Area.
179191 akCert , err := x509 .ParseCertificate (attestation .GetAkCert ())
192+ certPubKey := akCert .PublicKey .(crypto.PublicKey ) // This cast cannot fail
193+ if ! internal .PubKeysEqual (certPubKey , akPubKey ) {
194+ return nil , tpm2.Public {}, nil , errors .New ("AK certificate does not match key" )
195+ }
180196 if err != nil {
181- return nil , nil , fmt .Errorf ("failed to parse AK certificate: %w" , err )
197+ return nil , tpm2. Public {}, nil , fmt .Errorf ("failed to parse AK certificate: %w" , err )
182198 }
183199 // Use intermediate certs from the attestation if they exist.
184200 certs , err := parseCerts (attestation .IntermediateCerts )
185201 if err != nil {
186- return nil , nil , fmt .Errorf ("attestation intermediates: %w" , err )
202+ return nil , tpm2. Public {}, nil , fmt .Errorf ("attestation intermediates: %w" , err )
187203 }
188204 opts .IntermediateCerts = append (opts .IntermediateCerts , certs ... )
189205
190206 if err := VerifyAKCert (akCert , opts .TrustedRootCerts , opts .IntermediateCerts ); err != nil {
191- return nil , nil , fmt .Errorf ("failed to validate AK certificate: %w" , err )
207+ return nil , tpm2. Public {}, nil , fmt .Errorf ("failed to validate AK certificate: %w" , err )
192208 }
193209 instanceInfo , err := getInstanceInfoFromExtensions (akCert .Extensions )
194210 if err != nil {
195- return nil , nil , fmt .Errorf ("error getting instance info: %v" , err )
211+ return nil , tpm2. Public {}, nil , fmt .Errorf ("error getting instance info: %v" , err )
196212 }
197213
198- return & pb.MachineState {Platform : & pb.PlatformState {InstanceInfo : instanceInfo }}, akCert .PublicKey , nil
214+ return & pb.MachineState {Platform : & pb.PlatformState {InstanceInfo : instanceInfo }}, akPubArea , akCert .PublicKey , nil
199215}
200216
201217// GetGCEInstanceInfo takes a GCE-issued x509 EK/AK certificate and tries to
0 commit comments