From e6f109f951a5faecf48c58e1e024cc4154fe3984 Mon Sep 17 00:00:00 2001 From: Sanjit Bhat Date: Fri, 9 Aug 2024 11:09:15 -0400 Subject: [PATCH] split evid into signedLink and signedPut. more modular --- ktmerkle/evidence.go | 99 +++++++++++++++++++++++--------------------- ktmerkle/ktmerkle.go | 20 ++++++--- 2 files changed, 67 insertions(+), 52 deletions(-) diff --git a/ktmerkle/evidence.go b/ktmerkle/evidence.go index c40c4b6..b1d5780 100644 --- a/ktmerkle/evidence.go +++ b/ktmerkle/evidence.go @@ -6,44 +6,59 @@ import ( "github.com/mit-pdos/pav/merkle" ) +type signedLink struct { + epoch epochTy + prevLink linkTy + dig merkle.Digest + sig cryptoffi.Sig +} + +func (o *signedLink) check(pk cryptoffi.PublicKey) (linkTy, errorTy) { + preLink := (&chainSepSome{epoch: o.epoch, prevLink: o.prevLink, data: o.dig}).encode() + link := cryptoffi.Hash(preLink) + sepLink := (&servSepLink{link: link}).encode() + ok := pk.Verify(sepLink, o.sig) + return link, !ok +} + +type signedPut struct { + epoch epochTy + id merkle.Id + val merkle.Val + sig cryptoffi.Sig +} + +func (o *signedPut) check(pk cryptoffi.PublicKey) errorTy { + sepPut := (&servSepPut{epoch: o.epoch, id: o.id, val: o.val}).encode() + okPut := pk.Verify(sepPut, o.sig) + return !okPut +} + // evidServLink is evidence that the server signed two conflicting links, // either zero or one epochs away. type evidServLink struct { - epoch0 epochTy - prevLink0 linkTy - dig0 merkle.Digest - sig0 cryptoffi.Sig - - epoch1 epochTy - prevLink1 linkTy - dig1 merkle.Digest - sig1 cryptoffi.Sig + sln0 *signedLink + sln1 *signedLink } // check returns an error if the evidence does not check out. // otherwise, it proves that the server was dishonest. func (e *evidServLink) check(servPk cryptoffi.PublicKey) errorTy { - linkSep0 := (&chainSepSome{epoch: e.epoch0, prevLink: e.prevLink0, data: e.dig0}).encode() - link0 := cryptoffi.Hash(linkSep0) - enc0 := (&servSepLink{link: link0}).encode() - ok0 := servPk.Verify(enc0, e.sig0) - if !ok0 { + link0, err0 := e.sln0.check(servPk) + if err0 { return errSome } - linkSep1 := (&chainSepSome{epoch: e.epoch1, prevLink: e.prevLink1, data: e.dig1}).encode() - link1 := cryptoffi.Hash(linkSep1) - enc1 := (&servSepLink{link: link1}).encode() - ok1 := servPk.Verify(enc1, e.sig1) - if !ok1 { + link1, err1 := e.sln1.check(servPk) + if err1 { return errSome } - if e.epoch0 == e.epoch1 { + if e.sln0.epoch == e.sln1.epoch { return std.BytesEqual(link0, link1) } - if e.epoch0 == e.epoch1-1 { - return std.BytesEqual(link0, e.prevLink1) + if e.sln0.epoch == e.sln1.epoch-1 { + return std.BytesEqual(link0, e.sln1.prevLink) } return errSome } @@ -51,42 +66,32 @@ func (e *evidServLink) check(servPk cryptoffi.PublicKey) errorTy { // evidServPut is evidence when a server promises to put a value at a certain // epoch but actually there's a different value (as evidenced by a merkle proof). type evidServPut struct { - epoch epochTy - // For signed link. - prevLink linkTy - dig merkle.Digest - linkSig cryptoffi.Sig - // For signed put. - id merkle.Id - val0 merkle.Val - putSig cryptoffi.Sig - // For merkle inclusion. - val1 merkle.Val + sln *signedLink + sp *signedPut + // merkle inclusion. + val merkle.Val proof merkle.Proof } func (e *evidServPut) check(servPk cryptoffi.PublicKey) errorTy { - // Proof of signing the link. - preLink := (&chainSepSome{epoch: e.epoch, prevLink: e.prevLink, data: e.dig}).encode() - link := cryptoffi.Hash(preLink) - preLinkSig := (&servSepLink{link: link}).encode() - linkOk := servPk.Verify(preLinkSig, e.linkSig) - if !linkOk { + _, err0 := e.sln.check(servPk) + if err0 { return errSome } - // Proof of signing the put promise. - prePut := (&servSepPut{epoch: e.epoch, id: e.id, val: e.val0}).encode() - putOk := servPk.Verify(prePut, e.putSig) - if !putOk { + err1 := e.sp.check(servPk) + if err1 { return errSome } - // Proof of merkle inclusion of the other val. - err0 := merkle.CheckProof(merkle.MembProofTy, e.proof, e.id, e.val1, e.dig) - if err0 { + // merkle inclusion of the other val. + err2 := merkle.CheckProof(merkle.MembProofTy, e.proof, e.sp.id, e.val, e.sln.dig) + if err2 { return errSome } - return std.BytesEqual(e.val0, e.val1) + if e.sln.epoch != e.sp.epoch { + return errSome + } + return std.BytesEqual(e.sp.val, e.val) } diff --git a/ktmerkle/ktmerkle.go b/ktmerkle/ktmerkle.go index 33d30c8..5118e7b 100644 --- a/ktmerkle/ktmerkle.go +++ b/ktmerkle/ktmerkle.go @@ -264,25 +264,29 @@ func (c *client) addLink(epoch epochTy, prevLink linkTy, dig merkle.Digest, sig if !ok0 { return nil, errSome } + newSigLn := &signedLink{epoch: epoch, prevLink: prevLink, dig: dig, sig: sig} // Check if epoch already exists. cachedLink, ok1 := c.links[epoch] if ok1 && !std.BytesEqual(cachedLink.link, link) { - evid := &evidServLink{epoch0: epoch, prevLink0: cachedLink.prevLink, dig0: cachedLink.dig, sig0: cachedLink.sig, epoch1: epoch, prevLink1: prevLink, dig1: dig, sig1: sig} + cachedSigLn := &signedLink{epoch: epoch, prevLink: cachedLink.prevLink, dig: cachedLink.dig, sig: cachedLink.sig} + evid := &evidServLink{sln0: newSigLn, sln1: cachedSigLn} return evid, errSome } // Check if epoch-1 already exists. cachedPrevLink, ok2 := c.links[epoch-1] if epoch > 0 && ok2 && !std.BytesEqual(cachedPrevLink.link, prevLink) { - evid := &evidServLink{epoch0: epoch - 1, prevLink0: cachedPrevLink.prevLink, dig0: cachedPrevLink.dig, sig0: cachedPrevLink.sig, epoch1: epoch, prevLink1: prevLink, dig1: dig, sig1: sig} + cachedSigLn := &signedLink{epoch: epoch - 1, prevLink: cachedLink.prevLink, dig: cachedLink.dig, sig: cachedLink.sig} + evid := &evidServLink{sln0: cachedSigLn, sln1: newSigLn} return evid, errSome } // Check if epoch+1 already exists. cachedNextLink, ok3 := c.links[epoch+1] if epoch < maxUint64 && ok3 && !std.BytesEqual(link, cachedNextLink.prevLink) { - evid := &evidServLink{epoch0: epoch, prevLink0: link, dig0: dig, sig0: sig, epoch1: epoch + 1, prevLink1: cachedNextLink.prevLink, dig1: cachedNextLink.dig, sig1: cachedNextLink.sig} + cachedSigLn := &signedLink{epoch: epoch + 1, prevLink: cachedLink.prevLink, dig: cachedLink.dig, sig: cachedLink.sig} + evid := &evidServLink{sln0: newSigLn, sln1: cachedSigLn} return evid, errSome } @@ -372,6 +376,8 @@ func (c *client) fetchLink(epoch epochTy) (*evidServLink, errorTy) { // there could be lots of errors, but currently, we mainly // return an error if there's evidence. // TODO: maybe change err handling, in selfCheck as well. +// TODO: maybe split cross-epoch consistency check into sep routine. +// it seems nice to have (but not necessary) for both audit and selfCheck. func (c *client) audit(adtrAddr grove_ffi.Address, adtrPk cryptoffi.PublicKey) (epochTy, *evidServLink, errorTy) { // Note: potential attack. // Key serv refuses to fill in a hole, even though we have bigger digests. @@ -417,7 +423,9 @@ func (c *client) audit(adtrAddr grove_ffi.Address, adtrPk cryptoffi.PublicKey) ( // Check if our chain diverges from adtr. if !std.BytesEqual(lastLink.link, adtrLink) { - evid := &evidServLink{epoch0: lastEpoch, prevLink0: lastLink.prevLink, dig0: lastLink.dig, sig0: lastLink.sig, epoch1: lastEpoch, prevLink1: reply.prevLink, dig1: reply.dig, sig1: reply.servSig} + adtrSigLn := &signedLink{epoch: lastEpoch, prevLink: reply.prevLink, dig: reply.dig, sig: reply.servSig} + mySigLn := &signedLink{epoch: lastEpoch, prevLink: lastLink.prevLink, dig: lastLink.dig, sig: lastLink.sig} + evid := &evidServLink{sln0: adtrSigLn, sln1: mySigLn} return 0, evid, errSome } return epoch, nil, errNone @@ -449,7 +457,9 @@ func (c *client) selfCheckAt(epoch epochTy) (*evidServLink, *evidServPut, errorT if !std.BytesEqual(expVal, reply.val) { // The put promise is only valid on a boundary epoch. if isBoundary { - ev := &evidServPut{epoch: epoch, prevLink: reply.prevLink, dig: reply.dig, linkSig: reply.sig, id: c.id, val0: expVal, putSig: putSig, val1: reply.val, proof: reply.proof} + sigLn := &signedLink{epoch: epoch, prevLink: reply.prevLink, dig: reply.dig, sig: reply.sig} + sigPut := &signedPut{epoch: epoch, id: c.id, val: expVal, sig: putSig} + ev := &evidServPut{sln: sigLn, sp: sigPut, val: reply.val, proof: reply.proof} return nil, ev, errSome } else { return nil, nil, errSome