...
1 package checker
2
3 import (
4 "bytes"
5 "crypto/x509"
6 "fmt"
7 "math/big"
8 "sort"
9 "time"
10
11 zlint_x509 "github.com/zmap/zcrypto/x509"
12 "github.com/zmap/zlint/v3"
13
14 "github.com/letsencrypt/boulder/linter"
15 )
16
17
18
19
20
21 func Validate(crl *x509.RevocationList, issuer *x509.Certificate, ageLimit time.Duration) error {
22 zcrl, err := zlint_x509.ParseRevocationList(crl.Raw)
23 if err != nil {
24 return fmt.Errorf("parsing CRL: %w", err)
25 }
26
27 err = linter.ProcessResultSet(zlint.LintRevocationList(zcrl))
28 if err != nil {
29 return fmt.Errorf("linting CRL: %w", err)
30 }
31
32 if issuer != nil {
33 err = crl.CheckSignatureFrom(issuer)
34 if err != nil {
35 return fmt.Errorf("checking CRL signature: %w", err)
36 }
37 }
38
39 if time.Since(crl.ThisUpdate) >= ageLimit {
40 return fmt.Errorf("thisUpdate more than %s in the past: %v", ageLimit, crl.ThisUpdate)
41 }
42
43 return nil
44 }
45
46 type diffResult struct {
47 Added []*big.Int
48 Removed []*big.Int
49
50
51 }
52
53
54
55
56
57 func Diff(old, new *x509.RevocationList) (*diffResult, error) {
58 if !bytes.Equal(old.AuthorityKeyId, new.AuthorityKeyId) {
59 return nil, fmt.Errorf("CRLs were not issued by same issuer")
60 }
61
62 if !old.ThisUpdate.Before(new.ThisUpdate) {
63 return nil, fmt.Errorf("old CRL does not precede new CRL")
64 }
65
66 if old.Number.Cmp(new.Number) >= 0 {
67 return nil, fmt.Errorf("old CRL does not precede new CRL")
68 }
69
70
71 oldSerials := make([]*big.Int, len(old.RevokedCertificateEntries))
72 for i, rc := range old.RevokedCertificateEntries {
73 oldSerials[i] = rc.SerialNumber
74 }
75 sort.Slice(oldSerials, func(i, j int) bool {
76 return oldSerials[i].Cmp(oldSerials[j]) < 0
77 })
78
79 newSerials := make([]*big.Int, len(new.RevokedCertificateEntries))
80 for j, rc := range new.RevokedCertificateEntries {
81 newSerials[j] = rc.SerialNumber
82 }
83 sort.Slice(newSerials, func(i, j int) bool {
84 return newSerials[i].Cmp(newSerials[j]) < 0
85 })
86
87
88
89
90 i, j := 0, 0
91 added := make([]*big.Int, 0)
92 removed := make([]*big.Int, 0)
93 for {
94 if i >= len(oldSerials) {
95 added = append(added, newSerials[j:]...)
96 break
97 }
98 if j >= len(newSerials) {
99 removed = append(removed, oldSerials[i:]...)
100 break
101 }
102 cmp := oldSerials[i].Cmp(newSerials[j])
103 if cmp < 0 {
104 removed = append(removed, oldSerials[i])
105 i++
106 } else if cmp > 0 {
107 added = append(added, newSerials[j])
108 j++
109 } else {
110 i++
111 j++
112 }
113 }
114
115 return &diffResult{added, removed}, nil
116 }
117
View as plain text