X Tutup
Skip to content

Commit b588db1

Browse files
authored
Allow multiple key-compromise revocation requests (letsencrypt#5666)
Remove the `GoodKey` check from `validSelfAuthenticatedJWS`, so that the verification performed by `RevokeCertificate`'s `revokeCertByJWK` path doesn't bail out early if the key being used to sign the revocation request has already been blocklisted (most likely because someone else has observed the same compromise and already submitted a similar revocation request). In turn, add the `GoodKey` check to `validSelfAuthenticatedPOST`, the only other function that relies on `validSelfAuthenticatedJWS` as a helper. This ensures that other self-authenticated code paths (namely `NewAccount`) continue to enforce our key policies. Fixes letsencrypt#5662
1 parent 6c85ae0 commit b588db1

File tree

1 file changed

+26
-14
lines changed

1 file changed

+26
-14
lines changed

wfe2/verify.go

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -634,12 +634,17 @@ func (wfe *WebFrontEndImpl) validPOSTAsGETForAccount(
634634
// is only used for creating new accounts or revoking a certificate by signing
635635
// the request with the private key corresponding to the certificate's public
636636
// key and embedding that public key in the JWS. All other request should be
637-
// validated using `validJWSforAccount`. If the JWS validates (e.g. the JWS is
638-
// well formed, verifies with the JWK embedded in it, the JWK meets
639-
// policy/algorithm requirements, has the correct URL and includes a valid
640-
// nonce) then `validSelfAuthenticatedJWS` returns the validated JWS body and
641-
// the JWK that was embedded in the JWS. Otherwise if the valid JWS conditions
642-
// are not met or an error occurs only a problem is returned
637+
// validated using `validJWSforAccount`.
638+
// If the JWS validates (e.g. the JWS is well formed, verifies with the JWK
639+
// embedded in it, has the correct URL, and includes a valid nonce) then
640+
// `validSelfAuthenticatedJWS` returns the validated JWS body and the JWK that
641+
// was embedded in the JWS. Otherwise if the valid JWS conditions are not met or
642+
// an error occurs only a problem is returned.
643+
// Note that this function does *not* enforce that the JWK abides by our goodkey
644+
// policies. This is because this method is used by the RevokeCertificate path,
645+
// which must allow JWKs which are signed by blocklisted (i.e. already revoked
646+
// due to compromise) keys, in case multiple clients attempt to revoke the same
647+
// cert.
643648
func (wfe *WebFrontEndImpl) validSelfAuthenticatedJWS(
644649
ctx context.Context,
645650
jws *jose.JSONWebSignature,
@@ -651,12 +656,6 @@ func (wfe *WebFrontEndImpl) validSelfAuthenticatedJWS(
651656
return nil, nil, prob
652657
}
653658

654-
// If the key doesn't meet the GoodKey policy return a problem immediately
655-
if err := wfe.keyPolicy.GoodKey(ctx, pubKey.Key); err != nil {
656-
wfe.stats.joseErrorCount.With(prometheus.Labels{"type": "JWKRejectedByGoodKey"}).Inc()
657-
return nil, nil, probs.BadPublicKey(err.Error())
658-
}
659-
660659
// Verify the JWS with the embedded JWK
661660
payload, prob := wfe.validJWSForKey(ctx, jws, pubKey, request, logEvent)
662661
if prob != nil {
@@ -667,7 +666,8 @@ func (wfe *WebFrontEndImpl) validSelfAuthenticatedJWS(
667666
}
668667

669668
// validSelfAuthenticatedPOST checks that a given POST request has a valid JWS
670-
// using `validSelfAuthenticatedJWS`.
669+
// using `validSelfAuthenticatedJWS`. It enforces that the JWK abides by our
670+
// goodkey policies (key algorithm, length, blocklist, etc).
671671
func (wfe *WebFrontEndImpl) validSelfAuthenticatedPOST(
672672
ctx context.Context,
673673
request *http.Request,
@@ -677,8 +677,20 @@ func (wfe *WebFrontEndImpl) validSelfAuthenticatedPOST(
677677
if prob != nil {
678678
return nil, nil, prob
679679
}
680+
680681
// Extract and validate the embedded JWK from the parsed JWS
681-
return wfe.validSelfAuthenticatedJWS(ctx, jws, request, logEvent)
682+
payload, pubKey, prob := wfe.validSelfAuthenticatedJWS(ctx, jws, request, logEvent)
683+
if prob != nil {
684+
return nil, nil, prob
685+
}
686+
687+
// If the key doesn't meet the GoodKey policy return a problem
688+
if err := wfe.keyPolicy.GoodKey(ctx, pubKey.Key); err != nil {
689+
wfe.stats.joseErrorCount.With(prometheus.Labels{"type": "JWKRejectedByGoodKey"}).Inc()
690+
return nil, nil, probs.BadPublicKey(err.Error())
691+
}
692+
693+
return payload, pubKey, nil
682694
}
683695

684696
// rolloverRequest is a client request to change the key for the account ID

0 commit comments

Comments
 (0)
X Tutup