Skip to content

Commit 6055bf0

Browse files
committed
Add support for evidence
- Rename QueuedAssertion to AssertionRequest, add Evidence field, and move from 'ca' package to 'mtc' package to be able to use private 'unmarshal' function. - Update /ca/queue to accept an AssertionRequest instead of an Assertion - Update index to include offset in evidence file. - Add 'mtc inspect evidence' option
1 parent 972fffc commit 6055bf0

File tree

8 files changed

+383
-167
lines changed

8 files changed

+383
-167
lines changed

ca/ca.go

Lines changed: 58 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,8 @@ import (
2121
"golang.org/x/crypto/cryptobyte"
2222
)
2323

24-
const csLen = 32
25-
2624
var (
27-
ErrChecksumInvalid = errors.New("Invalid checksum")
28-
ErrClosed = errors.New("Handle is closed")
25+
ErrClosed = errors.New("Handle is closed")
2926
)
3027

3128
type NewOpts struct {
@@ -55,71 +52,6 @@ type Handle struct {
5552
batchNumbersCache []uint32 // cache for existing batches
5653
}
5754

58-
type QueuedAssertion struct {
59-
Checksum []byte
60-
Assertion mtc.Assertion
61-
}
62-
63-
func (a *QueuedAssertion) UnmarshalBinary(data []byte) error {
64-
var (
65-
s cryptobyte.String = cryptobyte.String(data)
66-
checksum [csLen]byte
67-
)
68-
if !s.CopyBytes(checksum[:]) {
69-
return mtc.ErrTruncated
70-
}
71-
72-
a.Checksum = make([]byte, csLen)
73-
copy(a.Checksum, checksum[:])
74-
75-
checksum2 := sha256.Sum256([]byte(s))
76-
if !bytes.Equal(checksum2[:], checksum[:]) {
77-
return ErrChecksumInvalid
78-
}
79-
80-
if err := a.Assertion.UnmarshalBinary([]byte(s)); err != nil {
81-
return err
82-
}
83-
84-
return nil
85-
}
86-
87-
func (a *QueuedAssertion) marshalAndCheckAssertion() ([]byte, error) {
88-
buf, err := a.Assertion.MarshalBinary()
89-
if err != nil {
90-
return nil, err
91-
}
92-
93-
checksum2 := sha256.Sum256([]byte(buf))
94-
if a.Checksum == nil {
95-
a.Checksum = checksum2[:]
96-
} else if !bytes.Equal(checksum2[:], a.Checksum) {
97-
return nil, ErrChecksumInvalid
98-
}
99-
100-
return buf, nil
101-
}
102-
103-
// If set, checks whether the Checksum is correct. If not set, sets the
104-
// Checksum to the correct value.
105-
func (a *QueuedAssertion) Check() error {
106-
_, err := a.marshalAndCheckAssertion()
107-
return err
108-
}
109-
110-
func (a *QueuedAssertion) MarshalBinary() ([]byte, error) {
111-
var b cryptobyte.Builder
112-
113-
buf, err := a.marshalAndCheckAssertion()
114-
if err != nil {
115-
return nil, err
116-
}
117-
b.AddBytes(a.Checksum)
118-
b.AddBytes(buf)
119-
120-
return b.Bytes()
121-
}
122-
12355
func (ca *Handle) Params() mtc.CAParams {
12456
return ca.params
12557
}
@@ -165,7 +97,7 @@ func (h *Handle) dropQueue() error {
16597
//
16698
// For each entry, if checksum is not nil, makes sure the assertion
16799
// matches the checksum
168-
func (h *Handle) QueueMultiple(it func(yield func(qa QueuedAssertion) error) error) error {
100+
func (h *Handle) QueueMultiple(it func(yield func(a mtc.AssertionRequest) error) error) error {
169101
if h.closed {
170102
return ErrClosed
171103
}
@@ -177,8 +109,8 @@ func (h *Handle) QueueMultiple(it func(yield func(qa QueuedAssertion) error) err
177109
defer w.Close()
178110
bw := bufio.NewWriter(w)
179111

180-
if err := it(func(qa QueuedAssertion) error {
181-
buf, err := qa.MarshalBinary()
112+
if err := it(func(a mtc.AssertionRequest) error {
113+
buf, err := a.MarshalBinary()
182114
if err != nil {
183115
return err
184116
}
@@ -208,14 +140,9 @@ func (h *Handle) QueueMultiple(it func(yield func(qa QueuedAssertion) error) err
208140
// Queue assertion for publication.
209141
//
210142
// If checksum is not nil, makes sure assertion matches the checksum.
211-
func (h *Handle) Queue(a mtc.Assertion, checksum []byte) error {
212-
return h.QueueMultiple(func(yield func(qa QueuedAssertion) error) error {
213-
return yield(
214-
QueuedAssertion{
215-
Checksum: checksum,
216-
Assertion: a,
217-
},
218-
)
143+
func (h *Handle) Queue(a mtc.AssertionRequest) error {
144+
return h.QueueMultiple(func(yield func(a mtc.AssertionRequest) error) error {
145+
return yield(a)
219146
})
220147
}
221148

@@ -387,7 +314,7 @@ func (h *Handle) listBatchRange() (mtc.BatchRange, error) {
387314
}
388315

389316
// Calls f on each assertion queued to be published.
390-
func (h *Handle) WalkQueue(f func(QueuedAssertion) error) error {
317+
func (h *Handle) WalkQueue(f func(mtc.AssertionRequest) error) error {
391318
r, err := os.OpenFile(h.queuePath(), os.O_RDONLY, 0)
392319
if err != nil {
393320
return fmt.Errorf("Opening queue: %w", err)
@@ -400,7 +327,7 @@ func (h *Handle) WalkQueue(f func(QueuedAssertion) error) error {
400327
var (
401328
prefix [2]byte
402329
aLen uint16
403-
qa QueuedAssertion
330+
a mtc.AssertionRequest
404331
)
405332
_, err := io.ReadFull(br, prefix[:])
406333
if err == io.EOF {
@@ -418,12 +345,12 @@ func (h *Handle) WalkQueue(f func(QueuedAssertion) error) error {
418345
return fmt.Errorf("Reading queue: %w", err)
419346
}
420347

421-
err = qa.UnmarshalBinary(buf)
348+
err = a.UnmarshalBinary(buf)
422349
if err != nil {
423350
return fmt.Errorf("Parsing queue: %w", err)
424351
}
425352

426-
err = f(qa)
353+
err = f(a)
427354
if err != nil {
428355
return err
429356
}
@@ -760,6 +687,7 @@ func (h *Handle) issueBatch(number uint32, empty bool) error {
760687
"tree",
761688
"signed-validity-window",
762689
"abridged-assertions",
690+
"evidence",
763691
"index",
764692
},
765693
)
@@ -884,7 +812,7 @@ func (h *Handle) issueBatchTo(dir string, batch mtc.Batch, empty bool) error {
884812
prevHeads = w.ValidityWindow.TreeHeads
885813
}
886814

887-
// Read queue and write abridged-assertions
815+
// Read queue and write abridged-assertions and evidence
888816
aasPath := gopath.Join(dir, "abridged-assertions")
889817
aasW, err := os.Create(aasPath)
890818
if err != nil {
@@ -893,23 +821,48 @@ func (h *Handle) issueBatchTo(dir string, batch mtc.Batch, empty bool) error {
893821
defer aasW.Close()
894822
aasBW := bufio.NewWriter(aasW)
895823

824+
evPath := gopath.Join(dir, "evidence")
825+
evW, err := os.Create(evPath)
826+
if err != nil {
827+
return fmt.Errorf("creating %s: %w", evPath, err)
828+
}
829+
defer evW.Close()
830+
evBW := bufio.NewWriter(evW)
831+
896832
if !empty {
897-
err = h.WalkQueue(func(qa QueuedAssertion) error {
898-
aa := qa.Assertion.Abridge()
833+
err = h.WalkQueue(func(a mtc.AssertionRequest) error {
834+
aa := a.Assertion.Abridge()
899835
buf, err := aa.MarshalBinary()
900836
if err != nil {
901-
return fmt.Errorf("Marshalling assertion %x: %w", qa.Checksum, err)
837+
return fmt.Errorf("Marshalling assertion %x: %w", a.Checksum, err)
902838
}
903839

904840
_, err = aasBW.Write(buf)
905841
if err != nil {
906842
return fmt.Errorf(
907843
"Writing assertion %x to %s: %w",
908-
qa.Checksum,
844+
a.Checksum,
909845
aasPath,
910846
err,
911847
)
912848
}
849+
850+
ev := a.Evidence
851+
buf, err = ev.MarshalBinary()
852+
if err != nil {
853+
return fmt.Errorf("Marshalling evidence %x: %w", a.Checksum, err)
854+
}
855+
856+
_, err = evBW.Write(buf)
857+
if err != nil {
858+
return fmt.Errorf(
859+
"Writing evidence %x to %s: %w",
860+
a.Checksum,
861+
evPath,
862+
err,
863+
)
864+
}
865+
913866
return nil
914867
})
915868
if err != nil {
@@ -932,6 +885,21 @@ func (h *Handle) issueBatchTo(dir string, batch mtc.Batch, empty bool) error {
932885
}
933886
defer aasR.Close()
934887

888+
err = evBW.Flush()
889+
if err != nil {
890+
return fmt.Errorf("flushing %s: %w", evPath, err)
891+
}
892+
893+
err = evW.Close()
894+
if err != nil {
895+
return fmt.Errorf("closing %s: %w", evPath, err)
896+
}
897+
evR, err := os.OpenFile(evPath, os.O_RDONLY, 0)
898+
if err != nil {
899+
return fmt.Errorf("opening %s: %w", evPath, err)
900+
}
901+
defer evR.Close()
902+
935903
// Compute tree
936904
tree, err := batch.ComputeTree(bufio.NewReader(aasR))
937905
if err != nil {
@@ -970,7 +938,7 @@ func (h *Handle) issueBatchTo(dir string, batch mtc.Batch, empty bool) error {
970938

971939
defer indexW.Close()
972940

973-
err = ComputeIndex(aasR, indexW)
941+
err = ComputeIndex(aasR, evR, indexW)
974942
if err != nil {
975943
return fmt.Errorf("computing %s to start: %w", indexPath, err)
976944
}

ca/index.go

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
package ca
22

3-
// Functions to work with the batches' index file into abridged-assertions.
3+
// Functions to work with the batches' index file into abridged-assertions and evidence.
44
//
5-
// The index file consists of 48 byte entries, sorted by key.
5+
// The index file consists of 56 byte entries, sorted by key.
66
//
7-
// +--------------+--------------+---------------+
8-
// | 32-byte key | uint64 seqno | uint64 offset |
9-
// +--------------+--------------+---------------+
7+
// +--------------+--------------+---------------+------------------------+
8+
// | 32-byte key | uint64 seqno | uint64 offset | uint64 evidence_offset |
9+
// +--------------+--------------+---------------+------------------------+
1010
//
1111
// Each entry corresponds to an AbridgedAssertion. The key is its key,
12-
// the seqno is the sequence number within the abridged-assertions list, and
13-
// the offset is the byte-offset in the abridged-assertions file.
14-
// offset and seqno are encoded big endian.
12+
// the seqno is the sequence number within the abridged-assertions list,
13+
// the offset is the byte-offset in the abridged-assertions file, and
14+
// the evidence_offset is the byte-offset in the evidence file.
15+
// offset, evidence_offset, and seqno are encoded big endian.
1516
//
1617
// This allows quick lookups by key using interpolation search.
1718
//
@@ -154,19 +155,21 @@ func (h *Index) Search(hash []byte) (*IndexSearchResult, error) {
154155
}
155156

156157
type indexEntry struct {
157-
key [mtc.HashLen]byte
158-
seqno uint64
159-
offset uint64
158+
key [mtc.HashLen]byte
159+
seqno uint64
160+
offset uint64
161+
evidenceOffset uint64
160162
}
161163

162-
// Reads a stream of AbridgedAssertions from r, and writes the index to w.
163-
func ComputeIndex(r io.Reader, w io.Writer) error {
164+
// Reads a streams of AbridgedAssertions Evidence from aaReader and evReader,
165+
// and writes the index to w.
166+
func ComputeIndex(aaReader, evReader io.Reader, w io.Writer) error {
164167
// First compute keys
165168
seqno := uint64(0)
166169
entries := []indexEntry{}
167170

168171
var key [mtc.HashLen]byte
169-
err := mtc.UnmarshalAbridgedAssertions(r, func(offset int,
172+
err := mtc.UnmarshalAbridgedAssertions(aaReader, func(offset int,
170173
aa *mtc.AbridgedAssertion) error {
171174
err := aa.Key(key[:])
172175
if err != nil {
@@ -181,6 +184,13 @@ func ComputeIndex(r io.Reader, w io.Writer) error {
181184
return nil
182185
})
183186

187+
seqno = uint64(0)
188+
err = mtc.UnmarshalEvidenceEntries(evReader, func(offset int, _ *mtc.Evidence) error {
189+
entries[seqno].evidenceOffset = uint64(offset)
190+
seqno++
191+
return nil
192+
})
193+
184194
if err != nil {
185195
return fmt.Errorf("computing keys: %w", err)
186196
}
@@ -204,6 +214,7 @@ func ComputeIndex(r io.Reader, w io.Writer) error {
204214
b.AddBytes(entry.key[:])
205215
b.AddUint64(entry.seqno)
206216
b.AddUint64(entry.offset)
217+
b.AddUint64(entry.evidenceOffset)
207218
buf, _ := b.Bytes()
208219

209220
_, err = bw.Write(buf)

0 commit comments

Comments
 (0)