Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: CRL #214

Merged
merged 117 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
117 commits
Select commit Hold shift + click to select a range
62aa8fc
Squashed commit of the following:
JeyJeyGao Nov 29, 2023
eef8579
test: add unit test
JeyJeyGao Dec 7, 2023
feb151c
feat: crl support
JeyJeyGao Apr 18, 2024
56da59c
fix: update
JeyJeyGao Apr 18, 2024
7d869a7
Merge remote-tracking branch 'upstream/main' into feat/crl
JeyJeyGao Apr 18, 2024
a25275e
fix: update
JeyJeyGao May 29, 2024
a262bab
fix: update crl
JeyJeyGao Jul 8, 2024
7d591d6
Merge remote-tracking branch 'upstream/main' into feat/crl
JeyJeyGao Jul 8, 2024
e66d9fd
fix: update cache
JeyJeyGao Jul 11, 2024
ac1d240
fix: update
JeyJeyGao Jul 12, 2024
e789f29
Merge remote-tracking branch 'upstream/main' into feat/crl
JeyJeyGao Jul 12, 2024
31fa5a5
fix: update test
JeyJeyGao Jul 12, 2024
039be39
fix: update
JeyJeyGao Jul 12, 2024
3b1a7ed
fix: update
JeyJeyGao Jul 12, 2024
6875035
fix: update
JeyJeyGao Jul 12, 2024
5bbd8c7
fix: update
JeyJeyGao Jul 15, 2024
39c94d3
fix: deprecate revocation Mode
JeyJeyGao Jul 15, 2024
c85d472
fix: update
JeyJeyGao Jul 15, 2024
a8db155
fix: update
JeyJeyGao Jul 15, 2024
534d11e
fix: update
JeyJeyGao Jul 16, 2024
50964ba
fix: update
JeyJeyGao Jul 16, 2024
cf593b1
fix: update
JeyJeyGao Jul 19, 2024
c172845
fix: update
JeyJeyGao Jul 19, 2024
1aa53fd
fix: update
JeyJeyGao Jul 19, 2024
2d39c35
fix: update
JeyJeyGao Jul 19, 2024
4c01b9e
fix: update
JeyJeyGao Jul 19, 2024
5787e75
fix: remove cache
JeyJeyGao Jul 22, 2024
41746fb
fix: update
JeyJeyGao Jul 22, 2024
759b727
fix: refactor
JeyJeyGao Jul 22, 2024
17da500
fix: update
JeyJeyGao Jul 23, 2024
75884a5
fix: complete test for crl package
JeyJeyGao Jul 23, 2024
e92aff7
fix: update
JeyJeyGao Jul 23, 2024
5c5c041
fix: update github action rule for branches
JeyJeyGao Jul 24, 2024
efe7708
fix: update
JeyJeyGao Jul 24, 2024
28bbf22
fix: update
JeyJeyGao Jul 24, 2024
a8f3b4b
fix: update
JeyJeyGao Jul 24, 2024
93ee863
fix: update
JeyJeyGao Jul 24, 2024
99ad04c
fix: update
JeyJeyGao Jul 24, 2024
9eb5af5
fix: update
JeyJeyGao Jul 24, 2024
38d04ce
fix: update
JeyJeyGao Jul 24, 2024
6a5357e
fix: update
JeyJeyGao Jul 24, 2024
3f9a259
fix: update
JeyJeyGao Jul 25, 2024
6bf3ca2
fix: update
JeyJeyGao Jul 25, 2024
751397b
fix: add CRL size limit
JeyJeyGao Jul 25, 2024
3170db3
fix: restore workflow and update NewWithOptions
JeyJeyGao Jul 25, 2024
8df836d
Merge branch 'main' into feat/crl_no_cache
JeyJeyGao Jul 25, 2024
041a63d
fix: update
JeyJeyGao Jul 25, 2024
e170b90
fix: update
JeyJeyGao Jul 25, 2024
1c68a17
fix: update
JeyJeyGao Jul 26, 2024
c512907
Merge 215
JeyJeyGao Aug 8, 2024
281dd64
Squashed commit of the following:
JeyJeyGao Aug 8, 2024
f833d94
Merge remote-tracking branch 'upstream/main' into feat/crl_no_cache
JeyJeyGao Aug 8, 2024
2c677c1
fix: update
JeyJeyGao Aug 8, 2024
6c0db0a
fix: update
JeyJeyGao Aug 8, 2024
cf44e31
fix: update
JeyJeyGao Aug 8, 2024
a174c20
Merge remote-tracking branch 'upstream/main' into feat/crl_no_cache
JeyJeyGao Aug 8, 2024
3a45b12
fix: update
JeyJeyGao Aug 8, 2024
950f76d
fix: update
JeyJeyGao Aug 8, 2024
e32b2d7
fix: update
JeyJeyGao Aug 8, 2024
4c41371
fix: update
JeyJeyGao Aug 8, 2024
c76c7c4
fix: resolve comments
JeyJeyGao Aug 12, 2024
9be2722
fix: update
JeyJeyGao Aug 12, 2024
3e3934c
fix: update
JeyJeyGao Aug 13, 2024
8b64025
fix: update
JeyJeyGao Aug 13, 2024
1f2b8ae
fix: update
JeyJeyGao Aug 14, 2024
1b7b38f
fix: add issuing distribution point extension
JeyJeyGao Aug 16, 2024
8f6c2c0
fix: update
JeyJeyGao Aug 16, 2024
e2acd00
fix: add delta CRL not checked error
JeyJeyGao Aug 16, 2024
174b516
fix: add comment
JeyJeyGao Aug 16, 2024
fe77e59
fix: update
JeyJeyGao Aug 16, 2024
815cc5f
fix: add license
JeyJeyGao Aug 16, 2024
c3a484e
fix: update
JeyJeyGao Aug 19, 2024
15337d4
Squashed commit of the following:
JeyJeyGao Aug 19, 2024
148a7b9
Merge remote-tracking branch 'upstream/main' into feat/crl_no_cache
JeyJeyGao Aug 19, 2024
1dafcd5
fix: update
JeyJeyGao Aug 19, 2024
1f89b49
fix: resolve comments
JeyJeyGao Aug 20, 2024
1c4cbfb
fix: update
JeyJeyGao Aug 20, 2024
3bb154f
fix: update
JeyJeyGao Aug 20, 2024
5d2ada4
fix: update
JeyJeyGao Aug 21, 2024
679dd5b
fix: update
JeyJeyGao Aug 21, 2024
f395a1a
fix: update
JeyJeyGao Aug 21, 2024
dec2a8c
fix: update
JeyJeyGao Aug 21, 2024
4a5d93b
fix: update
JeyJeyGao Aug 21, 2024
61f6c1a
fix: update
JeyJeyGao Aug 21, 2024
a42c44c
fix: update
JeyJeyGao Aug 22, 2024
9d91fb6
fix: update
JeyJeyGao Aug 22, 2024
266d814
fix: update
JeyJeyGao Aug 22, 2024
7451fbe
fix: update
JeyJeyGao Aug 22, 2024
2748835
fix: update
JeyJeyGao Aug 22, 2024
3520a7b
fix: update
JeyJeyGao Aug 22, 2024
8aadc6c
fix: update
JeyJeyGao Aug 22, 2024
22540ea
fix: update
JeyJeyGao Aug 22, 2024
bf0eadb
fix: update
JeyJeyGao Aug 22, 2024
e7fedcf
fix: update
JeyJeyGao Aug 22, 2024
d643ea2
fix: update
JeyJeyGao Aug 22, 2024
c620d85
fix: update
JeyJeyGao Aug 22, 2024
d014978
Merge branch 'main' into feat/crl_no_cache
JeyJeyGao Aug 27, 2024
ab1ed37
fix: resolve comments
JeyJeyGao Sep 11, 2024
a89a11c
Merge branch 'feat/crl_no_cache' of https://github.com/JeyJeyGao/nota…
JeyJeyGao Sep 11, 2024
a0f9d47
fix: update
JeyJeyGao Sep 11, 2024
e2cf605
fix: update
JeyJeyGao Sep 11, 2024
1ec6ed4
fix: remove CertificateHold and RemoveFromCRL check
JeyJeyGao Sep 12, 2024
04ce2f0
fix: merge CRLResult with ServerResult
JeyJeyGao Sep 12, 2024
2320086
refactor: merge CRLResult and ServerResult
JeyJeyGao Sep 12, 2024
0ebc7f9
fix: update
JeyJeyGao Sep 12, 2024
02d07e2
fix: update
JeyJeyGao Sep 12, 2024
bb2315e
fix: add license
JeyJeyGao Sep 12, 2024
4e565ec
fix: update
JeyJeyGao Sep 12, 2024
5aa15e0
fix: update
JeyJeyGao Sep 12, 2024
e2b246d
fix: update
JeyJeyGao Sep 13, 2024
982561e
fix: update
JeyJeyGao Sep 13, 2024
f4400ac
fix: update
JeyJeyGao Sep 14, 2024
f422da2
fix: update
JeyJeyGao Sep 14, 2024
50f6e6d
fix: update
JeyJeyGao Sep 14, 2024
deec55e
fix: update
JeyJeyGao Sep 14, 2024
c6132af
fix: update
JeyJeyGao Sep 14, 2024
2bf101a
fix: update
JeyJeyGao Sep 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 45 additions & 60 deletions revocation/internal/crl/crl.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ import (
"github.com/notaryproject/notation-core-go/revocation/result"
)

// RevocationMethodCRL represents the CRL revocation method
const RevocationMethodCRL = 2

var (
// oidFreshestCRL is the object identifier for the distribution point
// for the delta CRL. (See RFC 5280, Section 5.2.6)
Expand All @@ -44,7 +47,9 @@ var (
)

// maxCRLSize is the maximum size of CRL in bytes
const maxCRLSize = 64 * 1024 * 1024 // 64 MiB
//
// CRL examples: https://chasersystems.com/blog/an-analysis-of-certificate-revocation-list-sizes/
const maxCRLSize = 32 * 1024 * 1024 // 32 MiB

// CertCheckStatusOptions specifies values that are needed to check CRL
type CertCheckStatusOptions struct {
Expand All @@ -69,9 +74,11 @@ func CertCheckStatus(ctx context.Context, cert, issuer *x509.Certificate, opts C
// CRL not enabled for this certificate.
return &result.CertRevocationResult{
Result: result.ResultNonRevokable,
CRLResults: []*result.CRLResult{{
Result: result.ResultNonRevokable,
ServerResults: []*result.ServerResult{{
RevocationMethod: RevocationMethodCRL,
Result: result.ResultNonRevokable,
}},
RevocationMethod: RevocationMethodCRL,
}
}

Expand All @@ -83,9 +90,9 @@ func CertCheckStatus(ctx context.Context, cert, issuer *x509.Certificate, opts C
// point with one CRL URI, which will be cached, so checking all the URIs is
// not a performance issue.
var (
crlResults []*result.CRLResult
lastErr error
crlURL string
results []*result.ServerResult
JeyJeyGao marked this conversation as resolved.
Show resolved Hide resolved
lastErr error
crlURL string
)
for _, crlURL = range cert.CRLDistributionPoints {
baseCRL, err := download(ctx, crlURL, opts.HTTPClient)
Expand All @@ -104,31 +111,35 @@ func CertCheckStatus(ctx context.Context, cert, issuer *x509.Certificate, opts C
lastErr = fmt.Errorf("failed to check revocation status from %s: %w", crlURL, err)
break
}
crlResults = append(crlResults, crlResult)

if crlResult.Result == result.ResultRevoked {
return &result.CertRevocationResult{
Result: result.ResultRevoked,
CRLResults: crlResults,
Result: result.ResultRevoked,
ServerResults: []*result.ServerResult{crlResult},
RevocationMethod: RevocationMethodCRL,
}
}

results = append(results, crlResult)
}

if lastErr != nil {
return &result.CertRevocationResult{
Result: result.ResultUnknown,
CRLResults: []*result.CRLResult{
ServerResults: []*result.ServerResult{
{
Result: result.ResultUnknown,
URI: crlURL,
Error: lastErr,
Result: result.ResultUnknown,
Server: crlURL,
Error: lastErr,
RevocationMethod: RevocationMethodCRL,
}},
RevocationMethod: RevocationMethodCRL,
}
}

return &result.CertRevocationResult{
Result: result.ResultOK,
CRLResults: crlResults,
Result: result.ResultOK,
ServerResults: results,
RevocationMethod: RevocationMethodCRL,
}
}

Expand All @@ -140,7 +151,7 @@ func Supported(cert *x509.Certificate) bool {
func validate(crl *x509.RevocationList, issuer *x509.Certificate) error {
// check signature
if err := crl.CheckSignatureFrom(issuer); err != nil {
return fmt.Errorf("failed to verify CRL signature: %w", err)
return fmt.Errorf("CRL is not signed by CA %s: %w,", issuer.Subject, err)
}

// check validity
Expand Down Expand Up @@ -169,7 +180,7 @@ func validate(crl *x509.RevocationList, issuer *x509.Certificate) error {
}

// checkRevocation checks if the certificate is revoked or not
func checkRevocation(cert *x509.Certificate, baseCRL *x509.RevocationList, signingTime time.Time, crlURL string) (*result.CRLResult, error) {
func checkRevocation(cert *x509.Certificate, baseCRL *x509.RevocationList, signingTime time.Time, crlURL string) (*result.ServerResult, error) {
if cert == nil {
return nil, errors.New("certificate cannot be nil")
}
Expand All @@ -178,14 +189,7 @@ func checkRevocation(cert *x509.Certificate, baseCRL *x509.RevocationList, signi
return nil, errors.New("baseCRL cannot be nil")
}

// latestTempRevokedEntry contains the most recent revocation entry with
// reasons such as CertificateHold or RemoveFromCRL.
//
// If the certificate is revoked with CertificateHold, it is temporarily
// revoked. If the certificate is shown in the CRL with RemoveFromCRL,
// it is unrevoked.
var latestTempRevokedEntry *x509.RevocationListEntry
for i, revocationEntry := range baseCRL.RevokedCertificateEntries {
for _, revocationEntry := range baseCRL.RevokedCertificateEntries {
if revocationEntry.SerialNumber.Cmp(cert.SerialNumber) == 0 {
extensions, err := parseEntryExtensions(revocationEntry)
if err != nil {
Expand All @@ -197,41 +201,22 @@ func checkRevocation(cert *x509.Certificate, baseCRL *x509.RevocationList, signi
signingTime.Before(extensions.invalidityDate) {
// signing time is before the invalidity date which means the
// certificate is not revoked at the time of signing.
continue
break
}

switch revocationEntry.ReasonCode {
case int(result.CRLReasonCodeCertificateHold), int(result.CRLReasonCodeRemoveFromCRL):
// temporarily revoked or unrevoked
if latestTempRevokedEntry == nil || latestTempRevokedEntry.RevocationTime.Before(revocationEntry.RevocationTime) {
// the revocation status depends on the most recent reason
latestTempRevokedEntry = &baseCRL.RevokedCertificateEntries[i]
}
default:
// permanently revoked
return &result.CRLResult{
Result: result.ResultRevoked,
ReasonCode: result.CRLReasonCode(revocationEntry.ReasonCode),
RevocationTime: revocationEntry.RevocationTime,
URI: crlURL,
}, nil
}
// revoked
return &result.ServerResult{
Result: result.ResultRevoked,
Server: crlURL,
RevocationMethod: RevocationMethodCRL,
}, nil
}
}

if latestTempRevokedEntry != nil && latestTempRevokedEntry.ReasonCode == int(result.CRLReasonCodeCertificateHold) {
// revoked with CertificateHold
return &result.CRLResult{
Result: result.ResultRevoked,
ReasonCode: result.CRLReasonCodeCertificateHold,
RevocationTime: latestTempRevokedEntry.RevocationTime,
URI: crlURL,
}, nil
}

return &result.CRLResult{
Result: result.ResultOK,
URI: crlURL,
return &result.ServerResult{
Result: result.ResultOK,
Server: crlURL,
RevocationMethod: RevocationMethodCRL,
}, nil
}

Expand Down Expand Up @@ -273,17 +258,17 @@ func download(ctx context.Context, crlURL string, client *http.Client) (*x509.Re
return nil, fmt.Errorf("invalid CRL URL: %w", err)
}
if parsedURL.Scheme != "http" {
return nil, fmt.Errorf("unsupported scheme: %s. Only supports CRL URL in HTTP protocol", parsedURL.Scheme)
return nil, fmt.Errorf("unsupported CRL endpoint: %s. Only urls with HTTP scheme is supported", crlURL)
}

// download CRL
req, err := http.NewRequestWithContext(ctx, http.MethodGet, crlURL, nil)
if err != nil {
return nil, fmt.Errorf("failed to create CRL request: %w", err)
return nil, fmt.Errorf("failed to create CRL request %q: %w", crlURL, err)
}
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("request failed: %w", err)
return nil, fmt.Errorf("request failed for %q: %w", crlURL, err)
}
defer resp.Body.Close()

Expand All @@ -296,7 +281,7 @@ func download(ctx context.Context, crlURL string, client *http.Client) (*x509.Re
limitedReader := io.LimitReader(resp.Body, maxCRLSize)
data, err := io.ReadAll(limitedReader)
if err != nil {
return nil, fmt.Errorf("failed to read CRL response: %w", err)
return nil, fmt.Errorf("failed to read CRL response from %q: %w", resp.Request.URL, err)
}
if len(data) == maxCRLSize {
return nil, fmt.Errorf("%s %q: CRL size reached the %d MiB size limit", resp.Request.Method, resp.Request.URL, maxCRLSize/1024/1024)
Expand Down
Loading
Loading