Return the CSR public key fingerprint for tpm format

This commit is contained in:
Herman Slatman 2023-03-13 23:30:39 +01:00
parent 6297bace1a
commit e1c7e8f00b
No known key found for this signature in database
GPG key ID: F4D8A44EA0A75A4F

View file

@ -445,9 +445,10 @@ func deviceAttest01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose
az.Fingerprint = data.Fingerprint
case "tpm":
data, err := doTPMAttestationFormat(ctx, ch, db, &att)
data, err := doTPMAttestationFormat(ctx, ch, db, jwk, &att)
if err != nil {
var acmeError *Error
q.Q("att error: %w", err)
if errors.As(err, &acmeError) {
if acmeError.Status == 500 {
return acmeError
@ -457,19 +458,10 @@ func deviceAttest01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose
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.
// Update attestation key fingerprint to compare against the CSR
az.Fingerprint = data.Fingerprint
default:
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 {
Certificate *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)
prov, ok := p.(*provisioner.ACME)
if !ok {
@ -634,25 +625,51 @@ func doTPMAttestationFormat(ctx context.Context, ch *Challenge, db DB, att *atte
CreateSignature: sig,
CreateAttestation: certInfo,
}
opts := attest.VerifyOpts{
verifyOpts := attest.VerifyOpts{
Public: leaf.PublicKey, // signature created by the AK that attested the key
Hash: hash,
}
if err = certificationParameters.Verify(opts); err != nil {
if err = certificationParameters.Verify(verifyOpts); err != nil {
return nil, WrapError(ErrorBadAttestationStatementType, err, "invalid certification parameters")
}
tpmCertInfo, err := tpm2.DecodeAttestationData([]byte(certInfo))
tpmCertInfo, err := tpm2.DecodeAttestationData(certInfo)
if err != nil {
return nil, WrapError(ErrorBadAttestationStatementType, err, "failed decoding attestation data")
}
// TODO(hs): pass more attestation data, so that that can be recorded too?
return &tpmAttestationData{
expectedDigest, err := keyAuthDigest(jwk, ch.Token)
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,
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