Return the CSR public key fingerprint for `tpm` format

pull/1063/head
Herman Slatman 1 year ago
parent 6297bace1a
commit e1c7e8f00b
No known key found for this signature in database
GPG Key ID: F4D8A44EA0A75A4F

@ -445,9 +445,10 @@ func deviceAttest01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose
az.Fingerprint = data.Fingerprint az.Fingerprint = data.Fingerprint
case "tpm": case "tpm":
data, err := doTPMAttestationFormat(ctx, ch, db, &att) data, err := doTPMAttestationFormat(ctx, ch, db, jwk, &att)
if err != nil { if err != nil {
var acmeError *Error var acmeError *Error
q.Q("att error: %w", err)
if errors.As(err, &acmeError) { if errors.As(err, &acmeError) {
if acmeError.Status == 500 { if acmeError.Status == 500 {
return acmeError return acmeError
@ -457,19 +458,10 @@ func deviceAttest01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose
return WrapErrorISE(err, "error validating attestation") return WrapErrorISE(err, "error validating attestation")
} }
expectedDigest, err := keyAuthDigest(jwk, ch.Token)
if err != nil {
return fmt.Errorf("error creating key auth digest: %w", err)
}
// verify the WebAuthn object contains the expect key authorization digest, which is carried
// within the encoded `certInfo` property of the attestation statement.
if subtle.ConstantTimeCompare(expectedDigest, data.ExtraData) == 0 {
return storeError(ctx, db, ch, true, NewError(ErrorBadAttestationStatementType, "key authorization doesn't match"))
}
// TODO(hs): more properties to verify? Apple method has nonce, check for permanent identifier. // TODO(hs): more properties to verify? Apple method has nonce, check for permanent identifier.
// Update attestation key fingerprint to compare against the CSR
az.Fingerprint = data.Fingerprint
default: default:
return storeError(ctx, db, ch, true, NewError(ErrorBadAttestationStatementType, "unexpected attestation object format")) return storeError(ctx, db, ch, true, NewError(ErrorBadAttestationStatementType, "unexpected attestation object format"))
} }
@ -505,11 +497,10 @@ func keyAuthDigest(jwk *jose.JSONWebKey, token string) ([]byte, error) {
type tpmAttestationData struct { type tpmAttestationData struct {
Certificate *x509.Certificate Certificate *x509.Certificate
VerifiedChains [][]*x509.Certificate VerifiedChains [][]*x509.Certificate
ExtraData []byte // TODO(hs): rename this to KeyAuthorization to reflect its usage? Fingerprint string
} }
func doTPMAttestationFormat(ctx context.Context, ch *Challenge, db DB, att *attestationObject) (*tpmAttestationData, error) { func doTPMAttestationFormat(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSONWebKey, att *attestationObject) (*tpmAttestationData, error) {
p := MustProvisionerFromContext(ctx) p := MustProvisionerFromContext(ctx)
prov, ok := p.(*provisioner.ACME) prov, ok := p.(*provisioner.ACME)
if !ok { if !ok {
@ -634,25 +625,51 @@ func doTPMAttestationFormat(ctx context.Context, ch *Challenge, db DB, att *atte
CreateSignature: sig, CreateSignature: sig,
CreateAttestation: certInfo, CreateAttestation: certInfo,
} }
opts := attest.VerifyOpts{ verifyOpts := attest.VerifyOpts{
Public: leaf.PublicKey, // signature created by the AK that attested the key Public: leaf.PublicKey, // signature created by the AK that attested the key
Hash: hash, Hash: hash,
} }
if err = certificationParameters.Verify(opts); err != nil { if err = certificationParameters.Verify(verifyOpts); err != nil {
return nil, WrapError(ErrorBadAttestationStatementType, err, "invalid certification parameters") return nil, WrapError(ErrorBadAttestationStatementType, err, "invalid certification parameters")
} }
tpmCertInfo, err := tpm2.DecodeAttestationData([]byte(certInfo)) tpmCertInfo, err := tpm2.DecodeAttestationData(certInfo)
if err != nil { if err != nil {
return nil, WrapError(ErrorBadAttestationStatementType, err, "failed decoding attestation data") return nil, WrapError(ErrorBadAttestationStatementType, err, "failed decoding attestation data")
} }
// TODO(hs): pass more attestation data, so that that can be recorded too? expectedDigest, err := keyAuthDigest(jwk, ch.Token)
return &tpmAttestationData{ if err != nil {
return nil, WrapError(ErrorBadAttestationStatementType, err, "failed creating key auth digest")
}
// verify the WebAuthn object contains the expect key authorization digest, which is carried
// within the encoded `certInfo` property of the attestation statement.
if subtle.ConstantTimeCompare(expectedDigest, []byte(tpmCertInfo.ExtraData)) == 0 {
return nil, NewError(ErrorBadAttestationStatementType, "key authorization doesn not match")
}
pub, err := tpm2.DecodePublic(pubArea)
if err != nil {
return nil, WrapError(ErrorBadAttestationStatementType, err, "failed decoding pubArea")
}
publicKey, err := pub.Key()
if err != nil {
return nil, WrapError(ErrorBadAttestationStatementType, err, "failed getting public key")
}
data := &tpmAttestationData{
Certificate: leaf, Certificate: leaf,
VerifiedChains: verifiedChains, VerifiedChains: verifiedChains,
ExtraData: []byte(tpmCertInfo.ExtraData), }
}, nil
if data.Fingerprint, err = keyutil.Fingerprint(publicKey); err != nil {
return nil, WrapErrorISE(err, "error calculating key fingerprint")
}
// TODO(hs): pass more attestation data, so that that can be used/recorded too?
return data, nil
} }
// Apple Enterprise Attestation Root CA from // Apple Enterprise Attestation Root CA from

Loading…
Cancel
Save