From 0aa58411b80b68633fd988e4ea85564c7e43ef1b Mon Sep 17 00:00:00 2001 From: MLETHZ Date: Tue, 20 Jun 2023 15:34:08 +0200 Subject: [PATCH 01/33] manually trigger workflow --- .github/workflows/gobra.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/gobra.yml b/.github/workflows/gobra.yml index d1df3a550..b59146620 100644 --- a/.github/workflows/gobra.yml +++ b/.github/workflows/gobra.yml @@ -10,6 +10,7 @@ on: push: branches: - master + - workflow_dispatch pull_request: # run this workflow on every pull_request env: From 8525b7cf70b0a3fe0136682fb02fd7e098f12342 Mon Sep 17 00:00:00 2001 From: MLETHZ Date: Tue, 20 Jun 2023 15:37:25 +0200 Subject: [PATCH 02/33] manually trigger workflow --- .github/workflows/gobra.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gobra.yml b/.github/workflows/gobra.yml index b59146620..1ef4e1f97 100644 --- a/.github/workflows/gobra.yml +++ b/.github/workflows/gobra.yml @@ -10,8 +10,8 @@ on: push: branches: - master - - workflow_dispatch pull_request: # run this workflow on every pull_request + workflow_dispatch: env: headerOnly: 1 From 2eaf7a475acb7760989ee97c189b1dfb1ceb1214 Mon Sep 17 00:00:00 2001 From: MLETHZ Date: Tue, 4 Jul 2023 12:06:17 +0200 Subject: [PATCH 03/33] raw byte to spec for segments and hopfields --- router/dataplane_spec.gobra | 103 ++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/router/dataplane_spec.gobra b/router/dataplane_spec.gobra index a15e3b794..416c513e5 100644 --- a/router/dataplane_spec.gobra +++ b/router/dataplane_spec.gobra @@ -20,6 +20,8 @@ import ( "net" "hash" sl "github.com/scionproto/scion/verification/utils/slices" + "github.com/scionproto/scion/verification/io" + "github.com/scionproto/scion/verification/dependencies/encoding/binary/binary.gobra" "github.com/scionproto/scion/pkg/scrypto" "github.com/scionproto/scion/pkg/addr" ) @@ -343,3 +345,104 @@ func closureSpec2(i uint16, c BatchConn) requires true func closureSpec3(c BatchConn) /** End of closure specs for the Run method **/ + + + +/** Start of io-spec helper functions **/ + +ghost +decreases +pure func getHopField(raw []byte) io.IO_HF { + return let inif2 := binary.BigEndian.Uint16(raw[2:4]) == 0 ? none[io.IO_ifs] : some(io.IO_ifs(binary.BigEndian.Uint16(raw[2:4]))) in + let egif2 := binary.BigEndian.Uint16(raw[4:6])== 0 ? none[io.IO_ifs] : some(io.IO_ifs(binary.BigEndian.Uint16(raw[4:6]))) in + io.IO_HF(io.IO_HF_{ + InIF2 : inif2, + EgIF2 : egif2, + HVF : computeMsgTerm(raw), + }) +} + +ghost +decreases +pure func getSegments(raw []byte) io.IO_seg2{ + return let line := binary.BigEndian.Uint32(raw[0:4]) in + let currINF := uint8(line >> 30) in + let currHF := uint8(line >> 24) & 0x3F in + let seg1Len := uint8(line >> 12) & 0x3F in + let seg2Len := uint8(line >> 6) & 0x3F in + let seg3Len := uint8(line) & 0x3F in + let numINF := numInfoFields(seg1Len, seg2Len, seg3Len) in + let rawHopFields := computeSeqBytes(raw[4+8*numINF:], currHF, seg1Len, seg2Len, seg3Len) in + let rawHopFieldsOffset := computeSeqOffset(currHF, seg1Len, seg2Len, seg3Len) - 1 in + io.IO_seg2(io.IO_seg3_{ + AInfo : computeAInfo(raw), + UInfo : computeUInfo(raw), + ConsDir : raw[infoFieldOffsetSeg(currINF)] & 0x1 == 0x1, + Peer : raw[infoFieldOffsetSeg(currINF)] & 0x2 == 0x2, + Past : getSegPast(rawHopFields, rawHopFieldsOffset - 1), + Future : getSegFuture(rawHopFields, rawHopFieldsOffset), + History : getSegHistory(rawHopFields, rawHopFieldsOffset - 1), + }) +} + +//assumption at least seg1Len > 0 correct? +ghost +decreases +pure func numInfoFields(seg1Len uint8, seg2Len uint8, seg3Len uint8) uint8 { + return seg3Len > 0 ? 3 : (seg2Len > 0 ? 2 : 1) +} + +ghost +decreases +pure func infoFieldOffsetSeg(currINF uint8) uint8{ + return 4 + 8 * currINF +} + +ghost +decreases +pure func computeSeqOffset(currHF uint8, seg1Len uint8, seg2Len uint8, seg3Len uint8) int{ + return seg1Len > currHF ? int(currHF)*12 : (seg2Len > currHF ? int(currHF-seg1Len) * 12 : int(currHF-seg2Len-seg1Len)* 12) +} + +ghost +decreases +pure func computeSeqBytes(raw []byte, currHF uint8, seg1Len uint8, seg2Len uint8, seg3Len uint8) []byte { + return seg1Len > currHF ? raw[0:seg1Len*12] : (seg2Len > currHF ? raw[seg1Len*12:seg2Len*12] : raw[seg2Len*12:seg3Len*12]) +} + +//TODO double check if order is correct +ghost +decreases +pure func getSegPast(raw []byte, offset int) seq[io.IO_HF]{ + return offset == -1 ? seq[io.IO_HF]{} : seq[io.IO_HF]{getHopField(raw[offset:offset+12])} ++ getSegPast(raw, offset-12) +} + + +//TODO double check if order is correct +ghost +decreases +pure func getSegFuture(raw []byte, offset int) seq[io.IO_HF]{ + return offset == len(raw) ? seq[io.IO_HF]{} : seq[io.IO_HF]{getHopField(raw[offset:offset+12])} ++ getSegFuture(raw, offset+12) +} + +//TODO double check if order is correct +ghost +decreases +pure func getSegHistory(raw []byte, offset int) seq[io.IO_ahi]{ + return offset == -1 ? seq[io.IO_HF]{} : seq[io.IO_HF]{getHopField(raw[offset:offset+12]).Toab()} ++ getSegHistory(raw, offset-12) +} + +// TODO Can we add a body? +ghost +decreases +pure func computeMsgTerm(raw []byte) io.IO_msgterm + +ghost +decreases _ +pure func computeAInfo(raw []byte) io.IO_ainfo + +ghost +decreases _ +pure func computeUInfo(raw []byte) set[io.IO_msgterm] + +/** End of io-spec helper functions **/ \ No newline at end of file From e9d31ae4d48f1fa8ee1d81556af27fe9ed2ea6e9 Mon Sep 17 00:00:00 2001 From: MLETHZ Date: Tue, 4 Jul 2023 12:07:21 +0200 Subject: [PATCH 04/33] bugfix --- router/dataplane_spec.gobra | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/router/dataplane_spec.gobra b/router/dataplane_spec.gobra index 416c513e5..2cfba02ec 100644 --- a/router/dataplane_spec.gobra +++ b/router/dataplane_spec.gobra @@ -403,13 +403,23 @@ decreases pure func computeSeqOffset(currHF uint8, seg1Len uint8, seg2Len uint8, seg3Len uint8) int{ return seg1Len > currHF ? int(currHF)*12 : (seg2Len > currHF ? int(currHF-seg1Len) * 12 : int(currHF-seg2Len-seg1Len)* 12) } +/* +ghost +decreases +requires len(raw) > 5 +pure func dummy(raw []byte) []byte{ + return raw[0:5] +} +*/ + ghost decreases pure func computeSeqBytes(raw []byte, currHF uint8, seg1Len uint8, seg2Len uint8, seg3Len uint8) []byte { - return seg1Len > currHF ? raw[0:seg1Len*12] : (seg2Len > currHF ? raw[seg1Len*12:seg2Len*12] : raw[seg2Len*12:seg3Len*12]) + return seg1Len > currHF ? raw[0:int(seg1Len)*12] : (seg2Len > currHF ? raw[int(seg1Len)*12:int(seg1Len + seg2Len)*12] : raw[int(seg1Len + seg2Len)*12:int(seg1Len + seg2Len + seg3Len)*12]) } + //TODO double check if order is correct ghost decreases @@ -429,7 +439,7 @@ pure func getSegFuture(raw []byte, offset int) seq[io.IO_HF]{ ghost decreases pure func getSegHistory(raw []byte, offset int) seq[io.IO_ahi]{ - return offset == -1 ? seq[io.IO_HF]{} : seq[io.IO_HF]{getHopField(raw[offset:offset+12]).Toab()} ++ getSegHistory(raw, offset-12) + return offset == -1 ? seq[io.IO_ahi]{} : seq[io.IO_ahi]{getHopField(raw[offset:offset+12]).Toab()} ++ getSegHistory(raw, offset-12) } // TODO Can we add a body? From 6b77cb642544373fc7571b6824be9ad72c7289e9 Mon Sep 17 00:00:00 2001 From: MLETHZ Date: Tue, 4 Jul 2023 14:07:13 +0200 Subject: [PATCH 05/33] import fix --- router/dataplane_spec.gobra | 54 ++++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/router/dataplane_spec.gobra b/router/dataplane_spec.gobra index 2cfba02ec..f0ca46768 100644 --- a/router/dataplane_spec.gobra +++ b/router/dataplane_spec.gobra @@ -21,7 +21,7 @@ import ( "hash" sl "github.com/scionproto/scion/verification/utils/slices" "github.com/scionproto/scion/verification/io" - "github.com/scionproto/scion/verification/dependencies/encoding/binary/binary.gobra" + "github.com/scionproto/scion/verification/dependencies/encoding/binary" "github.com/scionproto/scion/pkg/scrypto" "github.com/scionproto/scion/pkg/addr" ) @@ -350,18 +350,40 @@ func closureSpec3(c BatchConn) /** Start of io-spec helper functions **/ -ghost +ghost decreases -pure func getHopField(raw []byte) io.IO_HF { - return let inif2 := binary.BigEndian.Uint16(raw[2:4]) == 0 ? none[io.IO_ifs] : some(io.IO_ifs(binary.BigEndian.Uint16(raw[2:4]))) in - let egif2 := binary.BigEndian.Uint16(raw[4:6])== 0 ? none[io.IO_ifs] : some(io.IO_ifs(binary.BigEndian.Uint16(raw[4:6]))) in - io.IO_HF(io.IO_HF_{ - InIF2 : inif2, - EgIF2 : egif2, - HVF : computeMsgTerm(raw), - }) +pure func getPkt(raw []byte) io.IO_pkt2{ + return io.IO_pkt2(io.IO_Packet2{ + CurrSeg : tmpCurrSeg(raw), + LeftSeg : tmpLeftSeg(raw), + MidSeg : tmpMidSeg(raw), + RightSeg : tmpRightSeg(raw), + }) } +ghost +decreases +pure func tmpCurrSeg(raw []byte) io.IO_seg3 + +ghost +decreases +pure func tmpLeftSeg(raw []byte) option[io.IO_seg2] + +ghost +decreases +pure func tmpMidSeg(raw []byte) option[io.IO_seg2] + +ghost +decreases +pure func tmpRightSeg(raw []byte) option[io.IO_seg2] + + + + + + + + ghost decreases pure func getSegments(raw []byte) io.IO_seg2{ @@ -385,6 +407,18 @@ pure func getSegments(raw []byte) io.IO_seg2{ }) } +ghost +decreases +pure func getHopField(raw []byte) io.IO_HF { + return let inif2 := binary.BigEndian.Uint16(raw[2:4]) == 0 ? none[io.IO_ifs] : some(io.IO_ifs(binary.BigEndian.Uint16(raw[2:4]))) in + let egif2 := binary.BigEndian.Uint16(raw[4:6])== 0 ? none[io.IO_ifs] : some(io.IO_ifs(binary.BigEndian.Uint16(raw[4:6]))) in + io.IO_HF(io.IO_HF_{ + InIF2 : inif2, + EgIF2 : egif2, + HVF : computeMsgTerm(raw), + }) +} + //assumption at least seg1Len > 0 correct? ghost decreases From e9631e0010ff51d29f689de4c8e809349060b188 Mon Sep 17 00:00:00 2001 From: MLETHZ Date: Mon, 10 Jul 2023 18:03:45 +0200 Subject: [PATCH 06/33] bugfix after gobra update --- verification/dependencies/strconv/atoi.gobra | 1 + verification/dependencies/strings/strings.gobra | 1 + 2 files changed, 2 insertions(+) diff --git a/verification/dependencies/strconv/atoi.gobra b/verification/dependencies/strconv/atoi.gobra index 979bab907..9fef21b53 100644 --- a/verification/dependencies/strconv/atoi.gobra +++ b/verification/dependencies/strconv/atoi.gobra @@ -13,6 +13,7 @@ package strconv ghost requires exp >= 0 ensures res == (exp == 0 ? 1 : (base * Exp(base, exp - 1))) +decreases exp pure func Exp(base int, exp int) (res int) { return exp == 0 ? 1 : (base * Exp(base, exp - 1)) } diff --git a/verification/dependencies/strings/strings.gobra b/verification/dependencies/strings/strings.gobra index a913d66ca..31035eb19 100644 --- a/verification/dependencies/strings/strings.gobra +++ b/verification/dependencies/strings/strings.gobra @@ -155,6 +155,7 @@ func Map(mapping func(rune) rune, s string) string // the result of (len(s) * count) overflows. requires count >= 0 ensures res == (count == 0? "" : s + Repeat(s, count - 1)) +decreases count pure func Repeat(s string, count int) (res string) /*{ if count == 0 { return "" From bd062dc4e5658a355e12bbffc3b36167c047b6b4 Mon Sep 17 00:00:00 2001 From: MLETHZ Date: Mon, 10 Jul 2023 18:04:18 +0200 Subject: [PATCH 07/33] spec to pkt (currSeg) --- router/dataplane_spec.gobra | 461 +++++++++++++++++++++++++++++------- 1 file changed, 379 insertions(+), 82 deletions(-) diff --git a/router/dataplane_spec.gobra b/router/dataplane_spec.gobra index f0ca46768..11094bf3d 100644 --- a/router/dataplane_spec.gobra +++ b/router/dataplane_spec.gobra @@ -21,10 +21,14 @@ import ( "hash" sl "github.com/scionproto/scion/verification/utils/slices" "github.com/scionproto/scion/verification/io" + "github.com/scionproto/scion/verification/dependencies/encoding/binary" + "github.com/scionproto/scion/verification/utils/bitwise" "github.com/scionproto/scion/pkg/scrypto" "github.com/scionproto/scion/pkg/addr" ) +//"github.com/scionproto/scion/verification/definitions" + // TODO: maybe change interpretation of Mutex depending on whether the // dataplane is running or not. This is because, when Run is called and @@ -350,136 +354,429 @@ func closureSpec3(c BatchConn) /** Start of io-spec helper functions **/ + ghost +requires seg1Len > 0 +requires seg2Len >= 0 +requires seg3Len >= 0 +requires currHF < seg1Len + seg2Len + seg3Len decreases -pure func getPkt(raw []byte) io.IO_pkt2{ - return io.IO_pkt2(io.IO_Packet2{ - CurrSeg : tmpCurrSeg(raw), - LeftSeg : tmpLeftSeg(raw), - MidSeg : tmpMidSeg(raw), - RightSeg : tmpRightSeg(raw), - }) +pure func computeSeqlen(currHF int, seg1Len int, seg2Len int, seg3Len int) int{ + return seg1Len > currHF ? seg1Len : ((seg1Len + seg2Len) > currHF ? seg2Len: seg3Len) } -ghost -decreases -pure func tmpCurrSeg(raw []byte) io.IO_seg3 - ghost decreases -pure func tmpLeftSeg(raw []byte) option[io.IO_seg2] +pure func infoFieldOffsetSeg(currINF int) int{ + return 4 + 8 * currINF +} ghost -decreases -pure func tmpMidSeg(raw []byte) option[io.IO_seg2] - -ghost -decreases -pure func tmpRightSeg(raw []byte) option[io.IO_seg2] - - - - - - - +decreases +pure func numInfoFields(seg1Len int, seg2Len int, seg3Len int) int { + return seg3Len > 0 ? 3 : (seg2Len > 0 ? 2 : 1) +} ghost +requires seg1Len > 0 +requires seg2Len >= 0 +requires seg3Len >= 0 +requires currHF >= 0 +ensures res <= currHF decreases -pure func getSegments(raw []byte) io.IO_seg2{ - return let line := binary.BigEndian.Uint32(raw[0:4]) in - let currINF := uint8(line >> 30) in - let currHF := uint8(line >> 24) & 0x3F in - let seg1Len := uint8(line >> 12) & 0x3F in - let seg2Len := uint8(line >> 6) & 0x3F in - let seg3Len := uint8(line) & 0x3F in - let numINF := numInfoFields(seg1Len, seg2Len, seg3Len) in - let rawHopFields := computeSeqBytes(raw[4+8*numINF:], currHF, seg1Len, seg2Len, seg3Len) in - let rawHopFieldsOffset := computeSeqOffset(currHF, seg1Len, seg2Len, seg3Len) - 1 in - io.IO_seg2(io.IO_seg3_{ - AInfo : computeAInfo(raw), - UInfo : computeUInfo(raw), - ConsDir : raw[infoFieldOffsetSeg(currINF)] & 0x1 == 0x1, - Peer : raw[infoFieldOffsetSeg(currINF)] & 0x2 == 0x2, - Past : getSegPast(rawHopFields, rawHopFieldsOffset - 1), - Future : getSegFuture(rawHopFields, rawHopFieldsOffset), - History : getSegHistory(rawHopFields, rawHopFieldsOffset - 1), - }) +pure func computeprevSegLen(currHF int, seg1Len int, seg2Len int, seg3Len int) (res int){ + return seg1Len > currHF ? 0 : ((seg1Len + seg2Len) > currHF ? seg1Len : seg1Len + seg2Len) } +//expects the raw bytes of whole path ghost +requires start + 12 <= len(raw) +requires 0 <= start +requires acc(&raw[start+2], _) && acc(&raw[start+3], _) && acc(&raw[start+4], _) && acc(&raw[start+5], _) decreases -pure func getHopField(raw []byte) io.IO_HF { - return let inif2 := binary.BigEndian.Uint16(raw[2:4]) == 0 ? none[io.IO_ifs] : some(io.IO_ifs(binary.BigEndian.Uint16(raw[2:4]))) in - let egif2 := binary.BigEndian.Uint16(raw[4:6])== 0 ? none[io.IO_ifs] : some(io.IO_ifs(binary.BigEndian.Uint16(raw[4:6]))) in +pure func getHopField(raw []byte, start int) io.IO_HF { + return let inif2 := binary.BigEndian.Uint16(raw[start+2:start+4]) == 0 ? none[io.IO_ifs] : some(io.IO_ifs(binary.BigEndian.Uint16(raw[start+2:start+4]))) in + let egif2 := binary.BigEndian.Uint16(raw[start+4:start+6])== 0 ? none[io.IO_ifs] : some(io.IO_ifs(binary.BigEndian.Uint16(raw[start+4:start+6]))) in io.IO_HF(io.IO_HF_{ InIF2 : inif2, EgIF2 : egif2, - HVF : computeMsgTerm(raw), + HVF : computeMsgTerm(raw, start), }) } -//assumption at least seg1Len > 0 correct? +//TODO proof termination +//expects the raw bytes of whole path ghost -decreases -pure func numInfoFields(seg1Len uint8, seg2Len uint8, seg3Len uint8) uint8 { - return seg3Len > 0 ? 3 : (seg2Len > 0 ? 2 : 1) +requires 4 + 8 * numINF + offset*12 + 12 <= len(raw) +requires prevSegLen >= 0 && offset - prevSegLen >= -1 +requires 0 < numINF && numINF < 4 +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +decreases _ +pure func getSegPast(raw []byte, prevSegLen int, offset int, numINF int) seq[io.IO_HF]{ + return offset - prevSegLen == -1 ? seq[io.IO_HF]{} : + (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in + seq[io.IO_HF]{getHopField(raw,4 + 8 * numINF + offset*12)}) ++ getSegPast(raw, prevSegLen, offset-1, numINF) } ghost -decreases -pure func infoFieldOffsetSeg(currINF uint8) uint8{ - return 4 + 8 * currINF +requires 4 + 8 * numINF + offset*12 + 12 <= len(raw) +requires offset >= currHF && currHF >= 0 +requires 0 < numINF && numINF < 4 +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +decreases _ +pure func getSegFuture(raw []byte, currHF int, offset int, numINF int) seq[io.IO_HF]{ + return offset == currHF ? (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in seq[io.IO_HF]{getHopField(raw,4 + 8 * numINF + offset*12)}) : + getSegFuture(raw, currHF, offset-1, numINF) ++ (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in seq[io.IO_HF]{getHopField(raw, 4 + 8 * numINF + offset*12)}) } +//TODO proof termination +//expects the raw bytes of whole path ghost -decreases -pure func computeSeqOffset(currHF uint8, seg1Len uint8, seg2Len uint8, seg3Len uint8) int{ - return seg1Len > currHF ? int(currHF)*12 : (seg2Len > currHF ? int(currHF-seg1Len) * 12 : int(currHF-seg2Len-seg1Len)* 12) +requires 4 + 8 * numINF + offset*12 + 12 <= len(raw) +requires prevSegLen >= 0 && offset - prevSegLen >= -1 +requires 0 < numINF && numINF < 4 +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +decreases _ +pure func getSegHistory(raw []byte, prevSegLen int, offset int, numINF int) seq[io.IO_ahi]{ + return offset - prevSegLen == -1 ? seq[io.IO_ahi]{} : + (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in + seq[io.IO_ahi]{getHopField(raw,4 + 8 * numINF + offset*12).Toab()}) ++ getSegHistory(raw, prevSegLen, offset-1, numINF) } -/* + + + ghost -decreases -requires len(raw) > 5 -pure func dummy(raw []byte) []byte{ - return raw[0:5] +//expects the raw bytes of whole path +requires 4 + 8 * numINF + 12*prevSegLen + 12*segLen <= len(raw) +requires prevSegLen >= 0 && segLen >= 0 +requires 0 < numINF && numINF < 4 +requires segLen+prevSegLen > currHF && currHF >= prevSegLen +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +decreases _ +pure func getSegment(raw []byte, consDir bool, peer bool, currHF int, prevSegLen int, segLen int, numINF int) io.IO_seg2{ + return io.IO_seg2(io.IO_seg3_{ + AInfo : computeAInfo(raw), + UInfo : computeUInfo(raw), + ConsDir : consDir, + Peer : peer, + Past : getSegPast(raw, prevSegLen, currHF - 1, numINF), + Future : getSegFuture(raw, currHF, segLen+prevSegLen-1, numINF), + History : getSegHistory(raw, prevSegLen, currHF - 1, numINF), + }) } -*/ -ghost -decreases -pure func computeSeqBytes(raw []byte, currHF uint8, seg1Len uint8, seg2Len uint8, seg3Len uint8) []byte { - return seg1Len > currHF ? raw[0:int(seg1Len)*12] : (seg2Len > currHF ? raw[int(seg1Len)*12:int(seg1Len + seg2Len)*12] : raw[int(seg1Len + seg2Len)*12:int(seg1Len + seg2Len + seg3Len)*12]) +ghost +requires seg1Len > 0 +requires seg2Len >= 0 +requires seg3Len >= 0 +requires 4 + 8*numInfoFields(seg1Len, seg2Len, seg3Len) + 12 * seg1Len + 12 * seg2Len + 12 * seg3Len == len(raw) +//requires 12*computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) + +// 12*computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) <= 12 * seg1Len + 12 * seg2Len + 12 * seg3Len +requires 0 <= currINF && currINF < 3 +requires 0 <= currHF && currHF < seg1Len + seg2Len + seg3Len +// requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) > currHF +requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) + computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF +//requires currHF >= computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +decreases _ +pure func getCurrSeg(raw []byte, currINF int, currHF int, seg1Len int, seg2Len int, seg3Len int) io.IO_seg3 { + return let consDir := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in raw[infoFieldOffsetSeg(currINF)] & 0x1 == 0x1) in + let peer := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in raw[infoFieldOffsetSeg(currINF)] & 0x2 == 0x2) in + let segLen := computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) in + let prevSegLen := computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) in + let numINF := numInfoFields(seg1Len, seg2Len, seg3Len) in + getSegment(raw, consDir, peer, currHF, prevSegLen, segLen, numINF) } +/** tmp - helper functions +TODO prove these functions **/ -//TODO double check if order is correct -ghost +//TODO too strong assumption? +ghost +requires line == uint32(raw3) | uint32(raw2)<<8 | uint32(raw1)<<16 | uint32(raw0)<<24 +//preserves (raw0 & 0x3F) >= 0 //l3 +//preserves (raw2 >> 4 | raw1 << 4) & 0x3F > 0 +//preserves (raw3 >> 6 | raw2 << 2) & 0x3F >= 0 +//preserves (raw3 & 0x3F) >= 0 +ensures uint8(line >> 30) == raw0 >> 6 +ensures uint8(line >> 24) & 0x3F == (raw0 & 0x3F) +ensures uint8(line >> 12) & 0x3F == (raw2 >> 4 | raw1 << 4) & 0x3F +ensures uint8(line >> 6) & 0x3F == (raw3 >> 6 | raw2 << 2) & 0x3F +ensures uint8(line) & 0x3F == raw3 & 0x3F +ensures 0 <= uint8(line >> 30) && uint8(line >> 30) < 3 //currINF +ensures 0 <= (uint8(line >> 24) & 0x3F) && (uint8(line >> 24) & 0x3F) < (uint8(line >> 12) & 0x3F) + (uint8(line >> 6) & 0x3F) + (uint8(line) & 0x3F) //currHF +ensures 0 < uint8(line >> 12) & 0x3F //seg1Len +ensures 0 <= uint8(line >> 6) & 0x3F //seg2Len +ensures 0 <= uint8(line) & 0x3F //seg3Len +ensures res == true decreases -pure func getSegPast(raw []byte, offset int) seq[io.IO_HF]{ - return offset == -1 ? seq[io.IO_HF]{} : seq[io.IO_HF]{getHopField(raw[offset:offset+12])} ++ getSegPast(raw, offset-12) +pure func DeserializingHdr(raw0, raw1, raw2, raw3 uint8, line uint32) (res bool) + +/** End of of assumed functions **/ + +ghost +requires len(raw) > 4 +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +requires unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in + let hdr := binary.BigEndian.Uint32(raw[0:4]) in + hdr == (uint32(raw[3]) | uint32(raw[2])<<8 | uint32(raw[1])<<16 | uint32(raw[0])<<24) && + DeserializingHdr(raw[0], raw[1], raw[2], raw[3], hdr) && + //uint8(hdr >> 12) & 0x3F > 0 && + //uint8(hdr >> 6) & 0x3F >= 0 && + //uint8(hdr) & 0x3F >= 0 && + 4 + 8*numInfoFields(int(uint8(hdr >> 12) & 0x3F), int(uint8(hdr >> 6) & 0x3F), int(uint8(hdr) & 0x3F)) + 12 * int(uint8(hdr >> 12) & 0x3F) + 12 * int(uint8(hdr >> 6) & 0x3F) + 12 * int(uint8(hdr) & 0x3F) == len(raw) +decreases _ +pure func getPkt(raw []byte) io.IO_pkt2{ + return let hdr := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in binary.BigEndian.Uint32(raw[0:4]) in + let currINF := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in uint8(hdr >> 30) in + let currHF := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in uint8(hdr >> 24) & 0x3F in + let seg1Len := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in uint8(hdr >> 12) & 0x3F in + let seg2Len := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in uint8(hdr >> 6) & 0x3F in + let seg3Len := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in uint8(hdr) & 0x3F in + io.IO_pkt2(io.IO_Packet2{ + CurrSeg : getCurrSeg(raw, int(currINF), int(currHF), int(seg1Len), int(seg2Len), int(seg3Len)), + LeftSeg : tmpLeftSeg(raw), + MidSeg : tmpMidSeg(raw), + RightSeg : tmpRightSeg(raw), + }) } -//TODO double check if order is correct +// //TODO remove additional variable rawHopFields +// ghost +// //requires int(seg1Len + seg2Len + seg3Len)*12 <= len(raw) +// //requires 0 <= seg1Len && seg1Len*12 <= len(raw) +// //requires 0 <= seg2Len && (seg1Len + seg2Len)*12 <= len(raw) +// //requires 0 <= seg3Len && (seg1Len + seg2Len + seg3Len)*12 <= len(raw) +// requires len(raw) > infoFieldOffsetSeg(currINF) +// requires currINF >= 0 +// requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +// requires acc(sl.AbsSlice_Bytes(rawHopFields, 0, len(rawHopFields)), _) +// decreases _ +// pure func getCurrSeg(raw []byte, rawHopFields []byte, currINF int, currHF int, seg1Len int, seg2Len int, seg3Len int) io.IO_seg3 { +// return let consDir := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in raw[infoFieldOffsetSeg(currINF)] & 0x1 == 0x1) in +// let peer := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in raw[infoFieldOffsetSeg(currINF)] & 0x2 == 0x2) in +// let numHF := computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) in +// //let rawHopFields := getSegBytes(raw, currHF, seg1Len, seg2Len, seg3Len) in +// getSegment(rawHopFields, consDir, peer, currHF, numHF) +// } +// /* +// ghost +// decreases +// pure func getPkt1Seg(raw []byte, consDir bool, peer bool, currHF int, seg1Len uint8) io.IO_pkt2{ +// io.IO_pkt2(io.IO_Packet2{ +// CurrSeg : getSegments2(raw, consDir, peer, currHF), +// LeftSeg : None, +// MidSeg : None, +// RightSeg : None, +// }) +// } +// */ + +// ghost +// decreases +// pure func getPkt2Seg(raw []byte, seg1Len uint8, seg2Len uint8) io.IO_pkt2 + +// ghost +// decreases +// pure func getPkt3Seg(raw []byte, seg1Len uint8, seg2Len uint8, seg3Len uint8) io.IO_pkt2 + +// ghost +// decreases +// pure func tmpCurrSeg(raw []byte) io.IO_seg3 + ghost decreases -pure func getSegFuture(raw []byte, offset int) seq[io.IO_HF]{ - return offset == len(raw) ? seq[io.IO_HF]{} : seq[io.IO_HF]{getHopField(raw[offset:offset+12])} ++ getSegFuture(raw, offset+12) -} +pure func tmpLeftSeg(raw []byte) option[io.IO_seg2] -//TODO double check if order is correct ghost decreases -pure func getSegHistory(raw []byte, offset int) seq[io.IO_ahi]{ - return offset == -1 ? seq[io.IO_ahi]{} : seq[io.IO_ahi]{getHopField(raw[offset:offset+12]).Toab()} ++ getSegHistory(raw, offset-12) -} +pure func tmpMidSeg(raw []byte) option[io.IO_seg2] + +ghost +decreases +pure func tmpRightSeg(raw []byte) option[io.IO_seg2] + -// TODO Can we add a body? +// ghost +// requires numHF*12 + 12 <= len(raw) +// requires numHF >= currHF && currHF >= 0 +// requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +// requires (forall k int, i int :: 0 <=k && k <= numHF && 0 <= i && i < 12 ==> unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in &raw[k*12:k*12+12][i] == &raw[k*12+i]) +// decreases _ +// pure func getSegment(raw []byte, consDir bool, peer bool, currHF int, numHF int) io.IO_seg2{ +// return io.IO_seg2(io.IO_seg3_{ +// AInfo : computeAInfo(raw), +// UInfo : computeUInfo(raw), +// ConsDir : consDir, +// Peer : peer, +// Past : getSegPast(raw, currHF - 1), +// Future : getSegFuture2(raw, currHF, numHF), +// History : getSegHistory(raw, currHF - 1), +// }) +// } + + +// /* +// //TODO mistake, +// //not interested in currHF's ConsDir, Peer field but for one of the three segments +// ghost +// decreases +// pure func getSegments(raw []byte) io.IO_seg2{ +// return let line := binary.BigEndian.Uint32(raw[0:4]) in +// let currINF := uint8(line >> 30) in +// let currHF := uint8(line >> 24) & 0x3F in +// let seg1Len := uint8(line >> 12) & 0x3F in +// let seg2Len := uint8(line >> 6) & 0x3F in +// let seg3Len := uint8(line) & 0x3F in +// let numINF := numInfoFields(seg1Len, seg2Len, seg3Len) in +// let rawHopFields := getSegBytes(raw[4+8*numINF:], int(currHF), int(seg1Len), int(seg2Len), int(seg3Len)) in +// let rawHopFieldsOffset := computeSeqOffset(currHF, seg1Len, seg2Len, seg3Len) - 1 in +// io.IO_seg2(io.IO_seg3_{ +// AInfo : computeAInfo(raw), +// UInfo : computeUInfo(raw), +// ConsDir : raw[infoFieldOffsetSeg(int(currINF))] & 0x1 == 0x1, +// Peer : raw[infoFieldOffsetSeg(int(currINF))] & 0x2 == 0x2, +// Past : getSegPast(rawHopFields, rawHopFieldsOffset - 1), +// Future : getSegFuture(rawHopFields, rawHopFieldsOffset), +// History : getSegHistory(rawHopFields, rawHopFieldsOffset - 1), +// }) +// } +// */ + + +// //expects the raw bytes of a Hopfield +// ghost +// requires len(raw) > 6 +// requires acc(&raw[2], _) && acc(&raw[3], _) && acc(&raw[4], _) && acc(&raw[5], _) +// decreases +// pure func getHopField(raw []byte) io.IO_HF { +// return let inif2 := binary.BigEndian.Uint16(raw[2:4]) == 0 ? none[io.IO_ifs] : some(io.IO_ifs(binary.BigEndian.Uint16(raw[2:4]))) in +// let egif2 := binary.BigEndian.Uint16(raw[4:6])== 0 ? none[io.IO_ifs] : some(io.IO_ifs(binary.BigEndian.Uint16(raw[4:6]))) in +// io.IO_HF(io.IO_HF_{ +// InIF2 : inif2, +// EgIF2 : egif2, +// HVF : computeMsgTerm(raw), +// }) +// } + +// //assumption at least seg1Len > 0 correct? +// ghost +// decreases +// pure func numInfoFields(seg1Len uint8, seg2Len uint8, seg3Len uint8) uint8 { +// return seg3Len > 0 ? 3 : (seg2Len > 0 ? 2 : 1) +// } + +// ghost +// decreases +// pure func infoFieldOffsetSeg(currINF int) int{ +// return 4 + 8 * currINF +// } + +// ghost +// decreases +// pure func computeSeqOffset(currHF uint8, seg1Len uint8, seg2Len uint8, seg3Len uint8) int{ +// return seg1Len > currHF ? int(currHF)*12 : (seg2Len > currHF ? int(currHF-seg1Len) * 12 : int(currHF-seg2Len-seg1Len)* 12) +// } + +// ghost +// decreases +// pure func computeSeqlen(currHF int, seg1Len int, seg2Len int, seg3Len int) int{ +// return seg1Len > currHF ? seg1Len : (seg2Len > currHF ? seg2Len: seg3Len) +// } + +// ghost +// requires int(seg1Len + seg2Len + seg3Len)*12 <= len(raw) +// requires 0 <= seg1Len && seg1Len*12 <= len(raw) +// requires 0 <= seg2Len && (seg1Len+seg2Len)*12 <= len(raw) +// requires 0 <= seg3Len && (seg1Len+seg2Len+seg3Len)*12 <= len(raw) +// //requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +// //ensures acc(sl.AbsSlice_Bytes(raw, 0, len(res))) +// decreases +// pure func getSegBytes(raw []byte, currHF int, seg1Len int, seg2Len int, seg3Len int) []byte { +// //unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in +// return seg1Len > currHF ? +// raw[0:seg1Len*12] : (seg2Len > currHF ? +// raw[seg1Len*12:(seg1Len + seg2Len)*12] : +// raw[(seg1Len + seg2Len)*12:(seg1Len + seg2Len + seg3Len)*12]) +// } +// //different approach: +// //expects bytes of Hopfields of whole packet +// /*ghost +// requires numHF*12 + 12 < len(raw) +// requires numHF >= 0 +// requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +// requires forall k int, i int :: 0<=k && k <= numHF && 0 <= i && i < 12 ==> unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in &raw[k*12:k*12+12][i] == &raw[k*12+i] +// decreases _ +// pure func toSeqIO_HF_rev(raw []byte, numHF int) seq[io.IO_HF]{ +// return numHF == 0 ? +// (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in seq[io.IO_HF]{getHopField(raw[0:12])}) : +// (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in seq[io.IO_HF]{getHopField(raw[numHF*12:numHF*12+12])}) ++ getSegPast(raw, numHF-1) +// }*/ + + +// //--------------------------------------- + + +// //TODO proof termination +// //expects the raw bytes of the Hopfields of a segment +// ghost +// requires offset*12 + 12 <= len(raw) +// requires offset >= -1 +// requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +// requires offset >= 0 ==> +// (forall k int, i int :: 0 <=k && k <= offset && 0 <= i && i < 12 ==> unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in &raw[k*12:k*12+12][i] == &raw[k*12+i]) +// decreases _ +// pure func getSegPast(raw []byte, offset int) seq[io.IO_HF]{ +// return offset == -1 ? seq[io.IO_HF]{} : +// (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in seq[io.IO_HF]{getHopField(raw[offset*12:offset*12+12])}) ++ getSegPast(raw, offset-1) +// } + + +// //TODO proof termination +// //expects the raw bytes of the Hopfields of a segment +// ghost +// requires offset*12 == len(raw) || offset*12 + 12 < len(raw) +// requires offset >= 0 +// requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +// requires offset*12 < len(raw) ==> +// (forall k int, i int :: 0 <= k && k <= offset && 0 <= i && i < 12 ==> unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in &raw[k*12:k*12+12][i] == &raw[k*12+i]) +// decreases _ +// pure func getSegFuture(raw []byte, offset int) seq[io.IO_HF]{ +// return offset*12 == len(raw) ? seq[io.IO_HF]{} : +// getSegFuture(raw, offset-1) ++ (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in seq[io.IO_HF]{getHopField(raw[offset*12:offset*12+12])}) +// } + +// ghost +// requires offset*12 + 12 <= len(raw) +// requires offset >= currHF && currHF >= 0 +// requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +// requires forall k int, i int :: 0 <= k && k <= offset && 0 <= i && i < 12 ==> unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in &raw[k*12:k*12+12][i] == &raw[k*12+i] +// decreases _ +// pure func getSegFuture2(raw []byte, currHF int, offset int) seq[io.IO_HF]{ +// return offset == currHF ? (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in seq[io.IO_HF]{getHopField(raw[offset*12:offset*12+12])}) : +// getSegFuture2(raw, currHF, offset-1) ++ (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in seq[io.IO_HF]{getHopField(raw[offset*12:offset*12+12])}) +// } + +// //TODO proof termination +// //expects the raw bytes of the Hopfields of a segment +// ghost +// requires offset*12 + 12 <= len(raw) +// requires offset >= -1 +// requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +// requires offset >= 0 ==> +// (forall k int, i int :: 0<=k && k <= offset && 0 <= i && i < 12 ==> unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in &raw[k*12:k*12+12][i] == &raw[k*12+i]) +// decreases _ +// pure func getSegHistory(raw []byte, offset int) seq[io.IO_ahi]{ +// return offset == -1 ? seq[io.IO_ahi]{} : +// (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in seq[io.IO_ahi]{getHopField(raw[offset*12:offset*12+12]).Toab()}) ++ getSegHistory(raw, offset-1) +// } + +// TODO Do we need a body? ghost decreases -pure func computeMsgTerm(raw []byte) io.IO_msgterm +pure func computeMsgTerm(raw []byte, start int) io.IO_msgterm ghost decreases _ From 3246a2bea077ee3782ee19e087cf215badfe7832 Mon Sep 17 00:00:00 2001 From: MLETHZ Date: Tue, 11 Jul 2023 11:53:12 +0200 Subject: [PATCH 08/33] spec to pkt (left, mid, right) --- router/dataplane_spec.gobra | 97 +++++++++++++++++++++++++++++++++++-- 1 file changed, 94 insertions(+), 3 deletions(-) diff --git a/router/dataplane_spec.gobra b/router/dataplane_spec.gobra index 11094bf3d..2a2c8a8f2 100644 --- a/router/dataplane_spec.gobra +++ b/router/dataplane_spec.gobra @@ -465,6 +465,26 @@ pure func getSegment(raw []byte, consDir bool, peer bool, currHF int, prevSegLen }) } +ghost +//expects the raw bytes of whole path +requires 4 + 8 * numINF + 12*prevSegLen + 12*segLen <= len(raw) +requires prevSegLen >= 0 && segLen >= 0 +requires 0 < numINF && numINF < 4 +requires segLen+prevSegLen > currHF && currHF >= prevSegLen +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +decreases _ +pure func getPastSegment(raw []byte, consDir bool, peer bool, currHF int, prevSegLen int, segLen int, numINF int) io.IO_seg2{ + return io.IO_seg2(io.IO_seg3_{ + AInfo : computeAInfo(raw), + UInfo : computeUInfo(raw), + ConsDir : consDir, + Peer : peer, + Past : getSegPast(raw, prevSegLen, currHF, numINF), + Future : seq[io.IO_HF]{}, + History : getSegHistory(raw, prevSegLen, currHF, numINF), + }) +} + ghost requires seg1Len > 0 @@ -489,6 +509,77 @@ pure func getCurrSeg(raw []byte, currINF int, currHF int, seg1Len int, seg2Len i getSegment(raw, consDir, peer, currHF, prevSegLen, segLen, numINF) } + +ghost +requires seg1Len > 0 +requires seg2Len >= 0 +requires seg3Len >= 0 +requires 4 + 8*numInfoFields(seg1Len, seg2Len, seg3Len) + 12 * seg1Len + 12 * seg2Len + 12 * seg3Len == len(raw) +//requires 12*computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) + +// 12*computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) <= 12 * seg1Len + 12 * seg2Len + 12 * seg3Len +requires 0 <= currINF && currINF < 3 +requires 0 <= currHF && currHF < seg1Len + seg2Len + seg3Len +// requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) > currHF +requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) + computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF +//requires currHF >= computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +decreases _ +pure func getLeftSeg(raw []byte, currINF int, currHF int, seg1Len int, seg2Len int, seg3Len int) option[io.IO_seg3] { + return let newCurrHF := computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) + computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) in + (newCurrHF == seg1Len + seg2Len + seg3Len || currINF == 2) ? none[io.IO_seg3] : + some(getCurrSeg(raw, currINF + 1, newCurrHF, seg1Len, seg2Len, seg3Len)) +} + +ghost +requires seg1Len > 0 +requires seg2Len >= 0 +requires seg3Len >= 0 +requires 4 + 8*numInfoFields(seg1Len, seg2Len, seg3Len) + 12 * seg1Len + 12 * seg2Len + 12 * seg3Len == len(raw) +//requires 12*computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) + +// 12*computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) <= 12 * seg1Len + 12 * seg2Len + 12 * seg3Len +requires 0 <= currINF && currINF < 3 +requires 0 <= currHF && currHF < seg1Len + seg2Len + seg3Len +// requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) > currHF +requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) + computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF +//requires currHF >= computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +decreases _ +pure func getRightSeg(raw []byte, currINF int, currHF int, seg1Len int, seg2Len int, seg3Len int) option[io.IO_seg3] { + return (computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) == 0 || currINF == 0) ? none[io.IO_seg3] : + (let newCurrHF := computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len)-1 in + let consDir := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in raw[infoFieldOffsetSeg(currINF-1)] & 0x1 == 0x1) in + let peer := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in raw[infoFieldOffsetSeg(currINF-1)] & 0x2 == 0x2) in + let segLen := computeSeqlen(newCurrHF, seg1Len, seg2Len, seg3Len) in + let prevSegLen := computeprevSegLen(newCurrHF, seg1Len, seg2Len, seg3Len) in + let numINF := numInfoFields(seg1Len, seg2Len, seg3Len) in + some(getPastSegment(raw, consDir, peer, newCurrHF, prevSegLen, segLen, numINF))) +} + + +ghost +requires seg1Len > 0 +requires seg2Len >= 0 +requires seg3Len >= 0 +requires 4 + 8*numInfoFields(seg1Len, seg2Len, seg3Len) + 12 * seg1Len + 12 * seg2Len + 12 * seg3Len == len(raw) +//requires 12*computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) + +// 12*computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) <= 12 * seg1Len + 12 * seg2Len + 12 * seg3Len +requires 0 <= currINF && currINF < 3 +requires 0 <= currHF && currHF < seg1Len + seg2Len + seg3Len +// requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) > currHF +requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) + computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF +//requires currHF >= computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +decreases _ +pure func getMidSeg(raw []byte, currINF int, currHF int, seg1Len int, seg2Len int, seg3Len int) option[io.IO_seg3] { + return seg3Len == 0 ? none[io.IO_seg3] : + (computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) == seg1Len) ? none[io.IO_seg3] : + (computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) == 0) ? some(getCurrSeg(raw, 2, seg1Len + seg2Len, seg1Len, seg2Len, seg3Len)) : + (let consDir := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in raw[infoFieldOffsetSeg(0)] & 0x1 == 0x1) in + let peer := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in raw[infoFieldOffsetSeg(0)] & 0x2 == 0x2) in + let numINF := numInfoFields(seg1Len, seg2Len, seg3Len) in + some(getPastSegment(raw, consDir, peer, seg1Len-1, 0, seg1Len, numINF))) +} + /** tmp - helper functions TODO prove these functions **/ @@ -536,9 +627,9 @@ pure func getPkt(raw []byte) io.IO_pkt2{ let seg3Len := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in uint8(hdr) & 0x3F in io.IO_pkt2(io.IO_Packet2{ CurrSeg : getCurrSeg(raw, int(currINF), int(currHF), int(seg1Len), int(seg2Len), int(seg3Len)), - LeftSeg : tmpLeftSeg(raw), - MidSeg : tmpMidSeg(raw), - RightSeg : tmpRightSeg(raw), + LeftSeg : getLeftSeg(raw, int(currINF), int(currHF), int(seg1Len), int(seg2Len), int(seg3Len)), + MidSeg : getMidSeg(raw, int(currINF), int(currHF), int(seg1Len), int(seg2Len), int(seg3Len)), + RightSeg : getRightSeg(raw, int(currINF), int(currHF), int(seg1Len), int(seg2Len), int(seg3Len)), }) } From 35ff392029ce68a1663df1b3330a777e1cada9c6 Mon Sep 17 00:00:00 2001 From: MLETHZ Date: Tue, 11 Jul 2023 16:11:51 +0200 Subject: [PATCH 09/33] spec to pkt (termination) --- router/dataplane_spec.gobra | 46 ++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/router/dataplane_spec.gobra b/router/dataplane_spec.gobra index 2a2c8a8f2..1a7d3821b 100644 --- a/router/dataplane_spec.gobra +++ b/router/dataplane_spec.gobra @@ -411,7 +411,7 @@ requires 4 + 8 * numINF + offset*12 + 12 <= len(raw) requires prevSegLen >= 0 && offset - prevSegLen >= -1 requires 0 < numINF && numINF < 4 requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -decreases _ +decreases offset - prevSegLen + 1 pure func getSegPast(raw []byte, prevSegLen int, offset int, numINF int) seq[io.IO_HF]{ return offset - prevSegLen == -1 ? seq[io.IO_HF]{} : (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in @@ -423,7 +423,7 @@ requires 4 + 8 * numINF + offset*12 + 12 <= len(raw) requires offset >= currHF && currHF >= 0 requires 0 < numINF && numINF < 4 requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -decreases _ +decreases offset - currHF pure func getSegFuture(raw []byte, currHF int, offset int, numINF int) seq[io.IO_HF]{ return offset == currHF ? (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in seq[io.IO_HF]{getHopField(raw,4 + 8 * numINF + offset*12)}) : getSegFuture(raw, currHF, offset-1, numINF) ++ (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in seq[io.IO_HF]{getHopField(raw, 4 + 8 * numINF + offset*12)}) @@ -436,7 +436,7 @@ requires 4 + 8 * numINF + offset*12 + 12 <= len(raw) requires prevSegLen >= 0 && offset - prevSegLen >= -1 requires 0 < numINF && numINF < 4 requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -decreases _ +decreases offset - prevSegLen + 1 pure func getSegHistory(raw []byte, prevSegLen int, offset int, numINF int) seq[io.IO_ahi]{ return offset - prevSegLen == -1 ? seq[io.IO_ahi]{} : (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in @@ -452,11 +452,11 @@ requires prevSegLen >= 0 && segLen >= 0 requires 0 < numINF && numINF < 4 requires segLen+prevSegLen > currHF && currHF >= prevSegLen requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -decreases _ -pure func getSegment(raw []byte, consDir bool, peer bool, currHF int, prevSegLen int, segLen int, numINF int) io.IO_seg2{ +decreases +pure func getSegment(raw []byte, consDir bool, peer bool, currHF int, prevSegLen int, segLen int, numINF int, currINF int) io.IO_seg2{ return io.IO_seg2(io.IO_seg3_{ - AInfo : computeAInfo(raw), - UInfo : computeUInfo(raw), + AInfo : computeAInfo(raw, currINF), + UInfo : computeUInfo(raw, currINF), ConsDir : consDir, Peer : peer, Past : getSegPast(raw, prevSegLen, currHF - 1, numINF), @@ -472,11 +472,11 @@ requires prevSegLen >= 0 && segLen >= 0 requires 0 < numINF && numINF < 4 requires segLen+prevSegLen > currHF && currHF >= prevSegLen requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -decreases _ -pure func getPastSegment(raw []byte, consDir bool, peer bool, currHF int, prevSegLen int, segLen int, numINF int) io.IO_seg2{ +decreases +pure func getPastSegment(raw []byte, consDir bool, peer bool, currHF int, prevSegLen int, segLen int, numINF int, currINF int) io.IO_seg2{ return io.IO_seg2(io.IO_seg3_{ - AInfo : computeAInfo(raw), - UInfo : computeUInfo(raw), + AInfo : computeAInfo(raw, currINF), + UInfo : computeUInfo(raw, currINF), ConsDir : consDir, Peer : peer, Past : getSegPast(raw, prevSegLen, currHF, numINF), @@ -499,14 +499,14 @@ requires 0 <= currHF && currHF < seg1Len + seg2Len + seg3Len requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) + computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF //requires currHF >= computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -decreases _ +decreases pure func getCurrSeg(raw []byte, currINF int, currHF int, seg1Len int, seg2Len int, seg3Len int) io.IO_seg3 { return let consDir := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in raw[infoFieldOffsetSeg(currINF)] & 0x1 == 0x1) in let peer := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in raw[infoFieldOffsetSeg(currINF)] & 0x2 == 0x2) in let segLen := computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) in let prevSegLen := computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) in let numINF := numInfoFields(seg1Len, seg2Len, seg3Len) in - getSegment(raw, consDir, peer, currHF, prevSegLen, segLen, numINF) + getSegment(raw, consDir, peer, currHF, prevSegLen, segLen, numINF, currINF) } @@ -523,7 +523,7 @@ requires 0 <= currHF && currHF < seg1Len + seg2Len + seg3Len requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) + computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF //requires currHF >= computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -decreases _ +decreases pure func getLeftSeg(raw []byte, currINF int, currHF int, seg1Len int, seg2Len int, seg3Len int) option[io.IO_seg3] { return let newCurrHF := computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) + computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) in (newCurrHF == seg1Len + seg2Len + seg3Len || currINF == 2) ? none[io.IO_seg3] : @@ -543,7 +543,7 @@ requires 0 <= currHF && currHF < seg1Len + seg2Len + seg3Len requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) + computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF //requires currHF >= computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -decreases _ +decreases pure func getRightSeg(raw []byte, currINF int, currHF int, seg1Len int, seg2Len int, seg3Len int) option[io.IO_seg3] { return (computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) == 0 || currINF == 0) ? none[io.IO_seg3] : (let newCurrHF := computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len)-1 in @@ -552,7 +552,7 @@ pure func getRightSeg(raw []byte, currINF int, currHF int, seg1Len int, seg2Len let segLen := computeSeqlen(newCurrHF, seg1Len, seg2Len, seg3Len) in let prevSegLen := computeprevSegLen(newCurrHF, seg1Len, seg2Len, seg3Len) in let numINF := numInfoFields(seg1Len, seg2Len, seg3Len) in - some(getPastSegment(raw, consDir, peer, newCurrHF, prevSegLen, segLen, numINF))) + some(getPastSegment(raw, consDir, peer, newCurrHF, prevSegLen, segLen, numINF, currINF))) } @@ -569,7 +569,7 @@ requires 0 <= currHF && currHF < seg1Len + seg2Len + seg3Len requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) + computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF //requires currHF >= computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -decreases _ +decreases pure func getMidSeg(raw []byte, currINF int, currHF int, seg1Len int, seg2Len int, seg3Len int) option[io.IO_seg3] { return seg3Len == 0 ? none[io.IO_seg3] : (computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) == seg1Len) ? none[io.IO_seg3] : @@ -577,7 +577,7 @@ pure func getMidSeg(raw []byte, currINF int, currHF int, seg1Len int, seg2Len in (let consDir := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in raw[infoFieldOffsetSeg(0)] & 0x1 == 0x1) in let peer := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in raw[infoFieldOffsetSeg(0)] & 0x2 == 0x2) in let numINF := numInfoFields(seg1Len, seg2Len, seg3Len) in - some(getPastSegment(raw, consDir, peer, seg1Len-1, 0, seg1Len, numINF))) + some(getPastSegment(raw, consDir, peer, seg1Len-1, 0, seg1Len, numINF, currINF))) } /** tmp - helper functions @@ -617,7 +617,7 @@ requires unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in //uint8(hdr >> 6) & 0x3F >= 0 && //uint8(hdr) & 0x3F >= 0 && 4 + 8*numInfoFields(int(uint8(hdr >> 12) & 0x3F), int(uint8(hdr >> 6) & 0x3F), int(uint8(hdr) & 0x3F)) + 12 * int(uint8(hdr >> 12) & 0x3F) + 12 * int(uint8(hdr >> 6) & 0x3F) + 12 * int(uint8(hdr) & 0x3F) == len(raw) -decreases _ +decreases pure func getPkt(raw []byte) io.IO_pkt2{ return let hdr := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in binary.BigEndian.Uint32(raw[0:4]) in let currINF := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in uint8(hdr >> 30) in @@ -870,11 +870,11 @@ decreases pure func computeMsgTerm(raw []byte, start int) io.IO_msgterm ghost -decreases _ -pure func computeAInfo(raw []byte) io.IO_ainfo +decreases +pure func computeAInfo(raw []byte, currINF int) io.IO_ainfo ghost -decreases _ -pure func computeUInfo(raw []byte) set[io.IO_msgterm] +decreases +pure func computeUInfo(raw []byte, currINF int) set[io.IO_msgterm] /** End of io-spec helper functions **/ \ No newline at end of file From f925f1010a283818a660fc400cdb1c7458f2b7f3 Mon Sep 17 00:00:00 2001 From: MLETHZ Date: Mon, 17 Jul 2023 10:04:09 +0200 Subject: [PATCH 10/33] code clean up --- router/dataplane_spec.gobra | 290 ++---------------------------------- 1 file changed, 10 insertions(+), 280 deletions(-) diff --git a/router/dataplane_spec.gobra b/router/dataplane_spec.gobra index 1a7d3821b..5db1fb861 100644 --- a/router/dataplane_spec.gobra +++ b/router/dataplane_spec.gobra @@ -404,7 +404,7 @@ pure func getHopField(raw []byte, start int) io.IO_HF { }) } -//TODO proof termination + //expects the raw bytes of whole path ghost requires 4 + 8 * numINF + offset*12 + 12 <= len(raw) @@ -418,6 +418,7 @@ pure func getSegPast(raw []byte, prevSegLen int, offset int, numINF int) seq[io. seq[io.IO_HF]{getHopField(raw,4 + 8 * numINF + offset*12)}) ++ getSegPast(raw, prevSegLen, offset-1, numINF) } +//expects the raw bytes of whole path ghost requires 4 + 8 * numINF + offset*12 + 12 <= len(raw) requires offset >= currHF && currHF >= 0 @@ -429,7 +430,6 @@ pure func getSegFuture(raw []byte, currHF int, offset int, numINF int) seq[io.IO getSegFuture(raw, currHF, offset-1, numINF) ++ (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in seq[io.IO_HF]{getHopField(raw, 4 + 8 * numINF + offset*12)}) } -//TODO proof termination //expects the raw bytes of whole path ghost requires 4 + 8 * numINF + offset*12 + 12 <= len(raw) @@ -491,13 +491,9 @@ requires seg1Len > 0 requires seg2Len >= 0 requires seg3Len >= 0 requires 4 + 8*numInfoFields(seg1Len, seg2Len, seg3Len) + 12 * seg1Len + 12 * seg2Len + 12 * seg3Len == len(raw) -//requires 12*computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) + -// 12*computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) <= 12 * seg1Len + 12 * seg2Len + 12 * seg3Len requires 0 <= currINF && currINF < 3 requires 0 <= currHF && currHF < seg1Len + seg2Len + seg3Len -// requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) > currHF requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) + computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF -//requires currHF >= computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases pure func getCurrSeg(raw []byte, currINF int, currHF int, seg1Len int, seg2Len int, seg3Len int) io.IO_seg3 { @@ -515,13 +511,9 @@ requires seg1Len > 0 requires seg2Len >= 0 requires seg3Len >= 0 requires 4 + 8*numInfoFields(seg1Len, seg2Len, seg3Len) + 12 * seg1Len + 12 * seg2Len + 12 * seg3Len == len(raw) -//requires 12*computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) + -// 12*computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) <= 12 * seg1Len + 12 * seg2Len + 12 * seg3Len requires 0 <= currINF && currINF < 3 requires 0 <= currHF && currHF < seg1Len + seg2Len + seg3Len -// requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) > currHF requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) + computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF -//requires currHF >= computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases pure func getLeftSeg(raw []byte, currINF int, currHF int, seg1Len int, seg2Len int, seg3Len int) option[io.IO_seg3] { @@ -535,13 +527,9 @@ requires seg1Len > 0 requires seg2Len >= 0 requires seg3Len >= 0 requires 4 + 8*numInfoFields(seg1Len, seg2Len, seg3Len) + 12 * seg1Len + 12 * seg2Len + 12 * seg3Len == len(raw) -//requires 12*computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) + -// 12*computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) <= 12 * seg1Len + 12 * seg2Len + 12 * seg3Len requires 0 <= currINF && currINF < 3 requires 0 <= currHF && currHF < seg1Len + seg2Len + seg3Len -// requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) > currHF requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) + computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF -//requires currHF >= computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases pure func getRightSeg(raw []byte, currINF int, currHF int, seg1Len int, seg2Len int, seg3Len int) option[io.IO_seg3] { @@ -561,13 +549,9 @@ requires seg1Len > 0 requires seg2Len >= 0 requires seg3Len >= 0 requires 4 + 8*numInfoFields(seg1Len, seg2Len, seg3Len) + 12 * seg1Len + 12 * seg2Len + 12 * seg3Len == len(raw) -//requires 12*computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) + -// 12*computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) <= 12 * seg1Len + 12 * seg2Len + 12 * seg3Len requires 0 <= currINF && currINF < 3 requires 0 <= currHF && currHF < seg1Len + seg2Len + seg3Len -// requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) > currHF requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) + computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF -//requires currHF >= computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases pure func getMidSeg(raw []byte, currINF int, currHF int, seg1Len int, seg2Len int, seg3Len int) option[io.IO_seg3] { @@ -580,42 +564,19 @@ pure func getMidSeg(raw []byte, currINF int, currHF int, seg1Len int, seg2Len in some(getPastSegment(raw, consDir, peer, seg1Len-1, 0, seg1Len, numINF, currINF))) } -/** tmp - helper functions -TODO prove these functions **/ - -//TODO too strong assumption? -ghost -requires line == uint32(raw3) | uint32(raw2)<<8 | uint32(raw1)<<16 | uint32(raw0)<<24 -//preserves (raw0 & 0x3F) >= 0 //l3 -//preserves (raw2 >> 4 | raw1 << 4) & 0x3F > 0 -//preserves (raw3 >> 6 | raw2 << 2) & 0x3F >= 0 -//preserves (raw3 & 0x3F) >= 0 -ensures uint8(line >> 30) == raw0 >> 6 -ensures uint8(line >> 24) & 0x3F == (raw0 & 0x3F) -ensures uint8(line >> 12) & 0x3F == (raw2 >> 4 | raw1 << 4) & 0x3F -ensures uint8(line >> 6) & 0x3F == (raw3 >> 6 | raw2 << 2) & 0x3F -ensures uint8(line) & 0x3F == raw3 & 0x3F -ensures 0 <= uint8(line >> 30) && uint8(line >> 30) < 3 //currINF -ensures 0 <= (uint8(line >> 24) & 0x3F) && (uint8(line >> 24) & 0x3F) < (uint8(line >> 12) & 0x3F) + (uint8(line >> 6) & 0x3F) + (uint8(line) & 0x3F) //currHF -ensures 0 < uint8(line >> 12) & 0x3F //seg1Len -ensures 0 <= uint8(line >> 6) & 0x3F //seg2Len -ensures 0 <= uint8(line) & 0x3F //seg3Len -ensures res == true -decreases -pure func DeserializingHdr(raw0, raw1, raw2, raw3 uint8, line uint32) (res bool) - -/** End of of assumed functions **/ - +//TODO improve preconditions ghost requires len(raw) > 4 requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) requires unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in let hdr := binary.BigEndian.Uint32(raw[0:4]) in - hdr == (uint32(raw[3]) | uint32(raw[2])<<8 | uint32(raw[1])<<16 | uint32(raw[0])<<24) && - DeserializingHdr(raw[0], raw[1], raw[2], raw[3], hdr) && - //uint8(hdr >> 12) & 0x3F > 0 && - //uint8(hdr >> 6) & 0x3F >= 0 && - //uint8(hdr) & 0x3F >= 0 && + //hdr == (uint32(raw[3]) | uint32(raw[2])<<8 | uint32(raw[1])<<16 | uint32(raw[0])<<24) && + //DeserializingHdr(raw[0], raw[1], raw[2], raw[3], hdr) && + 0 <= uint8(hdr >> 30) && uint8(hdr >> 30) < 3 && //currINF + 0 <= (uint8(hdr >> 24) & 0x3F) && (uint8(hdr >> 24) & 0x3F) < (uint8(hdr >> 12) & 0x3F) + (uint8(hdr >> 6) & 0x3F) + (uint8(hdr) & 0x3F) && //currHF + 0 < uint8(hdr >> 12) & 0x3F && //seg1Len + 0 <= uint8(hdr >> 6) & 0x3F && //seg2Len + 0 <= uint8(hdr) & 0x3F && //seg3Len 4 + 8*numInfoFields(int(uint8(hdr >> 12) & 0x3F), int(uint8(hdr >> 6) & 0x3F), int(uint8(hdr) & 0x3F)) + 12 * int(uint8(hdr >> 12) & 0x3F) + 12 * int(uint8(hdr >> 6) & 0x3F) + 12 * int(uint8(hdr) & 0x3F) == len(raw) decreases pure func getPkt(raw []byte) io.IO_pkt2{ @@ -633,237 +594,6 @@ pure func getPkt(raw []byte) io.IO_pkt2{ }) } - -// //TODO remove additional variable rawHopFields -// ghost -// //requires int(seg1Len + seg2Len + seg3Len)*12 <= len(raw) -// //requires 0 <= seg1Len && seg1Len*12 <= len(raw) -// //requires 0 <= seg2Len && (seg1Len + seg2Len)*12 <= len(raw) -// //requires 0 <= seg3Len && (seg1Len + seg2Len + seg3Len)*12 <= len(raw) -// requires len(raw) > infoFieldOffsetSeg(currINF) -// requires currINF >= 0 -// requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -// requires acc(sl.AbsSlice_Bytes(rawHopFields, 0, len(rawHopFields)), _) -// decreases _ -// pure func getCurrSeg(raw []byte, rawHopFields []byte, currINF int, currHF int, seg1Len int, seg2Len int, seg3Len int) io.IO_seg3 { -// return let consDir := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in raw[infoFieldOffsetSeg(currINF)] & 0x1 == 0x1) in -// let peer := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in raw[infoFieldOffsetSeg(currINF)] & 0x2 == 0x2) in -// let numHF := computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) in -// //let rawHopFields := getSegBytes(raw, currHF, seg1Len, seg2Len, seg3Len) in -// getSegment(rawHopFields, consDir, peer, currHF, numHF) -// } -// /* -// ghost -// decreases -// pure func getPkt1Seg(raw []byte, consDir bool, peer bool, currHF int, seg1Len uint8) io.IO_pkt2{ -// io.IO_pkt2(io.IO_Packet2{ -// CurrSeg : getSegments2(raw, consDir, peer, currHF), -// LeftSeg : None, -// MidSeg : None, -// RightSeg : None, -// }) -// } -// */ - -// ghost -// decreases -// pure func getPkt2Seg(raw []byte, seg1Len uint8, seg2Len uint8) io.IO_pkt2 - -// ghost -// decreases -// pure func getPkt3Seg(raw []byte, seg1Len uint8, seg2Len uint8, seg3Len uint8) io.IO_pkt2 - -// ghost -// decreases -// pure func tmpCurrSeg(raw []byte) io.IO_seg3 - -ghost -decreases -pure func tmpLeftSeg(raw []byte) option[io.IO_seg2] - -ghost -decreases -pure func tmpMidSeg(raw []byte) option[io.IO_seg2] - -ghost -decreases -pure func tmpRightSeg(raw []byte) option[io.IO_seg2] - - -// ghost -// requires numHF*12 + 12 <= len(raw) -// requires numHF >= currHF && currHF >= 0 -// requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -// requires (forall k int, i int :: 0 <=k && k <= numHF && 0 <= i && i < 12 ==> unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in &raw[k*12:k*12+12][i] == &raw[k*12+i]) -// decreases _ -// pure func getSegment(raw []byte, consDir bool, peer bool, currHF int, numHF int) io.IO_seg2{ -// return io.IO_seg2(io.IO_seg3_{ -// AInfo : computeAInfo(raw), -// UInfo : computeUInfo(raw), -// ConsDir : consDir, -// Peer : peer, -// Past : getSegPast(raw, currHF - 1), -// Future : getSegFuture2(raw, currHF, numHF), -// History : getSegHistory(raw, currHF - 1), -// }) -// } - - -// /* -// //TODO mistake, -// //not interested in currHF's ConsDir, Peer field but for one of the three segments -// ghost -// decreases -// pure func getSegments(raw []byte) io.IO_seg2{ -// return let line := binary.BigEndian.Uint32(raw[0:4]) in -// let currINF := uint8(line >> 30) in -// let currHF := uint8(line >> 24) & 0x3F in -// let seg1Len := uint8(line >> 12) & 0x3F in -// let seg2Len := uint8(line >> 6) & 0x3F in -// let seg3Len := uint8(line) & 0x3F in -// let numINF := numInfoFields(seg1Len, seg2Len, seg3Len) in -// let rawHopFields := getSegBytes(raw[4+8*numINF:], int(currHF), int(seg1Len), int(seg2Len), int(seg3Len)) in -// let rawHopFieldsOffset := computeSeqOffset(currHF, seg1Len, seg2Len, seg3Len) - 1 in -// io.IO_seg2(io.IO_seg3_{ -// AInfo : computeAInfo(raw), -// UInfo : computeUInfo(raw), -// ConsDir : raw[infoFieldOffsetSeg(int(currINF))] & 0x1 == 0x1, -// Peer : raw[infoFieldOffsetSeg(int(currINF))] & 0x2 == 0x2, -// Past : getSegPast(rawHopFields, rawHopFieldsOffset - 1), -// Future : getSegFuture(rawHopFields, rawHopFieldsOffset), -// History : getSegHistory(rawHopFields, rawHopFieldsOffset - 1), -// }) -// } -// */ - - -// //expects the raw bytes of a Hopfield -// ghost -// requires len(raw) > 6 -// requires acc(&raw[2], _) && acc(&raw[3], _) && acc(&raw[4], _) && acc(&raw[5], _) -// decreases -// pure func getHopField(raw []byte) io.IO_HF { -// return let inif2 := binary.BigEndian.Uint16(raw[2:4]) == 0 ? none[io.IO_ifs] : some(io.IO_ifs(binary.BigEndian.Uint16(raw[2:4]))) in -// let egif2 := binary.BigEndian.Uint16(raw[4:6])== 0 ? none[io.IO_ifs] : some(io.IO_ifs(binary.BigEndian.Uint16(raw[4:6]))) in -// io.IO_HF(io.IO_HF_{ -// InIF2 : inif2, -// EgIF2 : egif2, -// HVF : computeMsgTerm(raw), -// }) -// } - -// //assumption at least seg1Len > 0 correct? -// ghost -// decreases -// pure func numInfoFields(seg1Len uint8, seg2Len uint8, seg3Len uint8) uint8 { -// return seg3Len > 0 ? 3 : (seg2Len > 0 ? 2 : 1) -// } - -// ghost -// decreases -// pure func infoFieldOffsetSeg(currINF int) int{ -// return 4 + 8 * currINF -// } - -// ghost -// decreases -// pure func computeSeqOffset(currHF uint8, seg1Len uint8, seg2Len uint8, seg3Len uint8) int{ -// return seg1Len > currHF ? int(currHF)*12 : (seg2Len > currHF ? int(currHF-seg1Len) * 12 : int(currHF-seg2Len-seg1Len)* 12) -// } - -// ghost -// decreases -// pure func computeSeqlen(currHF int, seg1Len int, seg2Len int, seg3Len int) int{ -// return seg1Len > currHF ? seg1Len : (seg2Len > currHF ? seg2Len: seg3Len) -// } - -// ghost -// requires int(seg1Len + seg2Len + seg3Len)*12 <= len(raw) -// requires 0 <= seg1Len && seg1Len*12 <= len(raw) -// requires 0 <= seg2Len && (seg1Len+seg2Len)*12 <= len(raw) -// requires 0 <= seg3Len && (seg1Len+seg2Len+seg3Len)*12 <= len(raw) -// //requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -// //ensures acc(sl.AbsSlice_Bytes(raw, 0, len(res))) -// decreases -// pure func getSegBytes(raw []byte, currHF int, seg1Len int, seg2Len int, seg3Len int) []byte { -// //unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in -// return seg1Len > currHF ? -// raw[0:seg1Len*12] : (seg2Len > currHF ? -// raw[seg1Len*12:(seg1Len + seg2Len)*12] : -// raw[(seg1Len + seg2Len)*12:(seg1Len + seg2Len + seg3Len)*12]) -// } -// //different approach: -// //expects bytes of Hopfields of whole packet -// /*ghost -// requires numHF*12 + 12 < len(raw) -// requires numHF >= 0 -// requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -// requires forall k int, i int :: 0<=k && k <= numHF && 0 <= i && i < 12 ==> unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in &raw[k*12:k*12+12][i] == &raw[k*12+i] -// decreases _ -// pure func toSeqIO_HF_rev(raw []byte, numHF int) seq[io.IO_HF]{ -// return numHF == 0 ? -// (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in seq[io.IO_HF]{getHopField(raw[0:12])}) : -// (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in seq[io.IO_HF]{getHopField(raw[numHF*12:numHF*12+12])}) ++ getSegPast(raw, numHF-1) -// }*/ - - -// //--------------------------------------- - - -// //TODO proof termination -// //expects the raw bytes of the Hopfields of a segment -// ghost -// requires offset*12 + 12 <= len(raw) -// requires offset >= -1 -// requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -// requires offset >= 0 ==> -// (forall k int, i int :: 0 <=k && k <= offset && 0 <= i && i < 12 ==> unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in &raw[k*12:k*12+12][i] == &raw[k*12+i]) -// decreases _ -// pure func getSegPast(raw []byte, offset int) seq[io.IO_HF]{ -// return offset == -1 ? seq[io.IO_HF]{} : -// (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in seq[io.IO_HF]{getHopField(raw[offset*12:offset*12+12])}) ++ getSegPast(raw, offset-1) -// } - - -// //TODO proof termination -// //expects the raw bytes of the Hopfields of a segment -// ghost -// requires offset*12 == len(raw) || offset*12 + 12 < len(raw) -// requires offset >= 0 -// requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -// requires offset*12 < len(raw) ==> -// (forall k int, i int :: 0 <= k && k <= offset && 0 <= i && i < 12 ==> unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in &raw[k*12:k*12+12][i] == &raw[k*12+i]) -// decreases _ -// pure func getSegFuture(raw []byte, offset int) seq[io.IO_HF]{ -// return offset*12 == len(raw) ? seq[io.IO_HF]{} : -// getSegFuture(raw, offset-1) ++ (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in seq[io.IO_HF]{getHopField(raw[offset*12:offset*12+12])}) -// } - -// ghost -// requires offset*12 + 12 <= len(raw) -// requires offset >= currHF && currHF >= 0 -// requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -// requires forall k int, i int :: 0 <= k && k <= offset && 0 <= i && i < 12 ==> unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in &raw[k*12:k*12+12][i] == &raw[k*12+i] -// decreases _ -// pure func getSegFuture2(raw []byte, currHF int, offset int) seq[io.IO_HF]{ -// return offset == currHF ? (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in seq[io.IO_HF]{getHopField(raw[offset*12:offset*12+12])}) : -// getSegFuture2(raw, currHF, offset-1) ++ (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in seq[io.IO_HF]{getHopField(raw[offset*12:offset*12+12])}) -// } - -// //TODO proof termination -// //expects the raw bytes of the Hopfields of a segment -// ghost -// requires offset*12 + 12 <= len(raw) -// requires offset >= -1 -// requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -// requires offset >= 0 ==> -// (forall k int, i int :: 0<=k && k <= offset && 0 <= i && i < 12 ==> unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in &raw[k*12:k*12+12][i] == &raw[k*12+i]) -// decreases _ -// pure func getSegHistory(raw []byte, offset int) seq[io.IO_ahi]{ -// return offset == -1 ? seq[io.IO_ahi]{} : -// (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in seq[io.IO_ahi]{getHopField(raw[offset*12:offset*12+12]).Toab()}) ++ getSegHistory(raw, offset-1) -// } - // TODO Do we need a body? ghost decreases From 3d90011f3609d30d9aa1565efdae3d8f1e7f65ee Mon Sep 17 00:00:00 2001 From: MLETHZ Date: Mon, 17 Jul 2023 16:14:32 +0200 Subject: [PATCH 11/33] clean up --- .github/workflows/gobra.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/gobra.yml b/.github/workflows/gobra.yml index 1ef4e1f97..d1df3a550 100644 --- a/.github/workflows/gobra.yml +++ b/.github/workflows/gobra.yml @@ -11,7 +11,6 @@ on: branches: - master pull_request: # run this workflow on every pull_request - workflow_dispatch: env: headerOnly: 1 From 6e8f8848a59d49f200d4c1906611674d74a58555 Mon Sep 17 00:00:00 2001 From: MLETHZ Date: Tue, 18 Jul 2023 16:11:18 +0200 Subject: [PATCH 12/33] improvements --- router/dataplane_spec.gobra | 244 +++++++++++++++++++++--------------- 1 file changed, 140 insertions(+), 104 deletions(-) diff --git a/router/dataplane_spec.gobra b/router/dataplane_spec.gobra index 5db1fb861..7baaddfab 100644 --- a/router/dataplane_spec.gobra +++ b/router/dataplane_spec.gobra @@ -21,14 +21,11 @@ import ( "hash" sl "github.com/scionproto/scion/verification/utils/slices" "github.com/scionproto/scion/verification/io" - "github.com/scionproto/scion/verification/dependencies/encoding/binary" "github.com/scionproto/scion/verification/utils/bitwise" "github.com/scionproto/scion/pkg/scrypto" "github.com/scionproto/scion/pkg/addr" ) -//"github.com/scionproto/scion/verification/definitions" - // TODO: maybe change interpretation of Mutex depending on whether the // dataplane is running or not. This is because, when Run is called and @@ -112,8 +109,8 @@ pred forwardingMetricsNonInjectiveMem(v forwardingMetrics) { } ghost -requires acc(forwardingMetricsNonInjectiveMem(v), _) -ensures acc(forwardingMetricsMem(v, id), _) +requires acc(forwardingMetricsNonInjectiveMem(v), _) +ensures acc(forwardingMetricsMem(v, id), _) decreases func liftForwardingMetricsNonInjectiveMem(v forwardingMetrics, id uint16) { unfold acc(forwardingMetricsNonInjectiveMem(v), _) @@ -141,8 +138,8 @@ pred (p *scionPacketProcessor) initMem() { requires acc(key, _) && acc(sl.AbsSlice_Bytes(*key, 0, len(*key)), _) requires scrypto.ValidKeyForHash(*key) -ensures acc(key, _) && acc(sl.AbsSlice_Bytes(*key, 0, len(*key)), _) -ensures res.Mem() +ensures acc(key, _) && acc(sl.AbsSlice_Bytes(*key, 0, len(*key)), _) +ensures res.Mem() decreases func MacFactorySpec(ghost key *[]byte) (res hash.Hash) @@ -170,7 +167,7 @@ func (err scmpError) IsDuplicableMem() bool { ghost trusted preserves err.ErrorMem() -ensures err.IsDuplicableMem() ==> err.ErrorMem() +ensures err.IsDuplicableMem() ==> err.ErrorMem() decreases func (err scmpError) Duplicate() { if err.IsDuplicableMem() { @@ -191,16 +188,16 @@ type offsetPair struct { ghost pure requires 0 <= n -ensures len(res) == n -ensures forall i int :: {res[i]} 0 <= i && i < len(res) ==> res[i] == offsetPair{} +ensures len(res) == n +ensures forall i int :: {res[i]} 0 <= i && i < len(res) ==> res[i] == offsetPair{} decreases func newOffsetPair(n int) (res seq[offsetPair]) /**** Acessor methods to avoid unfolding the Mem predicate of the dataplane so much ****/ ghost requires acc(MutexInvariant!(), _) -ensures acc(&d.internalNextHops, _) -ensures d.internalNextHops != nil ==> acc(AccAddr(d.internalNextHops), _) +ensures acc(&d.internalNextHops, _) +ensures d.internalNextHops != nil ==> acc(AccAddr(d.internalNextHops), _) decreases func (d *DataPlane) getInternalNextHops() { unfold acc(MutexInvariant!(), _) @@ -208,7 +205,7 @@ func (d *DataPlane) getInternalNextHops() { ghost requires acc(MutexInvariant!(), _) -ensures acc(&d.external, _) && (d.external != nil ==> acc(AccBatchConn(d.external), _)) +ensures acc(&d.external, _) && (d.external != nil ==> acc(AccBatchConn(d.external), _)) decreases func (d *DataPlane) getExternalMem() { unfold acc(MutexInvariant!(), _) @@ -216,7 +213,7 @@ func (d *DataPlane) getExternalMem() { ghost requires acc(MutexInvariant!(), _) -ensures acc(&d.linkTypes, _) && (d.linkTypes != nil ==> acc(d.linkTypes, _)) +ensures acc(&d.linkTypes, _) && (d.linkTypes != nil ==> acc(d.linkTypes, _)) decreases func (d *DataPlane) getLinkTypesMem() { unfold acc(MutexInvariant!(), _) @@ -224,7 +221,7 @@ func (d *DataPlane) getLinkTypesMem() { ghost requires acc(MutexInvariant!(), _) -ensures acc(&d.localIA, _) +ensures acc(&d.localIA, _) decreases func (d *DataPlane) getLocalIA() { unfold acc(MutexInvariant!(), _) @@ -232,7 +229,7 @@ func (d *DataPlane) getLocalIA() { ghost requires acc(MutexInvariant!(), _) -ensures acc(&d.neighborIAs, _) && (d.neighborIAs != nil ==> acc(d.neighborIAs, _)) +ensures acc(&d.neighborIAs, _) && (d.neighborIAs != nil ==> acc(d.neighborIAs, _)) decreases func (d *DataPlane) getNeighborIAs() { unfold acc(MutexInvariant!(), _) @@ -240,7 +237,7 @@ func (d *DataPlane) getNeighborIAs() { ghost requires acc(MutexInvariant!(), _) -ensures acc(&d.svc, _) && (d.svc != nil ==> acc(d.svc.Mem(), _)) +ensures acc(&d.svc, _) && (d.svc != nil ==> acc(d.svc.Mem(), _)) decreases func (d *DataPlane) getSvcMem() { unfold acc(MutexInvariant!(), _) @@ -248,7 +245,7 @@ func (d *DataPlane) getSvcMem() { ghost requires acc(MutexInvariant!(), _) -ensures acc(&d.bfdSessions, _) && (d.bfdSessions != nil ==> acc(AccBfdSession(d.bfdSessions), _)) +ensures acc(&d.bfdSessions, _) && (d.bfdSessions != nil ==> acc(AccBfdSession(d.bfdSessions), _)) decreases func (d *DataPlane) getBfdSessionsMem() { unfold acc(MutexInvariant!(), _) @@ -256,14 +253,14 @@ func (d *DataPlane) getBfdSessionsMem() { ghost requires acc(MutexInvariant!(), _) -ensures acc(&d.internal, _) && (d.internal != nil ==> acc(d.internal.Mem(), _)) +ensures acc(&d.internal, _) && (d.internal != nil ==> acc(d.internal.Mem(), _)) decreases func (d *DataPlane) getInternal() { unfold acc(MutexInvariant!(), _) } requires acc(MutexInvariant!(), _) -ensures acc(&d.macFactory, _) +ensures acc(&d.macFactory, _) decreases func (d *DataPlane) getMacFactoryMem() { unfold acc(MutexInvariant!(), _) @@ -272,13 +269,13 @@ func (d *DataPlane) getMacFactoryMem() { ghost requires acc(MutexInvariant!(), _) requires acc(&d.macFactory, _) && d.macFactory != nil -ensures acc(&d.macFactory, _) && acc(&d.key, _) && acc(d.key, _) -ensures acc(sl.AbsSlice_Bytes(*d.key, 0, len(*d.key)), _) -ensures scrypto.ValidKeyForHash(*d.key) -ensures d.macFactory implements MacFactorySpec{d.key} +ensures acc(&d.macFactory, _) && acc(&d.key, _) && acc(d.key, _) +ensures acc(sl.AbsSlice_Bytes(*d.key, 0, len(*d.key)), _) +ensures scrypto.ValidKeyForHash(*d.key) +ensures d.macFactory implements MacFactorySpec{d.key} decreases func (d *DataPlane) getNewPacketProcessorFootprint() { - unfold acc(MutexInvariant!(), _) + unfold acc(MutexInvariant!(), _) } /**** End of acessor methods to avoid unfolding the Mem predicate of the dataplane so much ****/ @@ -350,11 +347,8 @@ requires true func closureSpec3(c BatchConn) /** End of closure specs for the Run method **/ - - /** Start of io-spec helper functions **/ - ghost requires seg1Len > 0 requires seg2Len >= 0 @@ -362,7 +356,7 @@ requires seg3Len >= 0 requires currHF < seg1Len + seg2Len + seg3Len decreases pure func computeSeqlen(currHF int, seg1Len int, seg2Len int, seg3Len int) int{ - return seg1Len > currHF ? seg1Len : ((seg1Len + seg2Len) > currHF ? seg2Len: seg3Len) + return seg1Len > currHF ? seg1Len : ((seg1Len + seg2Len) > currHF ? seg2Len : seg3Len) } ghost @@ -384,7 +378,7 @@ requires seg3Len >= 0 requires currHF >= 0 ensures res <= currHF decreases -pure func computeprevSegLen(currHF int, seg1Len int, seg2Len int, seg3Len int) (res int){ +pure func computePrevSegLen(currHF int, seg1Len int, seg2Len int, seg3Len int) (res int){ return seg1Len > currHF ? 0 : ((seg1Len + seg2Len) > currHF ? seg1Len : seg1Len + seg2Len) } @@ -395,19 +389,18 @@ requires 0 <= start requires acc(&raw[start+2], _) && acc(&raw[start+3], _) && acc(&raw[start+4], _) && acc(&raw[start+5], _) decreases pure func getHopField(raw []byte, start int) io.IO_HF { - return let inif2 := binary.BigEndian.Uint16(raw[start+2:start+4]) == 0 ? none[io.IO_ifs] : some(io.IO_ifs(binary.BigEndian.Uint16(raw[start+2:start+4]))) in - let egif2 := binary.BigEndian.Uint16(raw[start+4:start+6])== 0 ? none[io.IO_ifs] : some(io.IO_ifs(binary.BigEndian.Uint16(raw[start+4:start+6]))) in - io.IO_HF(io.IO_HF_{ - InIF2 : inif2, - EgIF2 : egif2, - HVF : computeMsgTerm(raw, start), - }) + return let inif2 := binary.BigEndian.Uint16(raw[start+2:start+4]) in + let egif2 := binary.BigEndian.Uint16(raw[start+4:start+6]) in + io.IO_HF(io.IO_HF_{ + InIF2 : inif2 == 0 ? none[io.IO_ifs] : some(io.IO_ifs(inif2)), + EgIF2 : egif2 == 0 ? none[io.IO_ifs] : some(io.IO_ifs(egif2)), + HVF : computeMsgTerm(raw, start), + }) } - //expects the raw bytes of whole path ghost -requires 4 + 8 * numINF + offset*12 + 12 <= len(raw) +requires 4 + 8 * numINF + offset * 12 + 12 <= len(raw) requires prevSegLen >= 0 && offset - prevSegLen >= -1 requires 0 < numINF && numINF < 4 requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) @@ -443,11 +436,9 @@ pure func getSegHistory(raw []byte, prevSegLen int, offset int, numINF int) seq[ seq[io.IO_ahi]{getHopField(raw,4 + 8 * numINF + offset*12).Toab()}) ++ getSegHistory(raw, prevSegLen, offset-1, numINF) } - - -ghost //expects the raw bytes of whole path -requires 4 + 8 * numINF + 12*prevSegLen + 12*segLen <= len(raw) +ghost +requires 4 + 8 * numINF + 12 * (prevSegLen + segLen) <= len(raw) requires prevSegLen >= 0 && segLen >= 0 requires 0 < numINF && numINF < 4 requires segLen+prevSegLen > currHF && currHF >= prevSegLen @@ -455,19 +446,19 @@ requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases pure func getSegment(raw []byte, consDir bool, peer bool, currHF int, prevSegLen int, segLen int, numINF int, currINF int) io.IO_seg2{ return io.IO_seg2(io.IO_seg3_{ - AInfo : computeAInfo(raw, currINF), - UInfo : computeUInfo(raw, currINF), - ConsDir : consDir, - Peer : peer, - Past : getSegPast(raw, prevSegLen, currHF - 1, numINF), - Future : getSegFuture(raw, currHF, segLen+prevSegLen-1, numINF), - History : getSegHistory(raw, prevSegLen, currHF - 1, numINF), - }) + AInfo : computeAInfo(raw, currINF), + UInfo : computeUInfo(raw, currINF), + ConsDir : consDir, + Peer : peer, + Past : getSegPast(raw, prevSegLen, currHF - 1, numINF), + Future : getSegFuture(raw, currHF, segLen+prevSegLen-1, numINF), + History : getSegHistory(raw, prevSegLen, currHF - 1, numINF), + }) } -ghost //expects the raw bytes of whole path -requires 4 + 8 * numINF + 12*prevSegLen + 12*segLen <= len(raw) +ghost +requires 4 + 8 * numINF + 12 * (prevSegLen + segLen) <= len(raw) requires prevSegLen >= 0 && segLen >= 0 requires 0 < numINF && numINF < 4 requires segLen+prevSegLen > currHF && currHF >= prevSegLen @@ -475,49 +466,47 @@ requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases pure func getPastSegment(raw []byte, consDir bool, peer bool, currHF int, prevSegLen int, segLen int, numINF int, currINF int) io.IO_seg2{ return io.IO_seg2(io.IO_seg3_{ - AInfo : computeAInfo(raw, currINF), - UInfo : computeUInfo(raw, currINF), - ConsDir : consDir, - Peer : peer, - Past : getSegPast(raw, prevSegLen, currHF, numINF), - Future : seq[io.IO_HF]{}, - History : getSegHistory(raw, prevSegLen, currHF, numINF), - }) + AInfo : computeAInfo(raw, currINF), + UInfo : computeUInfo(raw, currINF), + ConsDir : consDir, + Peer : peer, + Past : getSegPast(raw, prevSegLen, currHF, numINF), + Future : seq[io.IO_HF]{}, + History : getSegHistory(raw, prevSegLen, currHF, numINF), + }) } - ghost requires seg1Len > 0 requires seg2Len >= 0 requires seg3Len >= 0 -requires 4 + 8*numInfoFields(seg1Len, seg2Len, seg3Len) + 12 * seg1Len + 12 * seg2Len + 12 * seg3Len == len(raw) +requires 4 + 8 * numInfoFields(seg1Len, seg2Len, seg3Len) + 12 * (seg1Len + seg2Len + seg3Len) == len(raw) requires 0 <= currINF && currINF < 3 requires 0 <= currHF && currHF < seg1Len + seg2Len + seg3Len -requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) + computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF +requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) + computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases pure func getCurrSeg(raw []byte, currINF int, currHF int, seg1Len int, seg2Len int, seg3Len int) io.IO_seg3 { - return let consDir := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in raw[infoFieldOffsetSeg(currINF)] & 0x1 == 0x1) in - let peer := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in raw[infoFieldOffsetSeg(currINF)] & 0x2 == 0x2) in + return let consDir := getConsDir(raw, currINF) in + let peer := getPeer(raw, currINF) in let segLen := computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) in - let prevSegLen := computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) in + let prevSegLen := computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len) in let numINF := numInfoFields(seg1Len, seg2Len, seg3Len) in getSegment(raw, consDir, peer, currHF, prevSegLen, segLen, numINF, currINF) } - ghost requires seg1Len > 0 requires seg2Len >= 0 requires seg3Len >= 0 -requires 4 + 8*numInfoFields(seg1Len, seg2Len, seg3Len) + 12 * seg1Len + 12 * seg2Len + 12 * seg3Len == len(raw) +requires 4 + 8 * numInfoFields(seg1Len, seg2Len, seg3Len) + 12 * (seg1Len + seg2Len + seg3Len) == len(raw) requires 0 <= currINF && currINF < 3 requires 0 <= currHF && currHF < seg1Len + seg2Len + seg3Len -requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) + computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF +requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) + computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases pure func getLeftSeg(raw []byte, currINF int, currHF int, seg1Len int, seg2Len int, seg3Len int) option[io.IO_seg3] { - return let newCurrHF := computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) + computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) in + return let newCurrHF := computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) + computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len) in (newCurrHF == seg1Len + seg2Len + seg3Len || currINF == 2) ? none[io.IO_seg3] : some(getCurrSeg(raw, currINF + 1, newCurrHF, seg1Len, seg2Len, seg3Len)) } @@ -526,40 +515,39 @@ ghost requires seg1Len > 0 requires seg2Len >= 0 requires seg3Len >= 0 -requires 4 + 8*numInfoFields(seg1Len, seg2Len, seg3Len) + 12 * seg1Len + 12 * seg2Len + 12 * seg3Len == len(raw) +requires 4 + 8 * numInfoFields(seg1Len, seg2Len, seg3Len) + 12 * (seg1Len + seg2Len + seg3Len) == len(raw) requires 0 <= currINF && currINF < 3 requires 0 <= currHF && currHF < seg1Len + seg2Len + seg3Len -requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) + computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF +requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) + computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases pure func getRightSeg(raw []byte, currINF int, currHF int, seg1Len int, seg2Len int, seg3Len int) option[io.IO_seg3] { - return (computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) == 0 || currINF == 0) ? none[io.IO_seg3] : - (let newCurrHF := computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len)-1 in - let consDir := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in raw[infoFieldOffsetSeg(currINF-1)] & 0x1 == 0x1) in - let peer := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in raw[infoFieldOffsetSeg(currINF-1)] & 0x2 == 0x2) in + return (computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len) == 0 || currINF == 0) ? none[io.IO_seg3] : + (let newCurrHF := computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len)-1 in + let consDir := getConsDir(raw, currINF-1) in + let peer := getPeer(raw, currINF-1) in let segLen := computeSeqlen(newCurrHF, seg1Len, seg2Len, seg3Len) in - let prevSegLen := computeprevSegLen(newCurrHF, seg1Len, seg2Len, seg3Len) in + let prevSegLen := computePrevSegLen(newCurrHF, seg1Len, seg2Len, seg3Len) in let numINF := numInfoFields(seg1Len, seg2Len, seg3Len) in some(getPastSegment(raw, consDir, peer, newCurrHF, prevSegLen, segLen, numINF, currINF))) } - ghost requires seg1Len > 0 requires seg2Len >= 0 requires seg3Len >= 0 -requires 4 + 8*numInfoFields(seg1Len, seg2Len, seg3Len) + 12 * seg1Len + 12 * seg2Len + 12 * seg3Len == len(raw) +requires 4 + 8 * numInfoFields(seg1Len, seg2Len, seg3Len) + 12 * (seg1Len + seg2Len + seg3Len) == len(raw) requires 0 <= currINF && currINF < 3 requires 0 <= currHF && currHF < seg1Len + seg2Len + seg3Len -requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) + computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF +requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) + computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases pure func getMidSeg(raw []byte, currINF int, currHF int, seg1Len int, seg2Len int, seg3Len int) option[io.IO_seg3] { return seg3Len == 0 ? none[io.IO_seg3] : - (computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) == seg1Len) ? none[io.IO_seg3] : - (computeprevSegLen(currHF, seg1Len, seg2Len, seg3Len) == 0) ? some(getCurrSeg(raw, 2, seg1Len + seg2Len, seg1Len, seg2Len, seg3Len)) : - (let consDir := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in raw[infoFieldOffsetSeg(0)] & 0x1 == 0x1) in - let peer := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in raw[infoFieldOffsetSeg(0)] & 0x2 == 0x2) in + (computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len) == seg1Len) ? none[io.IO_seg3] : + (computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len) == 0) ? some(getCurrSeg(raw, 2, seg1Len + seg2Len, seg1Len, seg2Len, seg3Len)) : + (let consDir := getConsDir(raw, 0) in + let peer := getPeer(raw, 0) in let numINF := numInfoFields(seg1Len, seg2Len, seg3Len) in some(getPastSegment(raw, consDir, peer, seg1Len-1, 0, seg1Len, numINF, currINF))) } @@ -570,28 +558,76 @@ requires len(raw) > 4 requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) requires unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in let hdr := binary.BigEndian.Uint32(raw[0:4]) in - //hdr == (uint32(raw[3]) | uint32(raw[2])<<8 | uint32(raw[1])<<16 | uint32(raw[0])<<24) && - //DeserializingHdr(raw[0], raw[1], raw[2], raw[3], hdr) && - 0 <= uint8(hdr >> 30) && uint8(hdr >> 30) < 3 && //currINF - 0 <= (uint8(hdr >> 24) & 0x3F) && (uint8(hdr >> 24) & 0x3F) < (uint8(hdr >> 12) & 0x3F) + (uint8(hdr >> 6) & 0x3F) + (uint8(hdr) & 0x3F) && //currHF - 0 < uint8(hdr >> 12) & 0x3F && //seg1Len - 0 <= uint8(hdr >> 6) & 0x3F && //seg2Len - 0 <= uint8(hdr) & 0x3F && //seg3Len - 4 + 8*numInfoFields(int(uint8(hdr >> 12) & 0x3F), int(uint8(hdr >> 6) & 0x3F), int(uint8(hdr) & 0x3F)) + 12 * int(uint8(hdr >> 12) & 0x3F) + 12 * int(uint8(hdr >> 6) & 0x3F) + 12 * int(uint8(hdr) & 0x3F) == len(raw) + 0 <= getCurrINF(hdr) && getCurrINF(hdr) < 3 && + 0 <= getCurrHF(hdr) && getCurrHF(hdr) < getSeg1Len(hdr) + getSeg2Len(hdr) + getSeg3Len(hdr) && + 0 < getSeg1Len(hdr) && + 0 <= getSeg2Len(hdr) && + 0 <= getSeg3Len(hdr) && + 4 + 8 * numInfoFields(int(getSeg1Len(hdr)), int(getSeg2Len(hdr)), int(getSeg3Len(hdr))) + 12 * (int(getSeg1Len(hdr)) + int(getSeg2Len(hdr)) + int(getSeg3Len(hdr))) == len(raw) decreases pure func getPkt(raw []byte) io.IO_pkt2{ return let hdr := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in binary.BigEndian.Uint32(raw[0:4]) in - let currINF := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in uint8(hdr >> 30) in - let currHF := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in uint8(hdr >> 24) & 0x3F in - let seg1Len := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in uint8(hdr >> 12) & 0x3F in - let seg2Len := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in uint8(hdr >> 6) & 0x3F in - let seg3Len := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in uint8(hdr) & 0x3F in - io.IO_pkt2(io.IO_Packet2{ - CurrSeg : getCurrSeg(raw, int(currINF), int(currHF), int(seg1Len), int(seg2Len), int(seg3Len)), - LeftSeg : getLeftSeg(raw, int(currINF), int(currHF), int(seg1Len), int(seg2Len), int(seg3Len)), - MidSeg : getMidSeg(raw, int(currINF), int(currHF), int(seg1Len), int(seg2Len), int(seg3Len)), - RightSeg : getRightSeg(raw, int(currINF), int(currHF), int(seg1Len), int(seg2Len), int(seg3Len)), - }) + let currINF := getCurrINF(hdr) in + let currHF := getCurrHF(hdr) in + let seg1Len := getSeg1Len(hdr) in + let seg2Len := getSeg2Len(hdr) in + let seg3Len := getSeg3Len(hdr) in + io.IO_pkt2(io.IO_Packet2{ + CurrSeg : getCurrSeg(raw, int(currINF), int(currHF), int(seg1Len), int(seg2Len), int(seg3Len)), + LeftSeg : getLeftSeg(raw, int(currINF), int(currHF), int(seg1Len), int(seg2Len), int(seg3Len)), + MidSeg : getMidSeg(raw, int(currINF), int(currHF), int(seg1Len), int(seg2Len), int(seg3Len)), + RightSeg : getRightSeg(raw, int(currINF), int(currHF), int(seg1Len), int(seg2Len), int(seg3Len)), + }) +} + +ghost +decreases +pure func getCurrINF(hdr uint32) uint8{ + return uint8(hdr >> 30) +} + +ghost +decreases +pure func getCurrHF(hdr uint32) uint8{ + return uint8(hdr >> 24) & 0x3F +} + +ghost +decreases +pure func getSeg1Len(hdr uint32) uint8{ + return uint8(hdr >> 12) & 0x3F +} + +ghost +decreases +pure func getSeg2Len(hdr uint32) uint8{ + return uint8(hdr >> 6) & 0x3F +} + +ghost +decreases +pure func getSeg3Len(hdr uint32) uint8{ + return uint8(hdr) & 0x3F +} + +ghost +requires 0 <= offset +requires infoFieldOffsetSeg(offset) < len(raw) +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +decreases +pure func getConsDir(raw []byte, offset int) bool{ + return unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in + raw[infoFieldOffsetSeg(offset)] & 0x1 == 0x1 +} + +ghost +requires 0 <= offset +requires infoFieldOffsetSeg(offset) < len(raw) +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +decreases +pure func getPeer(raw []byte, offset int) bool{ + return unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in + raw[infoFieldOffsetSeg(offset)] & 0x2 == 0x2 } // TODO Do we need a body? From afe9e52c0eba432aee0f0f92225416d1c95b1f42 Mon Sep 17 00:00:00 2001 From: MLETHZ Date: Wed, 19 Jul 2023 11:37:17 +0200 Subject: [PATCH 13/33] instantiate abstract functions with bodies --- verification/io/other_defs.gobra | 39 ++++++++++++++++++++------------ verification/io/router.gobra | 38 +++++++++++++++++++++++++++++-- 2 files changed, 61 insertions(+), 16 deletions(-) diff --git a/verification/io/other_defs.gobra b/verification/io/other_defs.gobra index 70c390daf..b2de80e8a 100644 --- a/verification/io/other_defs.gobra +++ b/verification/io/other_defs.gobra @@ -60,7 +60,7 @@ type IO_msgterm adt { } MsgTerm_FS { - MsgTerm_FS_ seq[IO_msgterm] + MsgTerm_FS_ set[IO_msgterm] } MsgTerm_MPair { @@ -107,8 +107,6 @@ pure func (hf IO_HF) extr_asid() IO_as { return hf.HVF.extract_asid() } - - // function 'toab' in Isabelle, originally of type HF_scheme -> aahi_scheme ghost pure @@ -159,31 +157,45 @@ pure func link_type(p1 IO_as, p2 IO_ifs) IO_Link ghost decreases -pure func egif_prov2(hf1 IO_HF, asid IO_as) bool +pure func egif_prov2(hf1 IO_HF, asid IO_as) bool{ + return egif2_type(hf1, asid, IO_Link(IO_CustProv{})) +} ghost decreases -pure func egif_core2(hf1 IO_HF, asid IO_as) bool +pure func egif_core2(hf1 IO_HF, asid IO_as) bool{ + return egif2_type(hf1, asid, IO_Link(IO_PeerOrCore{})) +} ghost decreases -pure func egif_cust2(hf1 IO_HF, asid IO_as) bool +pure func egif_cust2(hf1 IO_HF, asid IO_as) bool{ + return egif2_type(hf1, asid, IO_Link(IO_ProvCust{})) +} ghost decreases -pure func inif_cust2(hf1 IO_HF, asid IO_as) bool +pure func inif_cust2(hf1 IO_HF, asid IO_as) bool{ + return inif2_type(hf1, asid, IO_Link(IO_ProvCust{})) +} ghost decreases -pure func inif_core2(hf1 IO_HF, asid IO_as) bool +pure func inif_core2(hf1 IO_HF, asid IO_as) bool{ + return inif2_type(hf1, asid, IO_Link(IO_PeerOrCore{})) +} ghost decreases -pure func inif_prov2(hf1 IO_HF, asid IO_as) bool +pure func inif_prov2(hf1 IO_HF, asid IO_as) bool{ + return inif2_type(hf1, asid, IO_Link(IO_CustProv{})) +} ghost decreases -pure func if_type(asid IO_as, ifs option[IO_ifs], link IO_Link) bool +pure func if_type(asid IO_as, ifs option[IO_ifs], link IO_Link) bool{ + return exists outif IO_ifs :: some(outif) == ifs && link_type(asid, outif) == link +} type ext2_rec struct { op1 IO_as @@ -213,10 +225,9 @@ ghost decreases pure func dp2_in_ext(s IO_dp2_state, asid IO_as, ifs IO_ifs, pkt IO_pkt2) bool -// TODO: how is this defined? -// extract_asid ghost decreases -pure func (m IO_msgterm) extract_asid() IO_as - +pure func (m IO_msgterm) extract_asid() IO_as { + return m.MsgTerm_Hash_.MsgTerm_MPair_1.MsgTerm_Key_.Key_macK_ +} /* End of To clarify */ diff --git a/verification/io/router.gobra b/verification/io/router.gobra index 0bad5df67..09b0c85f3 100644 --- a/verification/io/router.gobra +++ b/verification/io/router.gobra @@ -27,11 +27,45 @@ pure func core_as_set() set[IO_as] ghost decreases -pure func hf_valid(p1 bool, p2 uint, p3 set[IO_msgterm], p4 IO_HF) bool +pure func hf_valid(p1 bool, p2 uint, p3 set[IO_msgterm], p4 IO_HF) bool { + return let inif := p4.InIF2 in + let egif := p4.EgIF2 in + let x := p4.HVF in + let ts := IO_msgterm(MsgTerm_Num{int(p2)}) in + let uinfo := IO_msgterm(MsgTerm_FS{p3}) in + let l := IO_msgterm(MsgTerm_L{seq[IO_msgterm]{ts, if2term(inif), if2term(egif), uinfo}}) in + exists a IO_key :: x == mac(macKey(a), l) +} + +ghost +decreases +pure func macKey(key IO_key) IO_msgterm { + return IO_msgterm(MsgTerm_Key{key}) +} + +ghost +decreases +pure func mac(fst IO_msgterm, snd IO_msgterm) IO_msgterm { + return IO_msgterm( MsgTerm_Hash { + MsgTerm_Hash_ : IO_msgterm( MsgTerm_MPair{ + MsgTerm_MPair_1 : fst, + MsgTerm_MPair_2 : snd, + }), + }) +} + +ghost +decreases +pure func if2term(ifs option[IO_ifs]) IO_msgterm { + return ifs == none[IO_ifs] ? MsgTerm_Empty{} : IO_msgterm(MsgTerm_AS{IO_as(get(ifs))}) +} ghost decreases -pure func upd_uinfo(p1 set[IO_msgterm], p2 IO_HF) set[IO_msgterm] +pure func upd_uinfo(p1 set[IO_msgterm], p2 IO_HF) set[IO_msgterm] { + return let setHVF := set[IO_msgterm]{p2.HVF} in + (p1 union setHVF) setminus (p1 intersection setHVF) +} ghost decreases From de241b53ca7ce39682f6dcba9dfaaaa751bb696a Mon Sep 17 00:00:00 2001 From: MLETHZ Date: Wed, 19 Jul 2023 17:41:55 +0200 Subject: [PATCH 14/33] progress io spec --- router/dataplane_spec.gobra | 265 ++++++++++++++++++++++++++++++- verification/io/other_defs.gobra | 3 +- 2 files changed, 265 insertions(+), 3 deletions(-) diff --git a/router/dataplane_spec.gobra b/router/dataplane_spec.gobra index 7baaddfab..989277544 100644 --- a/router/dataplane_spec.gobra +++ b/router/dataplane_spec.gobra @@ -630,10 +630,261 @@ pure func getPeer(raw []byte, offset int) bool{ raw[infoFieldOffsetSeg(offset)] & 0x2 == 0x2 } -// TODO Do we need a body? ghost decreases -pure func computeMsgTerm(raw []byte, start int) io.IO_msgterm +pure func upd_uinfo_bytes(raw []byte, currINFIdx int, currHFIdx int) set[io.IO_msgterm] { + return let uinfo := computeUInfo(raw, currINFIdx) in + let setHVF := set[io.IO_msgterm]{computeMsgTerm(raw, currHFIdx)} in + (uinfo union setHVF) setminus (uinfo intersection setHVF) +} + +ghost +decreases +pure func update_uinfo2_bytes(raw []byte, currINFIdx int, currHFIdx int) bool { + return computeUInfo(raw, currINFIdx) === upd_uinfo_bytes(raw, currINFIdx, currHFIdx) +} + +//TODO: is === even possible in this case? +ghost +decreases +pure func same_uinfo2_bytes(currRaw []byte, currINFIdx int, travRaw []byte, travINFIdx int) bool { + return computeUInfo(currRaw, currINFIdx) === computeUInfo(travRaw, travINFIdx) +} + +ghost +requires 0 <= currINFIdx +requires infoFieldOffsetSeg(currINFIdx) < len(currRaw) +requires acc(sl.AbsSlice_Bytes(currRaw, 0, len(currRaw)), _) +decreases +pure func update_uinfo_bytes(currRaw []byte, currINFIdx int, currHFIdx int, travRaw []byte, travINFIdx int) bool { + return getConsDir(currRaw, currINFIdx) ? update_uinfo2_bytes(currRaw, currINFIdx, currHFIdx) : + same_uinfo2_bytes(currRaw, currINFIdx, travRaw, travINFIdx) +} + + + +/* +ghost +requires 0 <= currINFIdx +requires 0 <= currHFIdx +requires infoFieldOffsetSeg(currINFIdx) + 12 * currHFIdx < len(raw) +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +//requires len(currseg.Future) > 0 +decreases +pure func dp3s_iospec_bio3s_create_guard_traversedseg_bytes(raw []byte, currINFIdx int, currHFIdx int) IO_seg3 { + return let uinfo := getConsDir(raw, currINFIdx) ? + upd_uinfo(raw []byte, currINFIdx, currHFIdx) : + computeUInfo(raw, currINFIdx) in + IO_seg3_ { + AInfo: computeAInfo(raw, currINFIdx), + UInfo: uinfo, + ConsDir: getConsDir(raw, currINFIdx), + Peer: getPeer(raw, currINFIdx), + Past: getPastSegment(), + Future: currseg.Future, + History: currseg.History} +} +*/ + +ghost +decreases +pure func same_segment2_bytes(currRaw []byte, travRaw []byte) bool { + return currRaw === travRaw +} + +ghost +decreases +pure func same_other2_bytes(currRaw []byte, currINFIdx int, travRaw []byte, travINFIdx int) bool { + return computeAInfo(currRaw, currINFIdx) == computeAInfo(travRaw, travINFIdx) && + getConsDir(currRaw, currINFIdx) == getConsDir(travRaw, travINFIdx) && + getPeer(currRaw, currINFIdx) == getPeer(travRaw, travINFIdx) +} + +ghost +requires acc(links) +requires forall key uint16 :: key in domain(links) ==> 0 <= links[key] && links[key] <= 4 +requires ifs in domain(links) +ensures 0 <= res && res <= 4 +decreases +pure func link_type_bytes(ifs uint16, links map[uint16]int) (res int) { + return links[ifs] +} + +ghost +requires 0 <= link && link <= 4 +requires acc(links) +requires forall key uint16 :: key in domain(links) ==> 0 <= links[key] && links[key] <= 4 +decreases +pure func if_type_bytes(ifs uint16, link int, links map[uint16]int) bool{ + return ifs in domain(links) ? link_type_bytes(ifs, links) == link : false +} + + +ghost +requires acc(links) +requires forall key uint16 :: key in domain(links) ==> 0 <= links[key] && links[key] <= 4 +requires 0 <= link && link <= 4 +requires 0 < numInfoFields && numInfoFields <= 3 +requires 0 <= currHFIdx +requires 4 + 8 * numInfoFields + 12 * currHFIdx + 12 <= len(raw) +requires acc(&raw[4 + 8 * numInfoFields + 12 * currHFIdx+4], _) +requires acc(&raw[4 + 8 * numInfoFields + 12 * currHFIdx+5], _) +decreases +pure func egif2_type_bytes(raw []byte, currHFIdx int, numInfoFields int, link int, links map[uint16]int) bool { + return let idx := 4 + 8 * numInfoFields + 12 * currHFIdx in + let egIF2 := binary.BigEndian.Uint16(raw[idx+4:idx+6]) in + if_type_bytes(egIF2, link, links) +} + +ghost +requires acc(links) +requires forall key uint16 :: key in domain(links) ==> 0 <= links[key] && links[key] <= 4 +requires 0 <= link && link <= 4 +requires 0 < numInfoFields && numInfoFields <= 3 +requires 0 <= currHFIdx +requires 4 + 8 * numInfoFields + 12 * currHFIdx + 12 <= len(raw) +requires acc(&raw[4 + 8 * numInfoFields + 12 * currHFIdx+2], _) +requires acc(&raw[4 + 8 * numInfoFields + 12 * currHFIdx+3], _) +decreases +pure func inif2_type_bytes(raw []byte, currHFIdx int, numInfoFields int, link int, links map[uint16]int) bool { + return let idx := 4 + 8 * numInfoFields + 12 * currHFIdx in + let inIF2 := binary.BigEndian.Uint16(raw[idx+2:idx+4]) in + if_type_bytes(inIF2, link, links) +} + +ghost +requires acc(links) +requires forall key uint16 :: key in domain(links) ==> 0 <= links[key] && links[key] <= 4 +requires 0 < numInfoFields && numInfoFields <= 3 +requires 0 <= currHFIdx +requires 4 + 8 * numInfoFields + 12 * currHFIdx + 12 <= len(raw) +requires acc(&raw[4 + 8 * numInfoFields + 12 * currHFIdx+4], _) +requires acc(&raw[4 + 8 * numInfoFields + 12 * currHFIdx+5], _) +decreases +pure func egif_prov2_bytes(raw []byte, currHFIdx int, numInfoFields int, links map[uint16]int) bool{ + return egif2_type_bytes(raw, currHFIdx, numInfoFields, 2, links) +} + +ghost +requires acc(links) +requires forall key uint16 :: key in domain(links) ==> 0 <= links[key] && links[key] <= 4 +requires 0 < numInfoFields && numInfoFields <= 3 +requires 0 <= currHFIdx +requires 4 + 8 * numInfoFields + 12 * currHFIdx + 12 <= len(raw) +requires acc(&raw[4 + 8 * numInfoFields + 12 * currHFIdx+4], _) +requires acc(&raw[4 + 8 * numInfoFields + 12 * currHFIdx+5], _) +decreases +pure func egif_core2_bytes(raw []byte, currHFIdx int, numInfoFields int, links map[uint16]int) bool{ + return egif2_type_bytes(raw, currHFIdx, numInfoFields, 1, links) || + egif2_type_bytes(raw, currHFIdx, numInfoFields, 4, links) +} + + +ghost +requires acc(links) +requires forall key uint16 :: key in domain(links) ==> 0 <= links[key] && links[key] <= 4 +requires 0 < numInfoFields && numInfoFields <= 3 +requires 0 <= currHFIdx +requires 4 + 8 * numInfoFields + 12 * currHFIdx + 12 <= len(raw) +requires acc(&raw[4 + 8 * numInfoFields + 12 * currHFIdx+4], _) +requires acc(&raw[4 + 8 * numInfoFields + 12 * currHFIdx+5], _) +decreases +pure func egif_cust2_bytes(raw []byte, currHFIdx int, numInfoFields int, links map[uint16]int) bool{ + return egif2_type_bytes(raw, currHFIdx, numInfoFields, 3, links) +} + +ghost +requires acc(links) +requires forall key uint16 :: key in domain(links) ==> 0 <= links[key] && links[key] <= 4 +requires 0 < numInfoFields && numInfoFields <= 3 +requires 0 <= currHFIdx +requires 4 + 8 * numInfoFields + 12 * currHFIdx + 12 <= len(raw) +requires acc(&raw[4 + 8 * numInfoFields + 12 * currHFIdx+2], _) +requires acc(&raw[4 + 8 * numInfoFields + 12 * currHFIdx+3], _) +decreases +pure func inif_cust2_bytes(raw []byte, currHFIdx int, numInfoFields int, links map[uint16]int) bool{ + return inif2_type_bytes(raw, currHFIdx, numInfoFields, 3, links) +} + +ghost +requires acc(links) +requires forall key uint16 :: key in domain(links) ==> 0 <= links[key] && links[key] <= 4 +requires 0 < numInfoFields && numInfoFields <= 3 +requires 0 <= currHFIdx +requires 4 + 8 * numInfoFields + 12 * currHFIdx + 12 <= len(raw) +requires acc(&raw[4 + 8 * numInfoFields + 12 * currHFIdx+2], _) +requires acc(&raw[4 + 8 * numInfoFields + 12 * currHFIdx+3], _) +decreases +pure func inif_core2_bytes(raw []byte, currHFIdx int, numInfoFields int, links map[uint16]int) bool{ + return inif2_type_bytes(raw, currHFIdx, numInfoFields, 1, links) || + inif2_type_bytes(raw, currHFIdx, numInfoFields, 4, links) +} + +ghost +requires acc(links) +requires forall key uint16 :: key in domain(links) ==> 0 <= links[key] && links[key] <= 4 +requires 0 < numInfoFields && numInfoFields <= 3 +requires 0 <= currHFIdx +requires 4 + 8 * numInfoFields + 12 * currHFIdx + 12 <= len(raw) +requires acc(&raw[4 + 8 * numInfoFields + 12 * currHFIdx+2], _) +requires acc(&raw[4 + 8 * numInfoFields + 12 * currHFIdx+3], _) +decreases +pure func inif_prov2_bytes(raw []byte, currHFIdx int, numInfoFields int, links map[uint16]int) bool{ + return inif2_type_bytes(raw, currHFIdx, numInfoFields, 2, links) +} + +/* +ghost +decreases +pure func valid_link_types2(hf1 IO_HF, a IO_as) bool { + return (egif_prov2(hf1, a) && inif_cust2(hf1, a)) || + (egif_core2(hf1, a) && inif_core2(hf1, a)) || + (egif_cust2(hf1, a) && inif_prov2(hf1, a)) +} +*/ +/* +ghost +decreases +pure func valid_link_types_in2_bytes(raw []byte, currHFIdx int, a uint64) bool { + return (inif_prov2(hf1, a) && egif_cust2(hf1, a)) || + (inif_core2(hf1, a) && egif_core2(hf1, a)) || + (inif_cust2(hf1, a) && egif_prov2(hf1, a)) +} + +*/ +/* +ghost +decreases +pure func dp2_check_interface(d bool, asid IO_as, hf1 IO_HF, recvif IO_ifs) bool { + return (d && hf1.InIF2 === some(recvif) && valid_link_types_in2(hf1, asid)) || + (!d && hf1.EgIF2 === some(recvif) && valid_link_types2(hf1, asid)) +} +*/ + + +/* +ghost +decreases +pure func dp2_enter_guard_bytes(m IO_pkt2, currseg IO_seg2, traversedseg IO_seg2, asid IO_as, hf1 IO_HF, recvif IO_ifs, fut seq[IO_HF]) bool { + return m.CurrSeg == currseg && + currseg.Future == seq[IO_HF]{hf1} ++ fut && + dp2_check_interface(currseg.ConsDir, asid, hf1, recvif) && + update_uinfo(!currseg.ConsDir, currseg, traversedseg, hf1) && + same_segment2(currseg, traversedseg) && + same_other2(currseg, traversedseg) && + hf_valid(currseg.ConsDir, currseg.AInfo, traversedseg.UInfo, hf1) && + hf1.extr_asid() == asid +} +*/ + + + +// TODO: Do we need a body? +// TODO: can we get rid of this assumptions +ghost +ensures res.isMsgTerm_Hash +decreases +pure func computeMsgTerm(raw []byte, start int) (res io.IO_msgterm) ghost decreases @@ -643,4 +894,14 @@ ghost decreases pure func computeUInfo(raw []byte, currINF int) set[io.IO_msgterm] +//TODO: double check last case +ghost +requires 0 <= linkType && linkType <= 4 +decreases +pure func linkToIO_Link(linkType int) io.IO_Link{ + return linkType == 0 ? io.IO_NoLink{} : + (linkType == 1 || linkType == 4) ? io.IO_PeerOrCore{} : + linkType == 2 ? io.IO_CustProv{} : io.IO_ProvCust{} +} + /** End of io-spec helper functions **/ \ No newline at end of file diff --git a/verification/io/other_defs.gobra b/verification/io/other_defs.gobra index b2de80e8a..2f2574614 100644 --- a/verification/io/other_defs.gobra +++ b/verification/io/other_defs.gobra @@ -194,7 +194,8 @@ pure func inif_prov2(hf1 IO_HF, asid IO_as) bool{ ghost decreases pure func if_type(asid IO_as, ifs option[IO_ifs], link IO_Link) bool{ - return exists outif IO_ifs :: some(outif) == ifs && link_type(asid, outif) == link + return ifs == none[IO_ifs] ? false : link_type(asid, get(ifs)) == link + //exists outif IO_ifs :: some(outif) == ifs && link_type(asid, outif) == link } type ext2_rec struct { From 8a0452eab5ec9a8112c2816c3f3e2fc91fd4d21b Mon Sep 17 00:00:00 2001 From: MLETHZ Date: Mon, 24 Jul 2023 10:27:00 +0200 Subject: [PATCH 15/33] formatting --- router/dataplane_spec.gobra | 42 ++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/router/dataplane_spec.gobra b/router/dataplane_spec.gobra index 7baaddfab..f70553bb3 100644 --- a/router/dataplane_spec.gobra +++ b/router/dataplane_spec.gobra @@ -109,8 +109,8 @@ pred forwardingMetricsNonInjectiveMem(v forwardingMetrics) { } ghost -requires acc(forwardingMetricsNonInjectiveMem(v), _) -ensures acc(forwardingMetricsMem(v, id), _) +requires acc(forwardingMetricsNonInjectiveMem(v), _) +ensures acc(forwardingMetricsMem(v, id), _) decreases func liftForwardingMetricsNonInjectiveMem(v forwardingMetrics, id uint16) { unfold acc(forwardingMetricsNonInjectiveMem(v), _) @@ -138,8 +138,8 @@ pred (p *scionPacketProcessor) initMem() { requires acc(key, _) && acc(sl.AbsSlice_Bytes(*key, 0, len(*key)), _) requires scrypto.ValidKeyForHash(*key) -ensures acc(key, _) && acc(sl.AbsSlice_Bytes(*key, 0, len(*key)), _) -ensures res.Mem() +ensures acc(key, _) && acc(sl.AbsSlice_Bytes(*key, 0, len(*key)), _) +ensures res.Mem() decreases func MacFactorySpec(ghost key *[]byte) (res hash.Hash) @@ -167,7 +167,7 @@ func (err scmpError) IsDuplicableMem() bool { ghost trusted preserves err.ErrorMem() -ensures err.IsDuplicableMem() ==> err.ErrorMem() +ensures err.IsDuplicableMem() ==> err.ErrorMem() decreases func (err scmpError) Duplicate() { if err.IsDuplicableMem() { @@ -188,16 +188,16 @@ type offsetPair struct { ghost pure requires 0 <= n -ensures len(res) == n -ensures forall i int :: {res[i]} 0 <= i && i < len(res) ==> res[i] == offsetPair{} +ensures len(res) == n +ensures forall i int :: {res[i]} 0 <= i && i < len(res) ==> res[i] == offsetPair{} decreases func newOffsetPair(n int) (res seq[offsetPair]) /**** Acessor methods to avoid unfolding the Mem predicate of the dataplane so much ****/ ghost requires acc(MutexInvariant!(), _) -ensures acc(&d.internalNextHops, _) -ensures d.internalNextHops != nil ==> acc(AccAddr(d.internalNextHops), _) +ensures acc(&d.internalNextHops, _) +ensures d.internalNextHops != nil ==> acc(AccAddr(d.internalNextHops), _) decreases func (d *DataPlane) getInternalNextHops() { unfold acc(MutexInvariant!(), _) @@ -205,7 +205,7 @@ func (d *DataPlane) getInternalNextHops() { ghost requires acc(MutexInvariant!(), _) -ensures acc(&d.external, _) && (d.external != nil ==> acc(AccBatchConn(d.external), _)) +ensures acc(&d.external, _) && (d.external != nil ==> acc(AccBatchConn(d.external), _)) decreases func (d *DataPlane) getExternalMem() { unfold acc(MutexInvariant!(), _) @@ -213,7 +213,7 @@ func (d *DataPlane) getExternalMem() { ghost requires acc(MutexInvariant!(), _) -ensures acc(&d.linkTypes, _) && (d.linkTypes != nil ==> acc(d.linkTypes, _)) +ensures acc(&d.linkTypes, _) && (d.linkTypes != nil ==> acc(d.linkTypes, _)) decreases func (d *DataPlane) getLinkTypesMem() { unfold acc(MutexInvariant!(), _) @@ -221,7 +221,7 @@ func (d *DataPlane) getLinkTypesMem() { ghost requires acc(MutexInvariant!(), _) -ensures acc(&d.localIA, _) +ensures acc(&d.localIA, _) decreases func (d *DataPlane) getLocalIA() { unfold acc(MutexInvariant!(), _) @@ -229,7 +229,7 @@ func (d *DataPlane) getLocalIA() { ghost requires acc(MutexInvariant!(), _) -ensures acc(&d.neighborIAs, _) && (d.neighborIAs != nil ==> acc(d.neighborIAs, _)) +ensures acc(&d.neighborIAs, _) && (d.neighborIAs != nil ==> acc(d.neighborIAs, _)) decreases func (d *DataPlane) getNeighborIAs() { unfold acc(MutexInvariant!(), _) @@ -237,7 +237,7 @@ func (d *DataPlane) getNeighborIAs() { ghost requires acc(MutexInvariant!(), _) -ensures acc(&d.svc, _) && (d.svc != nil ==> acc(d.svc.Mem(), _)) +ensures acc(&d.svc, _) && (d.svc != nil ==> acc(d.svc.Mem(), _)) decreases func (d *DataPlane) getSvcMem() { unfold acc(MutexInvariant!(), _) @@ -245,7 +245,7 @@ func (d *DataPlane) getSvcMem() { ghost requires acc(MutexInvariant!(), _) -ensures acc(&d.bfdSessions, _) && (d.bfdSessions != nil ==> acc(AccBfdSession(d.bfdSessions), _)) +ensures acc(&d.bfdSessions, _) && (d.bfdSessions != nil ==> acc(AccBfdSession(d.bfdSessions), _)) decreases func (d *DataPlane) getBfdSessionsMem() { unfold acc(MutexInvariant!(), _) @@ -253,14 +253,14 @@ func (d *DataPlane) getBfdSessionsMem() { ghost requires acc(MutexInvariant!(), _) -ensures acc(&d.internal, _) && (d.internal != nil ==> acc(d.internal.Mem(), _)) +ensures acc(&d.internal, _) && (d.internal != nil ==> acc(d.internal.Mem(), _)) decreases func (d *DataPlane) getInternal() { unfold acc(MutexInvariant!(), _) } requires acc(MutexInvariant!(), _) -ensures acc(&d.macFactory, _) +ensures acc(&d.macFactory, _) decreases func (d *DataPlane) getMacFactoryMem() { unfold acc(MutexInvariant!(), _) @@ -269,10 +269,10 @@ func (d *DataPlane) getMacFactoryMem() { ghost requires acc(MutexInvariant!(), _) requires acc(&d.macFactory, _) && d.macFactory != nil -ensures acc(&d.macFactory, _) && acc(&d.key, _) && acc(d.key, _) -ensures acc(sl.AbsSlice_Bytes(*d.key, 0, len(*d.key)), _) -ensures scrypto.ValidKeyForHash(*d.key) -ensures d.macFactory implements MacFactorySpec{d.key} +ensures acc(&d.macFactory, _) && acc(&d.key, _) && acc(d.key, _) +ensures acc(sl.AbsSlice_Bytes(*d.key, 0, len(*d.key)), _) +ensures scrypto.ValidKeyForHash(*d.key) +ensures d.macFactory implements MacFactorySpec{d.key} decreases func (d *DataPlane) getNewPacketProcessorFootprint() { unfold acc(MutexInvariant!(), _) From 4540095ceaadf1a95194d16450ac5f5125b3928f Mon Sep 17 00:00:00 2001 From: MLETHZ Date: Mon, 24 Jul 2023 10:46:58 +0200 Subject: [PATCH 16/33] specification fixes --- verification/io/other_defs.gobra | 2 +- verification/io/router.gobra | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/verification/io/other_defs.gobra b/verification/io/other_defs.gobra index 2f2574614..269e41626 100644 --- a/verification/io/other_defs.gobra +++ b/verification/io/other_defs.gobra @@ -48,7 +48,7 @@ type IO_msgterm adt { } MsgTerm_Num { - MsgTerm_Num_ int // formallized as nat in Isabelle + MsgTerm_Num_ uint // formallized as nat in Isabelle } MsgTerm_Key { diff --git a/verification/io/router.gobra b/verification/io/router.gobra index 09b0c85f3..d4ea683c8 100644 --- a/verification/io/router.gobra +++ b/verification/io/router.gobra @@ -31,12 +31,19 @@ pure func hf_valid(p1 bool, p2 uint, p3 set[IO_msgterm], p4 IO_HF) bool { return let inif := p4.InIF2 in let egif := p4.EgIF2 in let x := p4.HVF in - let ts := IO_msgterm(MsgTerm_Num{int(p2)}) in + let ts := IO_msgterm(MsgTerm_Num{p2}) in let uinfo := IO_msgterm(MsgTerm_FS{p3}) in let l := IO_msgterm(MsgTerm_L{seq[IO_msgterm]{ts, if2term(inif), if2term(egif), uinfo}}) in exists a IO_key :: x == mac(macKey(a), l) } +//Helper function (not in Isabelle) +ghost +decreases +pure func asidToKey(asid IO_as) IO_key{ + return IO_key(Key_macK{asid}) +} + ghost decreases pure func macKey(key IO_key) IO_msgterm { From 53cadc96332f76cba44e540d15b6cf8e087a06b3 Mon Sep 17 00:00:00 2001 From: MLETHZ Date: Mon, 24 Jul 2023 20:06:55 +0200 Subject: [PATCH 17/33] IO-spec to pkt rewritten --- router/dataplane_spec.gobra | 271 ++++++++++++++++++++++++++++++++---- 1 file changed, 246 insertions(+), 25 deletions(-) diff --git a/router/dataplane_spec.gobra b/router/dataplane_spec.gobra index f70553bb3..0e13015a2 100644 --- a/router/dataplane_spec.gobra +++ b/router/dataplane_spec.gobra @@ -355,7 +355,7 @@ requires seg2Len >= 0 requires seg3Len >= 0 requires currHF < seg1Len + seg2Len + seg3Len decreases -pure func computeSeqlen(currHF int, seg1Len int, seg2Len int, seg3Len int) int{ +pure func computeSeqLen(currHF int, seg1Len int, seg2Len int, seg3Len int) int{ return seg1Len > currHF ? seg1Len : ((seg1Len + seg2Len) > currHF ? seg2Len : seg3Len) } @@ -376,7 +376,7 @@ requires seg1Len > 0 requires seg2Len >= 0 requires seg3Len >= 0 requires currHF >= 0 -ensures res <= currHF +ensures res <= currHF decreases pure func computePrevSegLen(currHF int, seg1Len int, seg2Len int, seg3Len int) (res int){ return seg1Len > currHF ? 0 : ((seg1Len + seg2Len) > currHF ? seg1Len : seg1Len + seg2Len) @@ -398,6 +398,66 @@ pure func getHopField(raw []byte, start int) io.IO_HF { }) } +ghost +requires idx + 12 <= len(raw) +requires 0 <= idx +requires acc(&raw[idx+2], _) && acc(&raw[idx+3], _) && acc(&raw[idx+4], _) && acc(&raw[idx+5], _) +ensures len(res.HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_) > 0 +decreases +pure func getHopField2(raw []byte, idx int, beta set[io.IO_msgterm], asid io.IO_as, ainfo io.IO_ainfo) (res io.IO_HF) { + return let inif2 := binary.BigEndian.Uint16(raw[idx+2:idx+4]) in + let egif2 := binary.BigEndian.Uint16(raw[idx+4:idx+6]) in + let op_inif2 := inif2 == 0 ? none[io.IO_ifs] : some(io.IO_ifs(inif2)) in + let op_egif2 := egif2 == 0 ? none[io.IO_ifs] : some(io.IO_ifs(egif2)) in + let ts := io.IO_msgterm(io.MsgTerm_Num{ainfo}) in + let l := io.IO_msgterm(io.MsgTerm_L{seq[io.IO_msgterm]{ts, io.if2term(op_inif2), io.if2term(op_egif2), + io.IO_msgterm(io.MsgTerm_FS{beta})}}) in + let hvf := io.mac(io.macKey(io.asidToKey(asid)), l) in + io.IO_HF(io.IO_HF_{ + InIF2 : op_inif2, + EgIF2 : op_egif2, + HVF : hvf, + }) +} + +ghost +requires 0 <= offset +requires 0 <= currHFIdx && currHFIdx <= segLen +requires offset + 12 * segLen <= len(raw) +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +ensures len(res) == segLen - currHFIdx +ensures forall k int :: 0 <= k && k < len(res) ==> + len(res[k].HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_) > 0 +decreases segLen - currHFIdx +pure func getHopfieldsConsDir(raw []byte, offset int, currHFIdx int, segLen int, beta set[io.IO_msgterm], asid io.IO_as, ainfo io.IO_ainfo) (res seq[io.IO_HF]){ + return currHFIdx == segLen ? seq[io.IO_HF]{} : + let hf := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getHopField2(raw, offset + 12 * currHFIdx, beta, asid, ainfo)) in + seq[io.IO_HF]{hf} ++ getHopfieldsConsDir(raw, offset, currHFIdx + 1, segLen, (beta union set[io.IO_msgterm]{hf.HVF}), asid, ainfo) +} + +ghost +requires 0 <= offset +requires -1 <= currHFIdx +requires offset + 12 * currHFIdx + 12 <= len(raw) +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +ensures len(res) == currHFIdx + 1 +ensures forall k int :: 0 <= k && k < len(res) ==> + len(res[k].HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_) > 0 +decreases currHFIdx + 1 +pure func getHopfieldsNotConsDir(raw []byte, offset int, currHFIdx int, beta set[io.IO_msgterm], asid io.IO_as, ainfo io.IO_ainfo) (res seq[io.IO_HF]){ + return currHFIdx == -1 ? seq[io.IO_HF]{} : + let hf := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getHopField2(raw, offset + 12 * currHFIdx, beta, asid, ainfo)) in + getHopfieldsNotConsDir(raw, offset, currHFIdx -1, (beta union set[io.IO_msgterm]{hf.HVF}), asid, ainfo) ++ seq[io.IO_HF]{hf} +} + +ghost +requires -1 <= currHFIdx && currHFIdx < len(hopfields) +decreases currHFIdx + 1 +pure func getSegPast2(hopfields seq[io.IO_HF], currHFIdx int) seq[io.IO_HF]{ + return currHFIdx == -1 ? seq[io.IO_HF]{} : + seq[io.IO_HF]{hopfields[currHFIdx]} ++ getSegPast2(hopfields, currHFIdx - 1) +} + //expects the raw bytes of whole path ghost requires 4 + 8 * numINF + offset * 12 + 12 <= len(raw) @@ -411,6 +471,14 @@ pure func getSegPast(raw []byte, prevSegLen int, offset int, numINF int) seq[io. seq[io.IO_HF]{getHopField(raw,4 + 8 * numINF + offset*12)}) ++ getSegPast(raw, prevSegLen, offset-1, numINF) } +ghost +requires 0 <= currHFIdx && currHFIdx <= len(hopfields) +decreases len(hopfields) - currHFIdx +pure func getSegFuture2(hopfields seq[io.IO_HF], currHFIdx int) seq[io.IO_HF]{ + return currHFIdx == len(hopfields) ? seq[io.IO_HF]{} : + seq[io.IO_HF]{hopfields[currHFIdx]} ++ getSegFuture2(hopfields, currHFIdx + 1) +} + //expects the raw bytes of whole path ghost requires 4 + 8 * numINF + offset*12 + 12 <= len(raw) @@ -423,6 +491,15 @@ pure func getSegFuture(raw []byte, currHF int, offset int, numINF int) seq[io.IO getSegFuture(raw, currHF, offset-1, numINF) ++ (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in seq[io.IO_HF]{getHopField(raw, 4 + 8 * numINF + offset*12)}) } +ghost +requires -1 <= currHFIdx && currHFIdx < len(hopfields) +decreases currHFIdx + 1 +pure func getSegHistory2(hopfields seq[io.IO_HF], currHFIdx int) seq[io.IO_ahi]{ + return currHFIdx == -1 ? seq[io.IO_ahi]{} : + seq[io.IO_ahi]{hopfields[currHFIdx].Toab()} ++ getSegHistory2(hopfields, currHFIdx - 1) + +} + //expects the raw bytes of whole path ghost requires 4 + 8 * numINF + offset*12 + 12 <= len(raw) @@ -436,6 +513,49 @@ pure func getSegHistory(raw []byte, prevSegLen int, offset int, numINF int) seq[ seq[io.IO_ahi]{getHopField(raw,4 + 8 * numINF + offset*12).Toab()}) ++ getSegHistory(raw, prevSegLen, offset-1, numINF) } +ghost +requires len(hopfield.HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_) > 0 +decreases +pure func getHVFSet(hopfield io.IO_HF) set[io.IO_msgterm]{ + return let l := hopfield.HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_ in + l[len(l) - 1].MsgTerm_FS_ +} + +ghost +requires 0 < len(hopfields) +requires 0 <= currHFIdx && currHFIdx <= len(hopfields) +requires forall idx int :: 0 <= idx && idx < len(hopfields) ==> + len(hopfields[idx].HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_) > 0 +decreases +pure func getUInfo(hopfields seq[io.IO_HF], currHFIdx int, consDir bool) set[io.IO_msgterm]{ + return currHFIdx == len(hopfields) ? getHVFSet(hopfields[currHFIdx-1]) : + currHFIdx == 0 ? getHVFSet(hopfields[currHFIdx]) : + consDir ? getHVFSet(hopfields[currHFIdx]) : getHVFSet(hopfields[currHFIdx-1]) +} + +ghost +requires 0 <= offset +requires 0 < segLen +requires offset + 12 * segLen <= len(raw) +requires 0 <= currHFIdx && currHFIdx <= segLen +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +decreases +pure func getSegment2(raw []byte, offset int, currHFIdx int, segLen int, asid io.IO_as, ainfo io.IO_ainfo, consDir bool, peer bool) io.IO_seg2{ + return let hopfields := consDir ? + getHopfieldsConsDir(raw, offset, 0, segLen, set[io.IO_msgterm]{}, asid, ainfo) : + getHopfieldsNotConsDir(raw, offset, segLen - 1, set[io.IO_msgterm]{}, asid, ainfo) in + let uinfo := getUInfo(hopfields, currHFIdx, consDir) in + io.IO_seg2(io.IO_seg3_{ + AInfo :ainfo, + UInfo : uinfo, + ConsDir : consDir, + Peer : peer, + Past : getSegPast2(hopfields, currHFIdx - 1), + Future : getSegFuture2(hopfields, currHFIdx), + History : getSegHistory2(hopfields, currHFIdx - 1), + }) +} + //expects the raw bytes of whole path ghost requires 4 + 8 * numINF + 12 * (prevSegLen + segLen) <= len(raw) @@ -476,6 +596,22 @@ pure func getPastSegment(raw []byte, consDir bool, peer bool, currHF int, prevSe }) } +ghost +requires 4 + 8 * currINFIdx + 8 <= offset +requires 0 < segLen +requires offset + 12 * segLen <= len(raw) +requires 0 <= currHFIdx && currHFIdx <= segLen +requires 0 <= currINFIdx && currINFIdx < 3 +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +decreases +pure func getCurrSeg2(raw []byte, offset int, currINFIdx int, currHFIdx int, segLen int, asid io.IO_as) io.IO_seg3 { + return unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in + let ainfo := getTimestamp(raw, currINFIdx) in + let consDir := getConsDir(raw, currINFIdx) in + let peer := getPeer(raw, currINFIdx) in + getSegment2(raw, offset, currHFIdx, segLen, asid, ainfo, consDir, peer) +} + ghost requires seg1Len > 0 requires seg2Len >= 0 @@ -483,16 +619,30 @@ requires seg3Len >= 0 requires 4 + 8 * numInfoFields(seg1Len, seg2Len, seg3Len) + 12 * (seg1Len + seg2Len + seg3Len) == len(raw) requires 0 <= currINF && currINF < 3 requires 0 <= currHF && currHF < seg1Len + seg2Len + seg3Len -requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) + computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF +requires computeSeqLen(currHF, seg1Len, seg2Len, seg3Len) + computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases pure func getCurrSeg(raw []byte, currINF int, currHF int, seg1Len int, seg2Len int, seg3Len int) io.IO_seg3 { return let consDir := getConsDir(raw, currINF) in - let peer := getPeer(raw, currINF) in - let segLen := computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) in - let prevSegLen := computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len) in - let numINF := numInfoFields(seg1Len, seg2Len, seg3Len) in - getSegment(raw, consDir, peer, currHF, prevSegLen, segLen, numINF, currINF) + let peer := getPeer(raw, currINF) in + let segLen := computeSeqLen(currHF, seg1Len, seg2Len, seg3Len) in + let prevSegLen := computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len) in + let numINF := numInfoFields(seg1Len, seg2Len, seg3Len) in + getSegment(raw, consDir, peer, currHF, prevSegLen, segLen, numINF, currINF) +} + +ghost +requires 0 < seg1Len +requires 0 <= seg2Len +requires 0 <= seg3Len +requires 4 + 8 * numInfoFields(seg1Len, seg2Len, seg3Len) == offset +requires offset + 12 * (seg1Len + seg2Len + seg3Len) <= len(raw) +requires 1 <= currINFIdx && currINFIdx < 4 +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +decreases +pure func getLeftSeg2(raw []byte, offset int, currINFIdx int, seg1Len int, seg2Len int, seg3Len int, asid io.IO_as) option[io.IO_seg3] { + return (currINFIdx == 1 && seg2Len > 0) ? some(getCurrSeg2(raw, offset + 12 * seg1Len, currINFIdx, 0, seg2Len, asid)) : + (currINFIdx == 2 && seg3Len > 0) ? some(getCurrSeg2(raw, offset + 12 * (seg1Len + seg2Len), currINFIdx, 0, seg3Len, asid)) : none[io.IO_seg3] } ghost @@ -502,15 +652,29 @@ requires seg3Len >= 0 requires 4 + 8 * numInfoFields(seg1Len, seg2Len, seg3Len) + 12 * (seg1Len + seg2Len + seg3Len) == len(raw) requires 0 <= currINF && currINF < 3 requires 0 <= currHF && currHF < seg1Len + seg2Len + seg3Len -requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) + computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF +requires computeSeqLen(currHF, seg1Len, seg2Len, seg3Len) + computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases pure func getLeftSeg(raw []byte, currINF int, currHF int, seg1Len int, seg2Len int, seg3Len int) option[io.IO_seg3] { - return let newCurrHF := computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) + computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len) in + return let newCurrHF := computeSeqLen(currHF, seg1Len, seg2Len, seg3Len) + computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len) in (newCurrHF == seg1Len + seg2Len + seg3Len || currINF == 2) ? none[io.IO_seg3] : some(getCurrSeg(raw, currINF + 1, newCurrHF, seg1Len, seg2Len, seg3Len)) } +ghost +requires 0 < seg1Len +requires 0 <= seg2Len +requires 0 <= seg3Len +requires 4 + 8 * numInfoFields(seg1Len, seg2Len, seg3Len) == offset +requires offset + 12 * (seg1Len + seg2Len + seg3Len) <= len(raw) +requires -1 <= currINFIdx && currINFIdx < 2 +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +decreases +pure func getRightSeg2(raw []byte, offset int, currINFIdx int, seg1Len int, seg2Len int, seg3Len int, asid io.IO_as) option[io.IO_seg3] { + return (currINFIdx == 1 && seg3Len > 0 && seg2Len > 0) ? some(getCurrSeg2(raw, offset + 12 * seg1Len, currINFIdx, seg2Len, seg2Len, asid)) : + (currINFIdx == 0 && seg2Len > 0) ? some(getCurrSeg2(raw, offset, currINFIdx, seg1Len, seg1Len, asid)) : none[io.IO_seg3] +} + ghost requires seg1Len > 0 requires seg2Len >= 0 @@ -518,18 +682,32 @@ requires seg3Len >= 0 requires 4 + 8 * numInfoFields(seg1Len, seg2Len, seg3Len) + 12 * (seg1Len + seg2Len + seg3Len) == len(raw) requires 0 <= currINF && currINF < 3 requires 0 <= currHF && currHF < seg1Len + seg2Len + seg3Len -requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) + computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF +requires computeSeqLen(currHF, seg1Len, seg2Len, seg3Len) + computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases pure func getRightSeg(raw []byte, currINF int, currHF int, seg1Len int, seg2Len int, seg3Len int) option[io.IO_seg3] { return (computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len) == 0 || currINF == 0) ? none[io.IO_seg3] : - (let newCurrHF := computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len)-1 in - let consDir := getConsDir(raw, currINF-1) in - let peer := getPeer(raw, currINF-1) in - let segLen := computeSeqlen(newCurrHF, seg1Len, seg2Len, seg3Len) in - let prevSegLen := computePrevSegLen(newCurrHF, seg1Len, seg2Len, seg3Len) in - let numINF := numInfoFields(seg1Len, seg2Len, seg3Len) in - some(getPastSegment(raw, consDir, peer, newCurrHF, prevSegLen, segLen, numINF, currINF))) + (let newCurrHF := computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len)-1 in + let consDir := getConsDir(raw, currINF-1) in + let peer := getPeer(raw, currINF-1) in + let segLen := computeSeqLen(newCurrHF, seg1Len, seg2Len, seg3Len) in + let prevSegLen := computePrevSegLen(newCurrHF, seg1Len, seg2Len, seg3Len) in + let numINF := numInfoFields(seg1Len, seg2Len, seg3Len) in + some(getPastSegment(raw, consDir, peer, newCurrHF, prevSegLen, segLen, numINF, currINF))) +} + +ghost +requires 0 < seg1Len +requires 0 <= seg2Len +requires 0 <= seg3Len +requires 4 + 8 * numInfoFields(seg1Len, seg2Len, seg3Len) == offset +requires offset + 12 * (seg1Len + seg2Len + seg3Len) <= len(raw) +requires 2 <= currINFIdx && currINFIdx < 5 +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +decreases +pure func getMidSeg2(raw []byte, offset int, currINFIdx int, seg1Len int, seg2Len int, seg3Len int, asid io.IO_as) option[io.IO_seg3] { + return (currINFIdx == 4 && seg3Len > 0) ? some(getCurrSeg2(raw, offset, 0, seg1Len, seg1Len, asid)) : + (currINFIdx == 2 && seg3Len > 0) ? some(getCurrSeg2(raw, offset + 12 * (seg1Len + seg2Len), currINFIdx, 0, seg3Len, asid)) : none[io.IO_seg3] } ghost @@ -539,7 +717,7 @@ requires seg3Len >= 0 requires 4 + 8 * numInfoFields(seg1Len, seg2Len, seg3Len) + 12 * (seg1Len + seg2Len + seg3Len) == len(raw) requires 0 <= currINF && currINF < 3 requires 0 <= currHF && currHF < seg1Len + seg2Len + seg3Len -requires computeSeqlen(currHF, seg1Len, seg2Len, seg3Len) + computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF +requires computeSeqLen(currHF, seg1Len, seg2Len, seg3Len) + computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases pure func getMidSeg(raw []byte, currINF int, currHF int, seg1Len int, seg2Len int, seg3Len int) option[io.IO_seg3] { @@ -552,6 +730,38 @@ pure func getMidSeg(raw []byte, currINF int, currHF int, seg1Len int, seg2Len in some(getPastSegment(raw, consDir, peer, seg1Len-1, 0, seg1Len, numINF, currINF))) } +ghost +requires len(raw) > 4 +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +requires unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in + let hdr := binary.BigEndian.Uint32(raw[0:4]) in + 0 <= getCurrINF(hdr) && getCurrINF(hdr) < 3 && + getCurrINF(hdr) + 1 <= numInfoFields(int(getSeg1Len(hdr)), int(getSeg2Len(hdr)), int(getSeg3Len(hdr))) && + 0 <= getCurrHF(hdr) && getCurrHF(hdr) < getSeg1Len(hdr) + getSeg2Len(hdr) + getSeg3Len(hdr) && + 0 < getSeg1Len(hdr) && + 0 <= getSeg2Len(hdr) && + 0 <= getSeg3Len(hdr) && + 4 + 8 * numInfoFields(int(getSeg1Len(hdr)), int(getSeg2Len(hdr)), int(getSeg3Len(hdr))) + 12 * (int(getSeg1Len(hdr)) + int(getSeg2Len(hdr)) + int(getSeg3Len(hdr))) == len(raw) +decreases +pure func getPkt2(raw []byte, asid io.IO_as) io.IO_pkt2{ + return let hdr := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in binary.BigEndian.Uint32(raw[0:4]) in + let currINFIdx := int(getCurrINF(hdr)) in + let currHFIdx := int(getCurrHF(hdr)) in + let seg1Len := int(getSeg1Len(hdr)) in + let seg2Len := int(getSeg2Len(hdr)) in + let seg3Len := int(getSeg3Len(hdr)) in + let segLen := computeSeqLen(currHFIdx, seg1Len, seg2Len, seg3Len) in + let prevSegLen := computePrevSegLen(currHFIdx, seg1Len, seg2Len, seg3Len) in + let numINF := int(numInfoFields(seg1Len, seg2Len, seg3Len)) in + let offset := 4 + 8 * numINF in + io.IO_pkt2(io.IO_Packet2{ + CurrSeg : getCurrSeg2(raw, offset+prevSegLen, currINFIdx, currHFIdx-prevSegLen, segLen, asid), // currINFIdx = {0, 1, 2} + LeftSeg : getLeftSeg2(raw, offset, currINFIdx + 1, seg1Len, seg2Len , seg3Len, asid), // currINFIdx = {1, 2, 3} + MidSeg : getMidSeg2(raw, offset, currINFIdx + 2, seg1Len, seg2Len , seg3Len, asid), // currINFIdx = {2, 3, 4} + RightSeg : getRightSeg2(raw, offset, currINFIdx - 1, seg1Len, seg2Len , seg3Len, asid), // currINFIdx = {-1, 0, 1} + }) +} + //TODO improve preconditions ghost requires len(raw) > 4 @@ -613,21 +823,32 @@ pure func getSeg3Len(hdr uint32) uint8{ ghost requires 0 <= offset requires infoFieldOffsetSeg(offset) < len(raw) -requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +requires acc(&raw[infoFieldOffsetSeg(offset)], _) decreases pure func getConsDir(raw []byte, offset int) bool{ - return unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in - raw[infoFieldOffsetSeg(offset)] & 0x1 == 0x1 + return raw[infoFieldOffsetSeg(offset)] & 0x1 == 0x1 } ghost requires 0 <= offset requires infoFieldOffsetSeg(offset) < len(raw) -requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +requires acc(&raw[infoFieldOffsetSeg(offset)], _) decreases pure func getPeer(raw []byte, offset int) bool{ - return unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in - raw[infoFieldOffsetSeg(offset)] & 0x2 == 0x2 + return raw[infoFieldOffsetSeg(offset)] & 0x2 == 0x2 +} + +ghost +requires 0 <= offset +requires infoFieldOffsetSeg(offset) + 8 < len(raw) +requires acc(&raw[infoFieldOffsetSeg(offset) + 4], _) +requires acc(&raw[infoFieldOffsetSeg(offset) + 5], _) +requires acc(&raw[infoFieldOffsetSeg(offset) + 6], _) +requires acc(&raw[infoFieldOffsetSeg(offset) + 7], _) +decreases +pure func getTimestamp(raw []byte, offset int) io.IO_ainfo{ + return let idx := infoFieldOffsetSeg(offset) + 4 in + io.IO_ainfo(binary.BigEndian.Uint32(raw[idx : idx + 4])) } // TODO Do we need a body? From 790e842011cfe82b7ef56d8890288b937e9a26fd Mon Sep 17 00:00:00 2001 From: MLETHZ Date: Mon, 24 Jul 2023 20:16:16 +0200 Subject: [PATCH 18/33] clean up --- router/dataplane_spec.gobra | 311 ++++++------------------------------ 1 file changed, 50 insertions(+), 261 deletions(-) diff --git a/router/dataplane_spec.gobra b/router/dataplane_spec.gobra index 0e13015a2..73c65c556 100644 --- a/router/dataplane_spec.gobra +++ b/router/dataplane_spec.gobra @@ -350,9 +350,9 @@ func closureSpec3(c BatchConn) /** Start of io-spec helper functions **/ ghost -requires seg1Len > 0 -requires seg2Len >= 0 -requires seg3Len >= 0 +requires 0 < seg1Len +requires 0 <= seg2Len +requires 0 <= seg3Len requires currHF < seg1Len + seg2Len + seg3Len decreases pure func computeSeqLen(currHF int, seg1Len int, seg2Len int, seg3Len int) int{ @@ -372,39 +372,23 @@ pure func numInfoFields(seg1Len int, seg2Len int, seg3Len int) int { } ghost -requires seg1Len > 0 -requires seg2Len >= 0 -requires seg3Len >= 0 -requires currHF >= 0 +requires 0 < seg1Len +requires 0 <= seg2Len +requires 0 <= seg3Len +requires 0 <= currHF ensures res <= currHF decreases pure func computePrevSegLen(currHF int, seg1Len int, seg2Len int, seg3Len int) (res int){ return seg1Len > currHF ? 0 : ((seg1Len + seg2Len) > currHF ? seg1Len : seg1Len + seg2Len) } -//expects the raw bytes of whole path -ghost -requires start + 12 <= len(raw) -requires 0 <= start -requires acc(&raw[start+2], _) && acc(&raw[start+3], _) && acc(&raw[start+4], _) && acc(&raw[start+5], _) -decreases -pure func getHopField(raw []byte, start int) io.IO_HF { - return let inif2 := binary.BigEndian.Uint16(raw[start+2:start+4]) in - let egif2 := binary.BigEndian.Uint16(raw[start+4:start+6]) in - io.IO_HF(io.IO_HF_{ - InIF2 : inif2 == 0 ? none[io.IO_ifs] : some(io.IO_ifs(inif2)), - EgIF2 : egif2 == 0 ? none[io.IO_ifs] : some(io.IO_ifs(egif2)), - HVF : computeMsgTerm(raw, start), - }) -} - ghost requires idx + 12 <= len(raw) requires 0 <= idx requires acc(&raw[idx+2], _) && acc(&raw[idx+3], _) && acc(&raw[idx+4], _) && acc(&raw[idx+5], _) ensures len(res.HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_) > 0 decreases -pure func getHopField2(raw []byte, idx int, beta set[io.IO_msgterm], asid io.IO_as, ainfo io.IO_ainfo) (res io.IO_HF) { +pure func getHopField(raw []byte, idx int, beta set[io.IO_msgterm], asid io.IO_as, ainfo io.IO_ainfo) (res io.IO_HF) { return let inif2 := binary.BigEndian.Uint16(raw[idx+2:idx+4]) in let egif2 := binary.BigEndian.Uint16(raw[idx+4:idx+6]) in let op_inif2 := inif2 == 0 ? none[io.IO_ifs] : some(io.IO_ifs(inif2)) in @@ -431,7 +415,7 @@ ensures forall k int :: 0 <= k && k < len(res) ==> decreases segLen - currHFIdx pure func getHopfieldsConsDir(raw []byte, offset int, currHFIdx int, segLen int, beta set[io.IO_msgterm], asid io.IO_as, ainfo io.IO_ainfo) (res seq[io.IO_HF]){ return currHFIdx == segLen ? seq[io.IO_HF]{} : - let hf := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getHopField2(raw, offset + 12 * currHFIdx, beta, asid, ainfo)) in + let hf := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getHopField(raw, offset + 12 * currHFIdx, beta, asid, ainfo)) in seq[io.IO_HF]{hf} ++ getHopfieldsConsDir(raw, offset, currHFIdx + 1, segLen, (beta union set[io.IO_msgterm]{hf.HVF}), asid, ainfo) } @@ -446,93 +430,35 @@ ensures forall k int :: 0 <= k && k < len(res) ==> decreases currHFIdx + 1 pure func getHopfieldsNotConsDir(raw []byte, offset int, currHFIdx int, beta set[io.IO_msgterm], asid io.IO_as, ainfo io.IO_ainfo) (res seq[io.IO_HF]){ return currHFIdx == -1 ? seq[io.IO_HF]{} : - let hf := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getHopField2(raw, offset + 12 * currHFIdx, beta, asid, ainfo)) in + let hf := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getHopField(raw, offset + 12 * currHFIdx, beta, asid, ainfo)) in getHopfieldsNotConsDir(raw, offset, currHFIdx -1, (beta union set[io.IO_msgterm]{hf.HVF}), asid, ainfo) ++ seq[io.IO_HF]{hf} } ghost requires -1 <= currHFIdx && currHFIdx < len(hopfields) decreases currHFIdx + 1 -pure func getSegPast2(hopfields seq[io.IO_HF], currHFIdx int) seq[io.IO_HF]{ +pure func getSegPast(hopfields seq[io.IO_HF], currHFIdx int) seq[io.IO_HF]{ return currHFIdx == -1 ? seq[io.IO_HF]{} : - seq[io.IO_HF]{hopfields[currHFIdx]} ++ getSegPast2(hopfields, currHFIdx - 1) -} - -//expects the raw bytes of whole path -ghost -requires 4 + 8 * numINF + offset * 12 + 12 <= len(raw) -requires prevSegLen >= 0 && offset - prevSegLen >= -1 -requires 0 < numINF && numINF < 4 -requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -decreases offset - prevSegLen + 1 -pure func getSegPast(raw []byte, prevSegLen int, offset int, numINF int) seq[io.IO_HF]{ - return offset - prevSegLen == -1 ? seq[io.IO_HF]{} : - (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in - seq[io.IO_HF]{getHopField(raw,4 + 8 * numINF + offset*12)}) ++ getSegPast(raw, prevSegLen, offset-1, numINF) + seq[io.IO_HF]{hopfields[currHFIdx]} ++ getSegPast(hopfields, currHFIdx - 1) } ghost requires 0 <= currHFIdx && currHFIdx <= len(hopfields) decreases len(hopfields) - currHFIdx -pure func getSegFuture2(hopfields seq[io.IO_HF], currHFIdx int) seq[io.IO_HF]{ +pure func getSegFuture(hopfields seq[io.IO_HF], currHFIdx int) seq[io.IO_HF]{ return currHFIdx == len(hopfields) ? seq[io.IO_HF]{} : - seq[io.IO_HF]{hopfields[currHFIdx]} ++ getSegFuture2(hopfields, currHFIdx + 1) -} - -//expects the raw bytes of whole path -ghost -requires 4 + 8 * numINF + offset*12 + 12 <= len(raw) -requires offset >= currHF && currHF >= 0 -requires 0 < numINF && numINF < 4 -requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -decreases offset - currHF -pure func getSegFuture(raw []byte, currHF int, offset int, numINF int) seq[io.IO_HF]{ - return offset == currHF ? (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in seq[io.IO_HF]{getHopField(raw,4 + 8 * numINF + offset*12)}) : - getSegFuture(raw, currHF, offset-1, numINF) ++ (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in seq[io.IO_HF]{getHopField(raw, 4 + 8 * numINF + offset*12)}) + seq[io.IO_HF]{hopfields[currHFIdx]} ++ getSegFuture(hopfields, currHFIdx + 1) } ghost requires -1 <= currHFIdx && currHFIdx < len(hopfields) decreases currHFIdx + 1 -pure func getSegHistory2(hopfields seq[io.IO_HF], currHFIdx int) seq[io.IO_ahi]{ +pure func getSegHistory(hopfields seq[io.IO_HF], currHFIdx int) seq[io.IO_ahi]{ return currHFIdx == -1 ? seq[io.IO_ahi]{} : - seq[io.IO_ahi]{hopfields[currHFIdx].Toab()} ++ getSegHistory2(hopfields, currHFIdx - 1) + seq[io.IO_ahi]{hopfields[currHFIdx].Toab()} ++ getSegHistory(hopfields, currHFIdx - 1) } -//expects the raw bytes of whole path -ghost -requires 4 + 8 * numINF + offset*12 + 12 <= len(raw) -requires prevSegLen >= 0 && offset - prevSegLen >= -1 -requires 0 < numINF && numINF < 4 -requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -decreases offset - prevSegLen + 1 -pure func getSegHistory(raw []byte, prevSegLen int, offset int, numINF int) seq[io.IO_ahi]{ - return offset - prevSegLen == -1 ? seq[io.IO_ahi]{} : - (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in - seq[io.IO_ahi]{getHopField(raw,4 + 8 * numINF + offset*12).Toab()}) ++ getSegHistory(raw, prevSegLen, offset-1, numINF) -} - -ghost -requires len(hopfield.HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_) > 0 -decreases -pure func getHVFSet(hopfield io.IO_HF) set[io.IO_msgterm]{ - return let l := hopfield.HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_ in - l[len(l) - 1].MsgTerm_FS_ -} - -ghost -requires 0 < len(hopfields) -requires 0 <= currHFIdx && currHFIdx <= len(hopfields) -requires forall idx int :: 0 <= idx && idx < len(hopfields) ==> - len(hopfields[idx].HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_) > 0 -decreases -pure func getUInfo(hopfields seq[io.IO_HF], currHFIdx int, consDir bool) set[io.IO_msgterm]{ - return currHFIdx == len(hopfields) ? getHVFSet(hopfields[currHFIdx-1]) : - currHFIdx == 0 ? getHVFSet(hopfields[currHFIdx]) : - consDir ? getHVFSet(hopfields[currHFIdx]) : getHVFSet(hopfields[currHFIdx-1]) -} - ghost requires 0 <= offset requires 0 < segLen @@ -540,7 +466,7 @@ requires offset + 12 * segLen <= len(raw) requires 0 <= currHFIdx && currHFIdx <= segLen requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases -pure func getSegment2(raw []byte, offset int, currHFIdx int, segLen int, asid io.IO_as, ainfo io.IO_ainfo, consDir bool, peer bool) io.IO_seg2{ +pure func getSegment(raw []byte, offset int, currHFIdx int, segLen int, asid io.IO_as, ainfo io.IO_ainfo, consDir bool, peer bool) io.IO_seg2{ return let hopfields := consDir ? getHopfieldsConsDir(raw, offset, 0, segLen, set[io.IO_msgterm]{}, asid, ainfo) : getHopfieldsNotConsDir(raw, offset, segLen - 1, set[io.IO_msgterm]{}, asid, ainfo) in @@ -550,52 +476,12 @@ pure func getSegment2(raw []byte, offset int, currHFIdx int, segLen int, asid io UInfo : uinfo, ConsDir : consDir, Peer : peer, - Past : getSegPast2(hopfields, currHFIdx - 1), - Future : getSegFuture2(hopfields, currHFIdx), - History : getSegHistory2(hopfields, currHFIdx - 1), + Past : getSegPast(hopfields, currHFIdx - 1), + Future : getSegFuture(hopfields, currHFIdx), + History : getSegHistory(hopfields, currHFIdx - 1), }) } -//expects the raw bytes of whole path -ghost -requires 4 + 8 * numINF + 12 * (prevSegLen + segLen) <= len(raw) -requires prevSegLen >= 0 && segLen >= 0 -requires 0 < numINF && numINF < 4 -requires segLen+prevSegLen > currHF && currHF >= prevSegLen -requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -decreases -pure func getSegment(raw []byte, consDir bool, peer bool, currHF int, prevSegLen int, segLen int, numINF int, currINF int) io.IO_seg2{ - return io.IO_seg2(io.IO_seg3_{ - AInfo : computeAInfo(raw, currINF), - UInfo : computeUInfo(raw, currINF), - ConsDir : consDir, - Peer : peer, - Past : getSegPast(raw, prevSegLen, currHF - 1, numINF), - Future : getSegFuture(raw, currHF, segLen+prevSegLen-1, numINF), - History : getSegHistory(raw, prevSegLen, currHF - 1, numINF), - }) -} - -//expects the raw bytes of whole path -ghost -requires 4 + 8 * numINF + 12 * (prevSegLen + segLen) <= len(raw) -requires prevSegLen >= 0 && segLen >= 0 -requires 0 < numINF && numINF < 4 -requires segLen+prevSegLen > currHF && currHF >= prevSegLen -requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -decreases -pure func getPastSegment(raw []byte, consDir bool, peer bool, currHF int, prevSegLen int, segLen int, numINF int, currINF int) io.IO_seg2{ - return io.IO_seg2(io.IO_seg3_{ - AInfo : computeAInfo(raw, currINF), - UInfo : computeUInfo(raw, currINF), - ConsDir : consDir, - Peer : peer, - Past : getSegPast(raw, prevSegLen, currHF, numINF), - Future : seq[io.IO_HF]{}, - History : getSegHistory(raw, prevSegLen, currHF, numINF), - }) -} - ghost requires 4 + 8 * currINFIdx + 8 <= offset requires 0 < segLen @@ -604,31 +490,12 @@ requires 0 <= currHFIdx && currHFIdx <= segLen requires 0 <= currINFIdx && currINFIdx < 3 requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases -pure func getCurrSeg2(raw []byte, offset int, currINFIdx int, currHFIdx int, segLen int, asid io.IO_as) io.IO_seg3 { +pure func getCurrSeg(raw []byte, offset int, currINFIdx int, currHFIdx int, segLen int, asid io.IO_as) io.IO_seg3 { return unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in let ainfo := getTimestamp(raw, currINFIdx) in let consDir := getConsDir(raw, currINFIdx) in let peer := getPeer(raw, currINFIdx) in - getSegment2(raw, offset, currHFIdx, segLen, asid, ainfo, consDir, peer) -} - -ghost -requires seg1Len > 0 -requires seg2Len >= 0 -requires seg3Len >= 0 -requires 4 + 8 * numInfoFields(seg1Len, seg2Len, seg3Len) + 12 * (seg1Len + seg2Len + seg3Len) == len(raw) -requires 0 <= currINF && currINF < 3 -requires 0 <= currHF && currHF < seg1Len + seg2Len + seg3Len -requires computeSeqLen(currHF, seg1Len, seg2Len, seg3Len) + computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF -requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -decreases -pure func getCurrSeg(raw []byte, currINF int, currHF int, seg1Len int, seg2Len int, seg3Len int) io.IO_seg3 { - return let consDir := getConsDir(raw, currINF) in - let peer := getPeer(raw, currINF) in - let segLen := computeSeqLen(currHF, seg1Len, seg2Len, seg3Len) in - let prevSegLen := computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len) in - let numINF := numInfoFields(seg1Len, seg2Len, seg3Len) in - getSegment(raw, consDir, peer, currHF, prevSegLen, segLen, numINF, currINF) + getSegment(raw, offset, currHFIdx, segLen, asid, ainfo, consDir, peer) } ghost @@ -640,25 +507,9 @@ requires offset + 12 * (seg1Len + seg2Len + seg3Len) <= len(raw) requires 1 <= currINFIdx && currINFIdx < 4 requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases -pure func getLeftSeg2(raw []byte, offset int, currINFIdx int, seg1Len int, seg2Len int, seg3Len int, asid io.IO_as) option[io.IO_seg3] { - return (currINFIdx == 1 && seg2Len > 0) ? some(getCurrSeg2(raw, offset + 12 * seg1Len, currINFIdx, 0, seg2Len, asid)) : - (currINFIdx == 2 && seg3Len > 0) ? some(getCurrSeg2(raw, offset + 12 * (seg1Len + seg2Len), currINFIdx, 0, seg3Len, asid)) : none[io.IO_seg3] -} - -ghost -requires seg1Len > 0 -requires seg2Len >= 0 -requires seg3Len >= 0 -requires 4 + 8 * numInfoFields(seg1Len, seg2Len, seg3Len) + 12 * (seg1Len + seg2Len + seg3Len) == len(raw) -requires 0 <= currINF && currINF < 3 -requires 0 <= currHF && currHF < seg1Len + seg2Len + seg3Len -requires computeSeqLen(currHF, seg1Len, seg2Len, seg3Len) + computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF -requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -decreases -pure func getLeftSeg(raw []byte, currINF int, currHF int, seg1Len int, seg2Len int, seg3Len int) option[io.IO_seg3] { - return let newCurrHF := computeSeqLen(currHF, seg1Len, seg2Len, seg3Len) + computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len) in - (newCurrHF == seg1Len + seg2Len + seg3Len || currINF == 2) ? none[io.IO_seg3] : - some(getCurrSeg(raw, currINF + 1, newCurrHF, seg1Len, seg2Len, seg3Len)) +pure func getLeftSeg(raw []byte, offset int, currINFIdx int, seg1Len int, seg2Len int, seg3Len int, asid io.IO_as) option[io.IO_seg3] { + return (currINFIdx == 1 && seg2Len > 0) ? some(getCurrSeg(raw, offset + 12 * seg1Len, currINFIdx, 0, seg2Len, asid)) : + (currINFIdx == 2 && seg3Len > 0) ? some(getCurrSeg(raw, offset + 12 * (seg1Len + seg2Len), currINFIdx, 0, seg3Len, asid)) : none[io.IO_seg3] } ghost @@ -670,30 +521,9 @@ requires offset + 12 * (seg1Len + seg2Len + seg3Len) <= len(raw) requires -1 <= currINFIdx && currINFIdx < 2 requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases -pure func getRightSeg2(raw []byte, offset int, currINFIdx int, seg1Len int, seg2Len int, seg3Len int, asid io.IO_as) option[io.IO_seg3] { - return (currINFIdx == 1 && seg3Len > 0 && seg2Len > 0) ? some(getCurrSeg2(raw, offset + 12 * seg1Len, currINFIdx, seg2Len, seg2Len, asid)) : - (currINFIdx == 0 && seg2Len > 0) ? some(getCurrSeg2(raw, offset, currINFIdx, seg1Len, seg1Len, asid)) : none[io.IO_seg3] -} - -ghost -requires seg1Len > 0 -requires seg2Len >= 0 -requires seg3Len >= 0 -requires 4 + 8 * numInfoFields(seg1Len, seg2Len, seg3Len) + 12 * (seg1Len + seg2Len + seg3Len) == len(raw) -requires 0 <= currINF && currINF < 3 -requires 0 <= currHF && currHF < seg1Len + seg2Len + seg3Len -requires computeSeqLen(currHF, seg1Len, seg2Len, seg3Len) + computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF -requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -decreases -pure func getRightSeg(raw []byte, currINF int, currHF int, seg1Len int, seg2Len int, seg3Len int) option[io.IO_seg3] { - return (computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len) == 0 || currINF == 0) ? none[io.IO_seg3] : - (let newCurrHF := computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len)-1 in - let consDir := getConsDir(raw, currINF-1) in - let peer := getPeer(raw, currINF-1) in - let segLen := computeSeqLen(newCurrHF, seg1Len, seg2Len, seg3Len) in - let prevSegLen := computePrevSegLen(newCurrHF, seg1Len, seg2Len, seg3Len) in - let numINF := numInfoFields(seg1Len, seg2Len, seg3Len) in - some(getPastSegment(raw, consDir, peer, newCurrHF, prevSegLen, segLen, numINF, currINF))) +pure func getRightSeg(raw []byte, offset int, currINFIdx int, seg1Len int, seg2Len int, seg3Len int, asid io.IO_as) option[io.IO_seg3] { + return (currINFIdx == 1 && seg3Len > 0 && seg2Len > 0) ? some(getCurrSeg(raw, offset + 12 * seg1Len, currINFIdx, seg2Len, seg2Len, asid)) : + (currINFIdx == 0 && seg2Len > 0) ? some(getCurrSeg(raw, offset, currINFIdx, seg1Len, seg1Len, asid)) : none[io.IO_seg3] } ghost @@ -705,29 +535,9 @@ requires offset + 12 * (seg1Len + seg2Len + seg3Len) <= len(raw) requires 2 <= currINFIdx && currINFIdx < 5 requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases -pure func getMidSeg2(raw []byte, offset int, currINFIdx int, seg1Len int, seg2Len int, seg3Len int, asid io.IO_as) option[io.IO_seg3] { - return (currINFIdx == 4 && seg3Len > 0) ? some(getCurrSeg2(raw, offset, 0, seg1Len, seg1Len, asid)) : - (currINFIdx == 2 && seg3Len > 0) ? some(getCurrSeg2(raw, offset + 12 * (seg1Len + seg2Len), currINFIdx, 0, seg3Len, asid)) : none[io.IO_seg3] -} - -ghost -requires seg1Len > 0 -requires seg2Len >= 0 -requires seg3Len >= 0 -requires 4 + 8 * numInfoFields(seg1Len, seg2Len, seg3Len) + 12 * (seg1Len + seg2Len + seg3Len) == len(raw) -requires 0 <= currINF && currINF < 3 -requires 0 <= currHF && currHF < seg1Len + seg2Len + seg3Len -requires computeSeqLen(currHF, seg1Len, seg2Len, seg3Len) + computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len) > currHF -requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -decreases -pure func getMidSeg(raw []byte, currINF int, currHF int, seg1Len int, seg2Len int, seg3Len int) option[io.IO_seg3] { - return seg3Len == 0 ? none[io.IO_seg3] : - (computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len) == seg1Len) ? none[io.IO_seg3] : - (computePrevSegLen(currHF, seg1Len, seg2Len, seg3Len) == 0) ? some(getCurrSeg(raw, 2, seg1Len + seg2Len, seg1Len, seg2Len, seg3Len)) : - (let consDir := getConsDir(raw, 0) in - let peer := getPeer(raw, 0) in - let numINF := numInfoFields(seg1Len, seg2Len, seg3Len) in - some(getPastSegment(raw, consDir, peer, seg1Len-1, 0, seg1Len, numINF, currINF))) +pure func getMidSeg(raw []byte, offset int, currINFIdx int, seg1Len int, seg2Len int, seg3Len int, asid io.IO_as) option[io.IO_seg3] { + return (currINFIdx == 4 && seg3Len > 0) ? some(getCurrSeg(raw, offset, 0, seg1Len, seg1Len, asid)) : + (currINFIdx == 2 && seg3Len > 0) ? some(getCurrSeg(raw, offset + 12 * (seg1Len + seg2Len), currINFIdx, 0, seg3Len, asid)) : none[io.IO_seg3] } ghost @@ -743,7 +553,7 @@ requires unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in 0 <= getSeg3Len(hdr) && 4 + 8 * numInfoFields(int(getSeg1Len(hdr)), int(getSeg2Len(hdr)), int(getSeg3Len(hdr))) + 12 * (int(getSeg1Len(hdr)) + int(getSeg2Len(hdr)) + int(getSeg3Len(hdr))) == len(raw) decreases -pure func getPkt2(raw []byte, asid io.IO_as) io.IO_pkt2{ +pure func getPkt(raw []byte, asid io.IO_as) io.IO_pkt2{ return let hdr := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in binary.BigEndian.Uint32(raw[0:4]) in let currINFIdx := int(getCurrINF(hdr)) in let currHFIdx := int(getCurrHF(hdr)) in @@ -755,38 +565,10 @@ pure func getPkt2(raw []byte, asid io.IO_as) io.IO_pkt2{ let numINF := int(numInfoFields(seg1Len, seg2Len, seg3Len)) in let offset := 4 + 8 * numINF in io.IO_pkt2(io.IO_Packet2{ - CurrSeg : getCurrSeg2(raw, offset+prevSegLen, currINFIdx, currHFIdx-prevSegLen, segLen, asid), // currINFIdx = {0, 1, 2} - LeftSeg : getLeftSeg2(raw, offset, currINFIdx + 1, seg1Len, seg2Len , seg3Len, asid), // currINFIdx = {1, 2, 3} - MidSeg : getMidSeg2(raw, offset, currINFIdx + 2, seg1Len, seg2Len , seg3Len, asid), // currINFIdx = {2, 3, 4} - RightSeg : getRightSeg2(raw, offset, currINFIdx - 1, seg1Len, seg2Len , seg3Len, asid), // currINFIdx = {-1, 0, 1} - }) -} - -//TODO improve preconditions -ghost -requires len(raw) > 4 -requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -requires unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in - let hdr := binary.BigEndian.Uint32(raw[0:4]) in - 0 <= getCurrINF(hdr) && getCurrINF(hdr) < 3 && - 0 <= getCurrHF(hdr) && getCurrHF(hdr) < getSeg1Len(hdr) + getSeg2Len(hdr) + getSeg3Len(hdr) && - 0 < getSeg1Len(hdr) && - 0 <= getSeg2Len(hdr) && - 0 <= getSeg3Len(hdr) && - 4 + 8 * numInfoFields(int(getSeg1Len(hdr)), int(getSeg2Len(hdr)), int(getSeg3Len(hdr))) + 12 * (int(getSeg1Len(hdr)) + int(getSeg2Len(hdr)) + int(getSeg3Len(hdr))) == len(raw) -decreases -pure func getPkt(raw []byte) io.IO_pkt2{ - return let hdr := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in binary.BigEndian.Uint32(raw[0:4]) in - let currINF := getCurrINF(hdr) in - let currHF := getCurrHF(hdr) in - let seg1Len := getSeg1Len(hdr) in - let seg2Len := getSeg2Len(hdr) in - let seg3Len := getSeg3Len(hdr) in - io.IO_pkt2(io.IO_Packet2{ - CurrSeg : getCurrSeg(raw, int(currINF), int(currHF), int(seg1Len), int(seg2Len), int(seg3Len)), - LeftSeg : getLeftSeg(raw, int(currINF), int(currHF), int(seg1Len), int(seg2Len), int(seg3Len)), - MidSeg : getMidSeg(raw, int(currINF), int(currHF), int(seg1Len), int(seg2Len), int(seg3Len)), - RightSeg : getRightSeg(raw, int(currINF), int(currHF), int(seg1Len), int(seg2Len), int(seg3Len)), + CurrSeg : getCurrSeg(raw, offset+prevSegLen, currINFIdx, currHFIdx-prevSegLen, segLen, asid), + LeftSeg : getLeftSeg(raw, offset, currINFIdx + 1, seg1Len, seg2Len , seg3Len, asid), + MidSeg : getMidSeg(raw, offset, currINFIdx + 2, seg1Len, seg2Len , seg3Len, asid), + RightSeg : getRightSeg(raw, offset, currINFIdx - 1, seg1Len, seg2Len , seg3Len, asid), }) } @@ -851,17 +633,24 @@ pure func getTimestamp(raw []byte, offset int) io.IO_ainfo{ io.IO_ainfo(binary.BigEndian.Uint32(raw[idx : idx + 4])) } -// TODO Do we need a body? ghost +requires len(hopfield.HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_) > 0 decreases -pure func computeMsgTerm(raw []byte, start int) io.IO_msgterm +pure func getHVFSet(hopfield io.IO_HF) set[io.IO_msgterm]{ + return let l := hopfield.HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_ in + l[len(l) - 1].MsgTerm_FS_ +} ghost +requires 0 < len(hopfields) +requires 0 <= currHFIdx && currHFIdx <= len(hopfields) +requires forall idx int :: 0 <= idx && idx < len(hopfields) ==> + len(hopfields[idx].HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_) > 0 decreases -pure func computeAInfo(raw []byte, currINF int) io.IO_ainfo - -ghost -decreases -pure func computeUInfo(raw []byte, currINF int) set[io.IO_msgterm] +pure func getUInfo(hopfields seq[io.IO_HF], currHFIdx int, consDir bool) set[io.IO_msgterm]{ + return currHFIdx == len(hopfields) ? getHVFSet(hopfields[currHFIdx-1]) : + currHFIdx == 0 ? getHVFSet(hopfields[currHFIdx]) : + consDir ? getHVFSet(hopfields[currHFIdx]) : getHVFSet(hopfields[currHFIdx-1]) +} /** End of io-spec helper functions **/ \ No newline at end of file From ca581dbeeea4c0c6a26cbf4eba7a35590d9545f3 Mon Sep 17 00:00:00 2001 From: MLETHZ Date: Fri, 28 Jul 2023 12:58:42 +0200 Subject: [PATCH 19/33] improve readability --- router/dataplane_spec.gobra | 90 ++++++++++++++++++++++++++++++------- 1 file changed, 74 insertions(+), 16 deletions(-) diff --git a/router/dataplane_spec.gobra b/router/dataplane_spec.gobra index 73c65c556..c7ccaae51 100644 --- a/router/dataplane_spec.gobra +++ b/router/dataplane_spec.gobra @@ -410,12 +410,21 @@ requires 0 <= currHFIdx && currHFIdx <= segLen requires offset + 12 * segLen <= len(raw) requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) ensures len(res) == segLen - currHFIdx -ensures forall k int :: 0 <= k && k < len(res) ==> +ensures forall k int :: {res[k]} 0 <= k && k < len(res) ==> len(res[k].HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_) > 0 decreases segLen - currHFIdx -pure func getHopfieldsConsDir(raw []byte, offset int, currHFIdx int, segLen int, beta set[io.IO_msgterm], asid io.IO_as, ainfo io.IO_ainfo) (res seq[io.IO_HF]){ +pure func getHopfieldsConsDir( + raw []byte, + offset int, + currHFIdx int, + segLen int, + beta set[io.IO_msgterm], + asid io.IO_as, + ainfo io.IO_ainfo) (res seq[io.IO_HF]){ + return currHFIdx == segLen ? seq[io.IO_HF]{} : - let hf := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getHopField(raw, offset + 12 * currHFIdx, beta, asid, ainfo)) in + let hf := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in + getHopField(raw, offset + 12 * currHFIdx, beta, asid, ainfo)) in seq[io.IO_HF]{hf} ++ getHopfieldsConsDir(raw, offset, currHFIdx + 1, segLen, (beta union set[io.IO_msgterm]{hf.HVF}), asid, ainfo) } @@ -425,12 +434,20 @@ requires -1 <= currHFIdx requires offset + 12 * currHFIdx + 12 <= len(raw) requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) ensures len(res) == currHFIdx + 1 -ensures forall k int :: 0 <= k && k < len(res) ==> +ensures forall k int :: {res[k]} 0 <= k && k < len(res) ==> len(res[k].HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_) > 0 decreases currHFIdx + 1 -pure func getHopfieldsNotConsDir(raw []byte, offset int, currHFIdx int, beta set[io.IO_msgterm], asid io.IO_as, ainfo io.IO_ainfo) (res seq[io.IO_HF]){ +pure func getHopfieldsNotConsDir( + raw []byte, + offset int, + currHFIdx int, + beta set[io.IO_msgterm], + asid io.IO_as, + ainfo io.IO_ainfo) (res seq[io.IO_HF]){ + return currHFIdx == -1 ? seq[io.IO_HF]{} : - let hf := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getHopField(raw, offset + 12 * currHFIdx, beta, asid, ainfo)) in + let hf := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in + getHopField(raw, offset + 12 * currHFIdx, beta, asid, ainfo)) in getHopfieldsNotConsDir(raw, offset, currHFIdx -1, (beta union set[io.IO_msgterm]{hf.HVF}), asid, ainfo) ++ seq[io.IO_HF]{hf} } @@ -466,7 +483,15 @@ requires offset + 12 * segLen <= len(raw) requires 0 <= currHFIdx && currHFIdx <= segLen requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases -pure func getSegment(raw []byte, offset int, currHFIdx int, segLen int, asid io.IO_as, ainfo io.IO_ainfo, consDir bool, peer bool) io.IO_seg2{ +pure func getSegment(raw []byte, + offset int, + currHFIdx int, + segLen int, + asid io.IO_as, + ainfo io.IO_ainfo, + consDir bool, + peer bool) io.IO_seg2{ + return let hopfields := consDir ? getHopfieldsConsDir(raw, offset, 0, segLen, set[io.IO_msgterm]{}, asid, ainfo) : getHopfieldsNotConsDir(raw, offset, segLen - 1, set[io.IO_msgterm]{}, asid, ainfo) in @@ -507,9 +532,20 @@ requires offset + 12 * (seg1Len + seg2Len + seg3Len) <= len(raw) requires 1 <= currINFIdx && currINFIdx < 4 requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases -pure func getLeftSeg(raw []byte, offset int, currINFIdx int, seg1Len int, seg2Len int, seg3Len int, asid io.IO_as) option[io.IO_seg3] { - return (currINFIdx == 1 && seg2Len > 0) ? some(getCurrSeg(raw, offset + 12 * seg1Len, currINFIdx, 0, seg2Len, asid)) : - (currINFIdx == 2 && seg3Len > 0) ? some(getCurrSeg(raw, offset + 12 * (seg1Len + seg2Len), currINFIdx, 0, seg3Len, asid)) : none[io.IO_seg3] +pure func getLeftSeg( + raw []byte, + offset int, + currINFIdx int, + seg1Len int, + seg2Len int, + seg3Len int, + asid io.IO_as) option[io.IO_seg3] { + + return (currINFIdx == 1 && seg2Len > 0) ? + some(getCurrSeg(raw, offset + 12 * seg1Len, currINFIdx, 0, seg2Len, asid)) : + (currINFIdx == 2 && seg3Len > 0) ? + some(getCurrSeg(raw, offset + 12 * (seg1Len + seg2Len), currINFIdx, 0, seg3Len, asid)) : + none[io.IO_seg3] } ghost @@ -521,9 +557,20 @@ requires offset + 12 * (seg1Len + seg2Len + seg3Len) <= len(raw) requires -1 <= currINFIdx && currINFIdx < 2 requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases -pure func getRightSeg(raw []byte, offset int, currINFIdx int, seg1Len int, seg2Len int, seg3Len int, asid io.IO_as) option[io.IO_seg3] { - return (currINFIdx == 1 && seg3Len > 0 && seg2Len > 0) ? some(getCurrSeg(raw, offset + 12 * seg1Len, currINFIdx, seg2Len, seg2Len, asid)) : - (currINFIdx == 0 && seg2Len > 0) ? some(getCurrSeg(raw, offset, currINFIdx, seg1Len, seg1Len, asid)) : none[io.IO_seg3] +pure func getRightSeg( + raw []byte, + offset int, + currINFIdx int, + seg1Len int, + seg2Len int, + seg3Len int, + asid io.IO_as) option[io.IO_seg3] { + + return (currINFIdx == 1 && seg3Len > 0 && seg2Len > 0) ? + some(getCurrSeg(raw, offset + 12 * seg1Len, currINFIdx, seg2Len, seg2Len, asid)) : + (currINFIdx == 0 && seg2Len > 0) ? + some(getCurrSeg(raw, offset, currINFIdx, seg1Len, seg1Len, asid)) : + none[io.IO_seg3] } ghost @@ -535,9 +582,20 @@ requires offset + 12 * (seg1Len + seg2Len + seg3Len) <= len(raw) requires 2 <= currINFIdx && currINFIdx < 5 requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases -pure func getMidSeg(raw []byte, offset int, currINFIdx int, seg1Len int, seg2Len int, seg3Len int, asid io.IO_as) option[io.IO_seg3] { - return (currINFIdx == 4 && seg3Len > 0) ? some(getCurrSeg(raw, offset, 0, seg1Len, seg1Len, asid)) : - (currINFIdx == 2 && seg3Len > 0) ? some(getCurrSeg(raw, offset + 12 * (seg1Len + seg2Len), currINFIdx, 0, seg3Len, asid)) : none[io.IO_seg3] +pure func getMidSeg( + raw []byte, + offset int, + currINFIdx int, + seg1Len int, + seg2Len int, + seg3Len int, + asid io.IO_as) option[io.IO_seg3] { + + return (currINFIdx == 4 && seg3Len > 0) ? + some(getCurrSeg(raw, offset, 0, seg1Len, seg1Len, asid)) : + (currINFIdx == 2 && seg3Len > 0) ? + some(getCurrSeg(raw, offset + 12 * (seg1Len + seg2Len), currINFIdx, 0, seg3Len, asid)) : + none[io.IO_seg3] } ghost From bfd6c2fe84b1cda223d84e3841ec9e2c7e3c9dfb Mon Sep 17 00:00:00 2001 From: mlimbeck Date: Wed, 1 Nov 2023 13:58:28 +0100 Subject: [PATCH 20/33] rename of function lengthOfCurrSeg --- router/dataplane_spec.gobra | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/router/dataplane_spec.gobra b/router/dataplane_spec.gobra index f9cb1e5ed..c90510352 100644 --- a/router/dataplane_spec.gobra +++ b/router/dataplane_spec.gobra @@ -357,7 +357,7 @@ requires 0 <= seg2Len requires 0 <= seg3Len requires currHF < seg1Len + seg2Len + seg3Len decreases -pure func computeSeqLen(currHF int, seg1Len int, seg2Len int, seg3Len int) int{ +pure func lengthOfCurrSeg(currHF int, seg1Len int, seg2Len int, seg3Len int) int{ return seg1Len > currHF ? seg1Len : ((seg1Len + seg2Len) > currHF ? seg2Len : seg3Len) } @@ -620,7 +620,7 @@ pure func getPkt(raw []byte, asid io.IO_as) io.IO_pkt2{ let seg1Len := int(getSeg1Len(hdr)) in let seg2Len := int(getSeg2Len(hdr)) in let seg3Len := int(getSeg3Len(hdr)) in - let segLen := computeSeqLen(currHFIdx, seg1Len, seg2Len, seg3Len) in + let segLen := lengthOfCurrSeg(currHFIdx, seg1Len, seg2Len, seg3Len) in let prevSegLen := computePrevSegLen(currHFIdx, seg1Len, seg2Len, seg3Len) in let numINF := int(numInfoFields(seg1Len, seg2Len, seg3Len)) in let offset := 4 + 8 * numINF in From f1cf0b122358676e5b01e8b08052e096f2cb61f3 Mon Sep 17 00:00:00 2001 From: mlimbeck Date: Thu, 16 Nov 2023 11:51:40 +0100 Subject: [PATCH 21/33] extract asid-seqence from raw pkt --- router/dataplane_spec.gobra | 308 ++++++++++++++++++++++++++++++------ 1 file changed, 256 insertions(+), 52 deletions(-) diff --git a/router/dataplane_spec.gobra b/router/dataplane_spec.gobra index cb17c5129..c4a639cff 100644 --- a/router/dataplane_spec.gobra +++ b/router/dataplane_spec.gobra @@ -23,7 +23,6 @@ import ( sl "github.com/scionproto/scion/verification/utils/slices" "github.com/scionproto/scion/verification/io" "github.com/scionproto/scion/verification/dependencies/encoding/binary" - "github.com/scionproto/scion/verification/utils/bitwise" "github.com/scionproto/scion/pkg/scrypto" "github.com/scionproto/scion/pkg/addr" ) @@ -275,37 +274,218 @@ func closureSpec3(c BatchConn) /** Start of io-spec helper functions **/ ghost -requires 0 < seg1Len -requires 0 <= seg2Len -requires 0 <= seg3Len -requires currHF < seg1Len + seg2Len + seg3Len -decreases -pure func lengthOfCurrSeg(currHF int, seg1Len int, seg2Len int, seg3Len int) int{ - return seg1Len > currHF ? seg1Len : ((seg1Len + seg2Len) > currHF ? seg2Len : seg3Len) +decreases +pure func numInfoFields(seg1Len int, seg2Len int, seg3Len int) int { + return seg3Len > 0 ? 3 : (seg2Len > 0 ? 2 : 1) } ghost decreases -pure func infoFieldOffsetSeg(currINF int) int{ +pure func infoFieldOffset(currINF int) int { return 4 + 8 * currINF } ghost -decreases -pure func numInfoFields(seg1Len int, seg2Len int, seg3Len int) int { - return seg3Len > 0 ? 3 : (seg2Len > 0 ? 2 : 1) +decreases +pure func hopFieldOffset(numINF int, currHF int) int { + return 4 + 8*numINF + 12 * currHF +} + + +ghost +decreases +pure func lengthOfCurrSeg(currHF int, seg1Len int, seg2Len int, seg3Len int) int{ + return seg1Len > currHF ? seg1Len : ((seg1Len + seg2Len) > currHF ? seg2Len : seg3Len) } ghost -requires 0 < seg1Len -requires 0 <= seg2Len -requires 0 <= seg3Len requires 0 <= currHF ensures res <= currHF decreases -pure func computePrevSegLen(currHF int, seg1Len int, seg2Len int, seg3Len int) (res int){ +pure func lengthOfPrevSeg(currHF int, seg1Len int, seg2Len int, seg3Len int) (res int){ return seg1Len > currHF ? 0 : ((seg1Len + seg2Len) > currHF ? seg1Len : seg1Len + seg2Len) } +/* +ghost +requires 1 <= numINF && numINF <= 3 +requires 0 <= currHFIdx +requires hopFieldOffset(numINF, currHFIdx) + 12 <= len(raw) +requires dp.Valid() +requires let idx := hopFieldOffset(numINF, currHFIdx) in + acc(&raw[idx+4], _) && acc(&raw[idx+5], _) +decreases +pure func getAsidFromEgress(dp io.DataPlaneSpec, raw []byte, numINF int, currHFIdx int, asid io.IO_as) option[io.IO_as] { + return let idx := hopFieldOffset(numINF, currHFIdx) in + let consEgress := binary.BigEndian.Uint16(raw[idx+4:idx+6]) in + let outgoingPair := io.AsIfsPair{asid, io.IO_ifs(consEgress)} in + (io.AsIfsPair{asid, io.IO_ifs(consEgress)} in domain(dp.GetLinks()) ? + some(dp.Lookup(outgoingPair).asid) : none[io.IO_as]) +} + +ghost +requires 1 <= numINF && numINF <= 3 +requires 0 <= currHFIdx +requires hopFieldOffset(numINF, currHFIdx) + 12 <= len(raw) +requires dp.Valid() +requires let idx := hopFieldOffset(numINF, currHFIdx) in + acc(&raw[idx+2], _) && acc(&raw[idx+3], _) +decreases +pure func getAsidFromIngress(dp io.DataPlaneSpec, raw []byte, numINF int, currHFIdx int, asid io.IO_as) option[io.IO_as] { + return let idx := hopFieldOffset(numINF, currHFIdx) in + let consIngress := binary.BigEndian.Uint16(raw[idx+2:idx+4]) in + let incommingPair := io.AsIfsPair{asid, io.IO_ifs(consIngress)} in + (io.AsIfsPair{asid, io.IO_ifs(consIngress)} in domain(dp.GetLinks()) ? + some(dp.Lookup(incommingPair).asid) : none[io.IO_as]) +} +*/ +ghost +requires 1 <= numINF +requires 0 <= currHFIdx +requires hopFieldOffset(numINF, currHFIdx) + 12 <= len(raw) +requires dp.Valid() +requires let idx := hopFieldOffset(numINF, currHFIdx) in + acc(&raw[idx+2], _) && acc(&raw[idx+3], _) && acc(&raw[idx+4], _) && acc(&raw[idx+5], _) +decreases +pure func getAsidFromIfs(dp io.DataPlaneSpec, raw []byte, numINF int, currHFIdx int, consDir bool, asid io.IO_as) (res option[io.IO_as]) { + return let idx := hopFieldOffset(numINF, currHFIdx) in + let ifs := consDir ? binary.BigEndian.Uint16(raw[idx+4:idx+6]) : binary.BigEndian.Uint16(raw[idx+2:idx+4]) in + let asIfPair := io.AsIfsPair{asid, io.IO_ifs(ifs)} in + (asIfPair in domain(dp.GetLinks()) ? + some(dp.Lookup(asIfPair).asid) : none[io.IO_as]) +} + +ghost +requires 1 <= numINF +requires 0 <= prevSegLen && prevSegLen <= currHFIdx +requires hopFieldOffset(numINF, currHFIdx) + 12 <= len(raw) +requires dp.Valid() +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +ensures res != none[seq[io.IO_as]] ==> len(get(res)) == currHFIdx - prevSegLen + 1 +decreases currHFIdx - prevSegLen +pure func getAsidsBefore(dp io.DataPlaneSpec, raw []byte, numINF int, currHFIdx int, prevSegLen int, consDir bool, asid io.IO_as) (res option[seq[io.IO_as]]) { + return let next_asid := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getAsidFromIfs(dp, raw, numINF, currHFIdx, !consDir, asid)) in + match next_asid{ + case none[io.IO_as]: + none[seq[io.IO_as]] + default: + currHFIdx == prevSegLen ? some(seq[io.IO_as]{get(next_asid)}) : + let next_asid_seq := getAsidsBefore(dp, raw, numINF, currHFIdx-1, prevSegLen, consDir, get(next_asid)) in + match next_asid_seq{ + case none[seq[io.IO_as]]: + none[seq[io.IO_as]] + default: + some(get(next_asid_seq) ++ seq[io.IO_as]{get(next_asid)}) + } + } +} + +ghost +requires 1 <= numINF +requires 0 <= currHFIdx && currHFIdx < segLen +requires hopFieldOffset(numINF, segLen) <= len(raw) +requires dp.Valid() +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +ensures res != none[seq[io.IO_as]] ==> len(get(res)) == segLen - currHFIdx +decreases segLen - currHFIdx + 1 +pure func getAsidsAfter(dp io.DataPlaneSpec, raw []byte, numINF int, currHFIdx int, segLen int, consDir bool, asid io.IO_as) (res option[seq[io.IO_as]]) { + return let next_asid := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getAsidFromIfs(dp, raw, numINF, currHFIdx, consDir, asid)) in + match next_asid{ + case none[io.IO_as]: + none[seq[io.IO_as]] + default: + currHFIdx == segLen - 1 ? some(seq[io.IO_as]{get(next_asid)}) : + let next_asid_seq := getAsidsAfter(dp, raw, numINF, currHFIdx+1, segLen, consDir, get(next_asid)) in + match next_asid_seq{ + case none[seq[io.IO_as]]: + none[seq[io.IO_as]] + default: + some(seq[io.IO_as]{get(next_asid)} ++ get(next_asid_seq)) + } + } +} + +ghost +requires 1 <= numINF +requires 0 <= prevSegLen && prevSegLen <= currHFIdx +requires currHFIdx < segLen +requires hopFieldOffset(numINF, segLen) <= len(raw) +requires dp.Valid() +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +ensures res != none[seq[io.IO_as]] ==> len(get(res)) == segLen - prevSegLen +decreases +pure func getAsidSeq(dp io.DataPlaneSpec, raw []byte, numINF int, currHFIdx int, segLen int, prevSegLen int, consDir bool, asid io.IO_as) (res option[seq[io.IO_as]]) { + return segLen == 0 ? some(seq[io.IO_as]{}) : + let left := getAsidsBefore(dp, raw, numINF, currHFIdx, prevSegLen, consDir, asid) in + let right := getAsidsAfter(dp, raw, numINF, currHFIdx, segLen, consDir, asid) in + (left == none[seq[io.IO_as]] || right == none[seq[io.IO_as]]) ? none[seq[io.IO_as]] : + some(get(left) ++ get(right)[1:]) +} + +ghost +requires dp.Valid() +requires 1 <= numINF +requires 0 < seg1Len +requires 0 <= seg2Len +requires 0 <= seg3Len +requires hopFieldOffset(numINF, seg1Len + seg2Len + seg3Len) <= len(raw) +requires currINFIdx <= numINF + 1 +requires 1 <= currINFIdx && currINFIdx < 4 +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +decreases +pure func getAsidsLeft(dp io.DataPlaneSpec, raw []byte, numINF int, currINFIdx int, seg1Len int, seg2Len int, seg3Len int, asid io.IO_as) (res option[seq[io.IO_as]]){ + return let consDir := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getConsDir(raw, currINFIdx) in + (currINFIdx == 1 && seg2Len > 0) ? + getAsidSeq(dp, raw, numINF, seg1Len, seg1Len+seg2Len, seg1Len, consDir, asid) : + (currINFIdx == 2 && seg2Len > 0 && seg3Len > 0) ? + getAsidSeq(dp, raw, numINF, seg1Len+seg2Len, seg1Len+seg2Len+seg3Len, seg1Len+seg2Len, consDir, asid) : + some(seq[io.IO_as]{}) +} + +ghost +requires dp.Valid() +requires 1 <= numINF +requires 0 < seg1Len +requires 0 <= seg2Len +requires 0 <= seg3Len +requires hopFieldOffset(numINF, seg1Len + seg2Len + seg3Len) <= len(raw) +requires currINFIdx <= numINF + 1 +requires -1 <= currINFIdx && currINFIdx < 2 +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +ensures (currINFIdx == 0 && res != none[seq[io.IO_as]]) ==> len(get(res)) == seg1Len +ensures (currINFIdx == 1 && seg2Len > 0 && res != none[seq[io.IO_as]]) ==> len(get(res)) == seg2Len +decreases +pure func getAsidsRight(dp io.DataPlaneSpec, raw []byte, numINF int, currINFIdx int, seg1Len int, seg2Len int, seg3Len int, asid io.IO_as) (res option[seq[io.IO_as]]){ + return (currINFIdx == 1 && seg2Len > 0) ? + let consDir := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getConsDir(raw, currINFIdx) in + getAsidSeq(dp, raw, numINF, seg1Len+seg2Len-1, seg1Len+seg2Len, seg1Len, consDir, asid) : + (currINFIdx == 0) ? + let consDir := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getConsDir(raw, currINFIdx) in + getAsidSeq(dp, raw, numINF, seg1Len-1, seg1Len, 0, consDir, asid) : + some(seq[io.IO_as]{}) +} + +ghost +requires dp.Valid() +requires 1 <= numINF +requires 0 < seg1Len +requires 0 <= seg2Len +requires 0 <= seg3Len +requires hopFieldOffset(numINF, seg1Len + seg2Len + seg3Len) <= len(raw) +requires currINFIdx <= numINF + 1 +requires 2 <= currINFIdx && currINFIdx < 5 +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +requires (currINFIdx == 4 && seg2Len > 0) ==> asid != none[io.IO_as] +requires (currINFIdx == 2 && seg2Len > 0 && seg3Len > 0) ==> asid != none[io.IO_as] +decreases +pure func getAsidsMid(dp io.DataPlaneSpec, raw []byte, numINF int, currINFIdx int, seg1Len int, seg2Len int, seg3Len int, asid option[io.IO_as]) (res option[seq[io.IO_as]]){ + return (currINFIdx == 4 && seg2Len > 0) ? + let consDir := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getConsDir(raw, 1) in + getAsidSeq(dp, raw, numINF, seg1Len-1, seg1Len, 0, consDir, get(asid)) : + (currINFIdx == 2 && seg2Len > 0 && seg3Len > 0) ? + let consDir := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getConsDir(raw, 2) in + getAsidSeq(dp, raw, numINF, seg1Len + seg2Len, seg1Len + seg2Len + seg3Len, seg1Len + seg2Len, consDir, get(asid)) : + some(seq[io.IO_as]{}) +} ghost requires idx + 12 <= len(raw) @@ -334,6 +514,7 @@ requires 0 <= offset requires 0 <= currHFIdx && currHFIdx <= segLen requires offset + 12 * segLen <= len(raw) requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +requires len(asid) == segLen ensures len(res) == segLen - currHFIdx ensures forall k int :: {res[k]} 0 <= k && k < len(res) ==> len(res[k].HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_) > 0 @@ -344,20 +525,21 @@ pure func getHopfieldsConsDir( currHFIdx int, segLen int, beta set[io.IO_msgterm], - asid io.IO_as, + asid seq[io.IO_as], ainfo io.IO_ainfo) (res seq[io.IO_HF]){ return currHFIdx == segLen ? seq[io.IO_HF]{} : let hf := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in - getHopField(raw, offset + 12 * currHFIdx, beta, asid, ainfo)) in + getHopField(raw, offset + 12 * currHFIdx, beta, asid[currHFIdx], ainfo)) in seq[io.IO_HF]{hf} ++ getHopfieldsConsDir(raw, offset, currHFIdx + 1, segLen, (beta union set[io.IO_msgterm]{hf.HVF}), asid, ainfo) } ghost requires 0 <= offset -requires -1 <= currHFIdx +requires -1 <= currHFIdx && currHFIdx < segLen requires offset + 12 * currHFIdx + 12 <= len(raw) requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +requires len(asid) == segLen ensures len(res) == currHFIdx + 1 ensures forall k int :: {res[k]} 0 <= k && k < len(res) ==> len(res[k].HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_) > 0 @@ -366,14 +548,15 @@ pure func getHopfieldsNotConsDir( raw []byte, offset int, currHFIdx int, + segLen int, beta set[io.IO_msgterm], - asid io.IO_as, + asid seq[io.IO_as], ainfo io.IO_ainfo) (res seq[io.IO_HF]){ return currHFIdx == -1 ? seq[io.IO_HF]{} : let hf := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in - getHopField(raw, offset + 12 * currHFIdx, beta, asid, ainfo)) in - getHopfieldsNotConsDir(raw, offset, currHFIdx -1, (beta union set[io.IO_msgterm]{hf.HVF}), asid, ainfo) ++ seq[io.IO_HF]{hf} + getHopField(raw, offset + 12 * currHFIdx, beta, asid[currHFIdx], ainfo)) in + getHopfieldsNotConsDir(raw, offset, currHFIdx -1, segLen, (beta union set[io.IO_msgterm]{hf.HVF}), asid, ainfo) ++ seq[io.IO_HF]{hf} } ghost @@ -406,20 +589,21 @@ requires 0 <= offset requires 0 < segLen requires offset + 12 * segLen <= len(raw) requires 0 <= currHFIdx && currHFIdx <= segLen +requires len(asid) == segLen requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases pure func getSegment(raw []byte, offset int, currHFIdx int, segLen int, - asid io.IO_as, + asid seq[io.IO_as], ainfo io.IO_ainfo, consDir bool, peer bool) io.IO_seg2{ return let hopfields := consDir ? getHopfieldsConsDir(raw, offset, 0, segLen, set[io.IO_msgterm]{}, asid, ainfo) : - getHopfieldsNotConsDir(raw, offset, segLen - 1, set[io.IO_msgterm]{}, asid, ainfo) in + getHopfieldsNotConsDir(raw, offset, segLen - 1, segLen, set[io.IO_msgterm]{}, asid, ainfo) in let uinfo := getUInfo(hopfields, currHFIdx, consDir) in io.IO_seg2(io.IO_seg3_{ AInfo :ainfo, @@ -438,9 +622,10 @@ requires 0 < segLen requires offset + 12 * segLen <= len(raw) requires 0 <= currHFIdx && currHFIdx <= segLen requires 0 <= currINFIdx && currINFIdx < 3 +requires len(asid) == segLen requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases -pure func getCurrSeg(raw []byte, offset int, currINFIdx int, currHFIdx int, segLen int, asid io.IO_as) io.IO_seg3 { +pure func getCurrSeg(raw []byte, offset int, currINFIdx int, currHFIdx int, segLen int, asid seq[io.IO_as]) io.IO_seg3 { return unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in let ainfo := getTimestamp(raw, currINFIdx) in let consDir := getConsDir(raw, currINFIdx) in @@ -455,6 +640,8 @@ requires 0 <= seg3Len requires 4 + 8 * numInfoFields(seg1Len, seg2Len, seg3Len) == offset requires offset + 12 * (seg1Len + seg2Len + seg3Len) <= len(raw) requires 1 <= currINFIdx && currINFIdx < 4 +requires (currINFIdx == 1 && seg2Len > 0) ==> len(asid) == seg2Len +requires (currINFIdx == 2 && seg2Len > 0 && seg3Len > 0) ==> len(asid) == seg3Len requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases pure func getLeftSeg( @@ -464,11 +651,11 @@ pure func getLeftSeg( seg1Len int, seg2Len int, seg3Len int, - asid io.IO_as) option[io.IO_seg3] { + asid seq[io.IO_as]) option[io.IO_seg3] { return (currINFIdx == 1 && seg2Len > 0) ? some(getCurrSeg(raw, offset + 12 * seg1Len, currINFIdx, 0, seg2Len, asid)) : - (currINFIdx == 2 && seg3Len > 0) ? + (currINFIdx == 2 && seg2Len > 0 && seg3Len > 0) ? some(getCurrSeg(raw, offset + 12 * (seg1Len + seg2Len), currINFIdx, 0, seg3Len, asid)) : none[io.IO_seg3] } @@ -480,6 +667,8 @@ requires 0 <= seg3Len requires 4 + 8 * numInfoFields(seg1Len, seg2Len, seg3Len) == offset requires offset + 12 * (seg1Len + seg2Len + seg3Len) <= len(raw) requires -1 <= currINFIdx && currINFIdx < 2 +requires (currINFIdx == 1 && seg2Len > 0 && seg3Len > 0) ==> len(asid) == seg2Len +requires (currINFIdx == 0 && seg2Len > 0) ==> len(asid) == seg1Len requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases pure func getRightSeg( @@ -489,9 +678,9 @@ pure func getRightSeg( seg1Len int, seg2Len int, seg3Len int, - asid io.IO_as) option[io.IO_seg3] { + asid seq[io.IO_as]) option[io.IO_seg3] { - return (currINFIdx == 1 && seg3Len > 0 && seg2Len > 0) ? + return (currINFIdx == 1 && seg2Len > 0 && seg3Len > 0) ? some(getCurrSeg(raw, offset + 12 * seg1Len, currINFIdx, seg2Len, seg2Len, asid)) : (currINFIdx == 0 && seg2Len > 0) ? some(getCurrSeg(raw, offset, currINFIdx, seg1Len, seg1Len, asid)) : @@ -505,6 +694,8 @@ requires 0 <= seg3Len requires 4 + 8 * numInfoFields(seg1Len, seg2Len, seg3Len) == offset requires offset + 12 * (seg1Len + seg2Len + seg3Len) <= len(raw) requires 2 <= currINFIdx && currINFIdx < 5 +requires (currINFIdx == 4) ==> len(asid) == seg1Len +requires (currINFIdx == 2 && seg2Len > 0 && seg3Len > 0) ==> len(asid) == seg3Len requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases pure func getMidSeg( @@ -514,16 +705,17 @@ pure func getMidSeg( seg1Len int, seg2Len int, seg3Len int, - asid io.IO_as) option[io.IO_seg3] { + asid seq[io.IO_as]) option[io.IO_seg3] { - return (currINFIdx == 4 && seg3Len > 0) ? + return (currINFIdx == 4) ? some(getCurrSeg(raw, offset, 0, seg1Len, seg1Len, asid)) : - (currINFIdx == 2 && seg3Len > 0) ? + (currINFIdx == 2 && seg2Len > 0 && seg3Len > 0) ? some(getCurrSeg(raw, offset + 12 * (seg1Len + seg2Len), currINFIdx, 0, seg3Len, asid)) : none[io.IO_seg3] } ghost +requires dp.Valid() requires len(raw) > 4 requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) requires unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in @@ -536,7 +728,7 @@ requires unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in 0 <= getSeg3Len(hdr) && 4 + 8 * numInfoFields(int(getSeg1Len(hdr)), int(getSeg2Len(hdr)), int(getSeg3Len(hdr))) + 12 * (int(getSeg1Len(hdr)) + int(getSeg2Len(hdr)) + int(getSeg3Len(hdr))) == len(raw) decreases -pure func getPkt(raw []byte, asid io.IO_as) io.IO_pkt2{ +pure func getPkt(dp io.DataPlaneSpec, raw []byte, asid io.IO_as) option[io.IO_pkt2]{ return let hdr := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in binary.BigEndian.Uint32(raw[0:4]) in let currINFIdx := int(getCurrINF(hdr)) in let currHFIdx := int(getCurrHF(hdr)) in @@ -544,15 +736,27 @@ pure func getPkt(raw []byte, asid io.IO_as) io.IO_pkt2{ let seg2Len := int(getSeg2Len(hdr)) in let seg3Len := int(getSeg3Len(hdr)) in let segLen := lengthOfCurrSeg(currHFIdx, seg1Len, seg2Len, seg3Len) in - let prevSegLen := computePrevSegLen(currHFIdx, seg1Len, seg2Len, seg3Len) in + let prevSegLen := lengthOfPrevSeg(currHFIdx, seg1Len, seg2Len, seg3Len) in let numINF := int(numInfoFields(seg1Len, seg2Len, seg3Len)) in let offset := 4 + 8 * numINF in - io.IO_pkt2(io.IO_Packet2{ - CurrSeg : getCurrSeg(raw, offset+prevSegLen, currINFIdx, currHFIdx-prevSegLen, segLen, asid), - LeftSeg : getLeftSeg(raw, offset, currINFIdx + 1, seg1Len, seg2Len , seg3Len, asid), - MidSeg : getMidSeg(raw, offset, currINFIdx + 2, seg1Len, seg2Len , seg3Len, asid), - RightSeg : getRightSeg(raw, offset, currINFIdx - 1, seg1Len, seg2Len , seg3Len, asid), - }) + let consDir := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getConsDir(raw, currINFIdx) in + let currAsidSeq := getAsidSeq(dp, raw, numINF, currHFIdx, prevSegLen+segLen, prevSegLen, consDir, dp.Asid()) in + currAsidSeq == none[seq[io.IO_as]] ? none[io.IO_pkt2] : + let last := get(currAsidSeq)[segLen-1] in + let first := get(currAsidSeq)[0] in + let leftAsidSeq := getAsidsLeft(dp, raw, numINF, currINFIdx + 1, seg1Len, seg2Len, seg3Len, last) in + let rightAsidSeq := getAsidsRight(dp, raw, numINF, currINFIdx - 1, seg1Len, seg2Len, seg3Len, first) in + (leftAsidSeq == none[seq[io.IO_as]] || rightAsidSeq == none[seq[io.IO_as]]) ? none[io.IO_pkt2] : + let midAsid := ((currINFIdx == 0 && seg2Len > 0 && seg3Len > 0) ? some(get(leftAsidSeq)[len(get(leftAsidSeq))-1]) : + (currINFIdx == 2 && seg2Len > 0) ? some(get(rightAsidSeq)[0]) : none[io.IO_as]) in + let midAsidSeq := getAsidsMid(dp, raw, numINF, currINFIdx + 2, seg1Len, seg2Len, seg3Len, midAsid) in + midAsidSeq == none[seq[io.IO_as]] ? none[io.IO_pkt2] : + some(io.IO_pkt2(io.IO_Packet2{ + CurrSeg : getCurrSeg(raw, offset+prevSegLen, currINFIdx, currHFIdx-prevSegLen, segLen, get(currAsidSeq)), + LeftSeg : getLeftSeg(raw, offset, currINFIdx + 1, seg1Len, seg2Len , seg3Len, get(leftAsidSeq)), + MidSeg : none[io.IO_seg3],// getMidSeg(raw, offset, currINFIdx + 2, seg1Len, seg2Len , seg3Len, get(midAsidSeq)), + RightSeg : getRightSeg(raw, offset, currINFIdx - 1, seg1Len, seg2Len , seg3Len, get(rightAsidSeq)), + })) } ghost @@ -587,32 +791,32 @@ pure func getSeg3Len(hdr uint32) uint8{ ghost requires 0 <= offset -requires infoFieldOffsetSeg(offset) < len(raw) -requires acc(&raw[infoFieldOffsetSeg(offset)], _) +requires infoFieldOffset(offset) < len(raw) +requires acc(&raw[infoFieldOffset(offset)], _) decreases pure func getConsDir(raw []byte, offset int) bool{ - return raw[infoFieldOffsetSeg(offset)] & 0x1 == 0x1 + return raw[infoFieldOffset(offset)] & 0x1 == 0x1 } ghost requires 0 <= offset -requires infoFieldOffsetSeg(offset) < len(raw) -requires acc(&raw[infoFieldOffsetSeg(offset)], _) +requires infoFieldOffset(offset) < len(raw) +requires acc(&raw[infoFieldOffset(offset)], _) decreases pure func getPeer(raw []byte, offset int) bool{ - return raw[infoFieldOffsetSeg(offset)] & 0x2 == 0x2 + return raw[infoFieldOffset(offset)] & 0x2 == 0x2 } ghost requires 0 <= offset -requires infoFieldOffsetSeg(offset) + 8 < len(raw) -requires acc(&raw[infoFieldOffsetSeg(offset) + 4], _) -requires acc(&raw[infoFieldOffsetSeg(offset) + 5], _) -requires acc(&raw[infoFieldOffsetSeg(offset) + 6], _) -requires acc(&raw[infoFieldOffsetSeg(offset) + 7], _) +requires infoFieldOffset(offset) + 8 < len(raw) +requires acc(&raw[infoFieldOffset(offset) + 4], _) +requires acc(&raw[infoFieldOffset(offset) + 5], _) +requires acc(&raw[infoFieldOffset(offset) + 6], _) +requires acc(&raw[infoFieldOffset(offset) + 7], _) decreases pure func getTimestamp(raw []byte, offset int) io.IO_ainfo{ - return let idx := infoFieldOffsetSeg(offset) + 4 in + return let idx := infoFieldOffset(offset) + 4 in io.IO_ainfo(binary.BigEndian.Uint32(raw[idx : idx + 4])) } From 4343478e3082a96b4fe8d1abbc7f282e4fc1f5c7 Mon Sep 17 00:00:00 2001 From: mlimbeck Date: Thu, 16 Nov 2023 12:09:16 +0100 Subject: [PATCH 22/33] missing trigger --- router/dataplane_spec.gobra | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/router/dataplane_spec.gobra b/router/dataplane_spec.gobra index c4a639cff..b086cfc1a 100644 --- a/router/dataplane_spec.gobra +++ b/router/dataplane_spec.gobra @@ -831,7 +831,7 @@ pure func getHVFSet(hopfield io.IO_HF) set[io.IO_msgterm]{ ghost requires 0 < len(hopfields) requires 0 <= currHFIdx && currHFIdx <= len(hopfields) -requires forall idx int :: 0 <= idx && idx < len(hopfields) ==> +requires forall idx int :: {hopfields[idx]} 0 <= idx && idx < len(hopfields) ==> len(hopfields[idx].HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_) > 0 decreases pure func getUInfo(hopfields seq[io.IO_HF], currHFIdx int, consDir bool) set[io.IO_msgterm]{ From 715fa51fc20c1a56d1a42816601c09ff623091a6 Mon Sep 17 00:00:00 2001 From: mlimbeck Date: Thu, 16 Nov 2023 21:22:58 +0100 Subject: [PATCH 23/33] quick fix --- router/dataplane_spec.gobra | 38 +++---------------------------------- 1 file changed, 3 insertions(+), 35 deletions(-) diff --git a/router/dataplane_spec.gobra b/router/dataplane_spec.gobra index b086cfc1a..6252a023f 100644 --- a/router/dataplane_spec.gobra +++ b/router/dataplane_spec.gobra @@ -305,39 +305,7 @@ decreases pure func lengthOfPrevSeg(currHF int, seg1Len int, seg2Len int, seg3Len int) (res int){ return seg1Len > currHF ? 0 : ((seg1Len + seg2Len) > currHF ? seg1Len : seg1Len + seg2Len) } -/* -ghost -requires 1 <= numINF && numINF <= 3 -requires 0 <= currHFIdx -requires hopFieldOffset(numINF, currHFIdx) + 12 <= len(raw) -requires dp.Valid() -requires let idx := hopFieldOffset(numINF, currHFIdx) in - acc(&raw[idx+4], _) && acc(&raw[idx+5], _) -decreases -pure func getAsidFromEgress(dp io.DataPlaneSpec, raw []byte, numINF int, currHFIdx int, asid io.IO_as) option[io.IO_as] { - return let idx := hopFieldOffset(numINF, currHFIdx) in - let consEgress := binary.BigEndian.Uint16(raw[idx+4:idx+6]) in - let outgoingPair := io.AsIfsPair{asid, io.IO_ifs(consEgress)} in - (io.AsIfsPair{asid, io.IO_ifs(consEgress)} in domain(dp.GetLinks()) ? - some(dp.Lookup(outgoingPair).asid) : none[io.IO_as]) -} -ghost -requires 1 <= numINF && numINF <= 3 -requires 0 <= currHFIdx -requires hopFieldOffset(numINF, currHFIdx) + 12 <= len(raw) -requires dp.Valid() -requires let idx := hopFieldOffset(numINF, currHFIdx) in - acc(&raw[idx+2], _) && acc(&raw[idx+3], _) -decreases -pure func getAsidFromIngress(dp io.DataPlaneSpec, raw []byte, numINF int, currHFIdx int, asid io.IO_as) option[io.IO_as] { - return let idx := hopFieldOffset(numINF, currHFIdx) in - let consIngress := binary.BigEndian.Uint16(raw[idx+2:idx+4]) in - let incommingPair := io.AsIfsPair{asid, io.IO_ifs(consIngress)} in - (io.AsIfsPair{asid, io.IO_ifs(consIngress)} in domain(dp.GetLinks()) ? - some(dp.Lookup(incommingPair).asid) : none[io.IO_as]) -} -*/ ghost requires 1 <= numINF requires 0 <= currHFIdx @@ -694,7 +662,7 @@ requires 0 <= seg3Len requires 4 + 8 * numInfoFields(seg1Len, seg2Len, seg3Len) == offset requires offset + 12 * (seg1Len + seg2Len + seg3Len) <= len(raw) requires 2 <= currINFIdx && currINFIdx < 5 -requires (currINFIdx == 4) ==> len(asid) == seg1Len +requires (currINFIdx == 4 && seg2Len > 0) ==> len(asid) == seg1Len requires (currINFIdx == 2 && seg2Len > 0 && seg3Len > 0) ==> len(asid) == seg3Len requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases @@ -707,7 +675,7 @@ pure func getMidSeg( seg3Len int, asid seq[io.IO_as]) option[io.IO_seg3] { - return (currINFIdx == 4) ? + return (currINFIdx == 4 && seg2Len > 0) ? some(getCurrSeg(raw, offset, 0, seg1Len, seg1Len, asid)) : (currINFIdx == 2 && seg2Len > 0 && seg3Len > 0) ? some(getCurrSeg(raw, offset + 12 * (seg1Len + seg2Len), currINFIdx, 0, seg3Len, asid)) : @@ -754,7 +722,7 @@ pure func getPkt(dp io.DataPlaneSpec, raw []byte, asid io.IO_as) option[io.IO_pk some(io.IO_pkt2(io.IO_Packet2{ CurrSeg : getCurrSeg(raw, offset+prevSegLen, currINFIdx, currHFIdx-prevSegLen, segLen, get(currAsidSeq)), LeftSeg : getLeftSeg(raw, offset, currINFIdx + 1, seg1Len, seg2Len , seg3Len, get(leftAsidSeq)), - MidSeg : none[io.IO_seg3],// getMidSeg(raw, offset, currINFIdx + 2, seg1Len, seg2Len , seg3Len, get(midAsidSeq)), + MidSeg : getMidSeg(raw, offset, currINFIdx + 2, seg1Len, seg2Len , seg3Len, get(midAsidSeq)), RightSeg : getRightSeg(raw, offset, currINFIdx - 1, seg1Len, seg2Len , seg3Len, get(rightAsidSeq)), })) } From b051f0982c8ad02f85454883f145fbaea8bce407 Mon Sep 17 00:00:00 2001 From: Markus Limbeck <92801626+mlimbeck@users.noreply.github.com> Date: Fri, 17 Nov 2023 18:02:47 +0100 Subject: [PATCH 24/33] Update router/dataplane_spec.gobra Co-authored-by: Dionysios Spiliopoulos <32896454+Dspil@users.noreply.github.com> --- router/dataplane_spec.gobra | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/router/dataplane_spec.gobra b/router/dataplane_spec.gobra index 6252a023f..ba10546ec 100644 --- a/router/dataplane_spec.gobra +++ b/router/dataplane_spec.gobra @@ -288,7 +288,7 @@ pure func infoFieldOffset(currINF int) int { ghost decreases pure func hopFieldOffset(numINF int, currHF int) int { - return 4 + 8*numINF + 12 * currHF + return 4 + 8 * numINF + 12 * currHF } From 7cbe9d65981988cd4f691187ec71696e305279b0 Mon Sep 17 00:00:00 2001 From: Markus Limbeck <92801626+mlimbeck@users.noreply.github.com> Date: Wed, 22 Nov 2023 13:04:49 +0100 Subject: [PATCH 25/33] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: João Pereira --- router/dataplane_spec.gobra | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/router/dataplane_spec.gobra b/router/dataplane_spec.gobra index ba10546ec..dbdc7c5c9 100644 --- a/router/dataplane_spec.gobra +++ b/router/dataplane_spec.gobra @@ -288,7 +288,7 @@ pure func infoFieldOffset(currINF int) int { ghost decreases pure func hopFieldOffset(numINF int, currHF int) int { - return 4 + 8 * numINF + 12 * currHF + return infoFieldOffset(numINF) + 12 * currHF } @@ -531,7 +531,8 @@ ghost requires -1 <= currHFIdx && currHFIdx < len(hopfields) decreases currHFIdx + 1 pure func getSegPast(hopfields seq[io.IO_HF], currHFIdx int) seq[io.IO_HF]{ - return currHFIdx == -1 ? seq[io.IO_HF]{} : + return currHFIdx == -1 ? + seq[io.IO_HF]{} : seq[io.IO_HF]{hopfields[currHFIdx]} ++ getSegPast(hopfields, currHFIdx - 1) } @@ -803,9 +804,13 @@ requires forall idx int :: {hopfields[idx]} 0 <= idx && idx < len(hopfields) ==> len(hopfields[idx].HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_) > 0 decreases pure func getUInfo(hopfields seq[io.IO_HF], currHFIdx int, consDir bool) set[io.IO_msgterm]{ - return currHFIdx == len(hopfields) ? getHVFSet(hopfields[currHFIdx-1]) : - currHFIdx == 0 ? getHVFSet(hopfields[currHFIdx]) : - consDir ? getHVFSet(hopfields[currHFIdx]) : getHVFSet(hopfields[currHFIdx-1]) + return currHFIdx == len(hopfields) ? + getHVFSet(hopfields[currHFIdx-1]) : + (currHFIdx == 0 ? + getHVFSet(hopfields[currHFIdx]) : + (consDir ? + getHVFSet(hopfields[currHFIdx]) : + getHVFSet(hopfields[currHFIdx-1])) } /** End of io-spec helper functions **/ \ No newline at end of file From 689e9da2f13814c874badde47506e433fa558d15 Mon Sep 17 00:00:00 2001 From: mlimbeck Date: Wed, 22 Nov 2023 13:21:25 +0100 Subject: [PATCH 26/33] readability improvements --- router/dataplane_spec.gobra | 544 --------------------------------- router/io-spec.gobra | 588 ++++++++++++++++++++++++++++++++++++ 2 files changed, 588 insertions(+), 544 deletions(-) create mode 100644 router/io-spec.gobra diff --git a/router/dataplane_spec.gobra b/router/dataplane_spec.gobra index dbdc7c5c9..33094c185 100644 --- a/router/dataplane_spec.gobra +++ b/router/dataplane_spec.gobra @@ -270,547 +270,3 @@ func closureSpec2(i uint16, c BatchConn) requires true func closureSpec3(c BatchConn) /** End of closure specs for the Run method **/ - -/** Start of io-spec helper functions **/ - -ghost -decreases -pure func numInfoFields(seg1Len int, seg2Len int, seg3Len int) int { - return seg3Len > 0 ? 3 : (seg2Len > 0 ? 2 : 1) -} - -ghost -decreases -pure func infoFieldOffset(currINF int) int { - return 4 + 8 * currINF -} - -ghost -decreases -pure func hopFieldOffset(numINF int, currHF int) int { - return infoFieldOffset(numINF) + 12 * currHF -} - - -ghost -decreases -pure func lengthOfCurrSeg(currHF int, seg1Len int, seg2Len int, seg3Len int) int{ - return seg1Len > currHF ? seg1Len : ((seg1Len + seg2Len) > currHF ? seg2Len : seg3Len) -} - -ghost -requires 0 <= currHF -ensures res <= currHF -decreases -pure func lengthOfPrevSeg(currHF int, seg1Len int, seg2Len int, seg3Len int) (res int){ - return seg1Len > currHF ? 0 : ((seg1Len + seg2Len) > currHF ? seg1Len : seg1Len + seg2Len) -} - -ghost -requires 1 <= numINF -requires 0 <= currHFIdx -requires hopFieldOffset(numINF, currHFIdx) + 12 <= len(raw) -requires dp.Valid() -requires let idx := hopFieldOffset(numINF, currHFIdx) in - acc(&raw[idx+2], _) && acc(&raw[idx+3], _) && acc(&raw[idx+4], _) && acc(&raw[idx+5], _) -decreases -pure func getAsidFromIfs(dp io.DataPlaneSpec, raw []byte, numINF int, currHFIdx int, consDir bool, asid io.IO_as) (res option[io.IO_as]) { - return let idx := hopFieldOffset(numINF, currHFIdx) in - let ifs := consDir ? binary.BigEndian.Uint16(raw[idx+4:idx+6]) : binary.BigEndian.Uint16(raw[idx+2:idx+4]) in - let asIfPair := io.AsIfsPair{asid, io.IO_ifs(ifs)} in - (asIfPair in domain(dp.GetLinks()) ? - some(dp.Lookup(asIfPair).asid) : none[io.IO_as]) -} - -ghost -requires 1 <= numINF -requires 0 <= prevSegLen && prevSegLen <= currHFIdx -requires hopFieldOffset(numINF, currHFIdx) + 12 <= len(raw) -requires dp.Valid() -requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -ensures res != none[seq[io.IO_as]] ==> len(get(res)) == currHFIdx - prevSegLen + 1 -decreases currHFIdx - prevSegLen -pure func getAsidsBefore(dp io.DataPlaneSpec, raw []byte, numINF int, currHFIdx int, prevSegLen int, consDir bool, asid io.IO_as) (res option[seq[io.IO_as]]) { - return let next_asid := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getAsidFromIfs(dp, raw, numINF, currHFIdx, !consDir, asid)) in - match next_asid{ - case none[io.IO_as]: - none[seq[io.IO_as]] - default: - currHFIdx == prevSegLen ? some(seq[io.IO_as]{get(next_asid)}) : - let next_asid_seq := getAsidsBefore(dp, raw, numINF, currHFIdx-1, prevSegLen, consDir, get(next_asid)) in - match next_asid_seq{ - case none[seq[io.IO_as]]: - none[seq[io.IO_as]] - default: - some(get(next_asid_seq) ++ seq[io.IO_as]{get(next_asid)}) - } - } -} - -ghost -requires 1 <= numINF -requires 0 <= currHFIdx && currHFIdx < segLen -requires hopFieldOffset(numINF, segLen) <= len(raw) -requires dp.Valid() -requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -ensures res != none[seq[io.IO_as]] ==> len(get(res)) == segLen - currHFIdx -decreases segLen - currHFIdx + 1 -pure func getAsidsAfter(dp io.DataPlaneSpec, raw []byte, numINF int, currHFIdx int, segLen int, consDir bool, asid io.IO_as) (res option[seq[io.IO_as]]) { - return let next_asid := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getAsidFromIfs(dp, raw, numINF, currHFIdx, consDir, asid)) in - match next_asid{ - case none[io.IO_as]: - none[seq[io.IO_as]] - default: - currHFIdx == segLen - 1 ? some(seq[io.IO_as]{get(next_asid)}) : - let next_asid_seq := getAsidsAfter(dp, raw, numINF, currHFIdx+1, segLen, consDir, get(next_asid)) in - match next_asid_seq{ - case none[seq[io.IO_as]]: - none[seq[io.IO_as]] - default: - some(seq[io.IO_as]{get(next_asid)} ++ get(next_asid_seq)) - } - } -} - -ghost -requires 1 <= numINF -requires 0 <= prevSegLen && prevSegLen <= currHFIdx -requires currHFIdx < segLen -requires hopFieldOffset(numINF, segLen) <= len(raw) -requires dp.Valid() -requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -ensures res != none[seq[io.IO_as]] ==> len(get(res)) == segLen - prevSegLen -decreases -pure func getAsidSeq(dp io.DataPlaneSpec, raw []byte, numINF int, currHFIdx int, segLen int, prevSegLen int, consDir bool, asid io.IO_as) (res option[seq[io.IO_as]]) { - return segLen == 0 ? some(seq[io.IO_as]{}) : - let left := getAsidsBefore(dp, raw, numINF, currHFIdx, prevSegLen, consDir, asid) in - let right := getAsidsAfter(dp, raw, numINF, currHFIdx, segLen, consDir, asid) in - (left == none[seq[io.IO_as]] || right == none[seq[io.IO_as]]) ? none[seq[io.IO_as]] : - some(get(left) ++ get(right)[1:]) -} - -ghost -requires dp.Valid() -requires 1 <= numINF -requires 0 < seg1Len -requires 0 <= seg2Len -requires 0 <= seg3Len -requires hopFieldOffset(numINF, seg1Len + seg2Len + seg3Len) <= len(raw) -requires currINFIdx <= numINF + 1 -requires 1 <= currINFIdx && currINFIdx < 4 -requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -decreases -pure func getAsidsLeft(dp io.DataPlaneSpec, raw []byte, numINF int, currINFIdx int, seg1Len int, seg2Len int, seg3Len int, asid io.IO_as) (res option[seq[io.IO_as]]){ - return let consDir := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getConsDir(raw, currINFIdx) in - (currINFIdx == 1 && seg2Len > 0) ? - getAsidSeq(dp, raw, numINF, seg1Len, seg1Len+seg2Len, seg1Len, consDir, asid) : - (currINFIdx == 2 && seg2Len > 0 && seg3Len > 0) ? - getAsidSeq(dp, raw, numINF, seg1Len+seg2Len, seg1Len+seg2Len+seg3Len, seg1Len+seg2Len, consDir, asid) : - some(seq[io.IO_as]{}) -} - -ghost -requires dp.Valid() -requires 1 <= numINF -requires 0 < seg1Len -requires 0 <= seg2Len -requires 0 <= seg3Len -requires hopFieldOffset(numINF, seg1Len + seg2Len + seg3Len) <= len(raw) -requires currINFIdx <= numINF + 1 -requires -1 <= currINFIdx && currINFIdx < 2 -requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -ensures (currINFIdx == 0 && res != none[seq[io.IO_as]]) ==> len(get(res)) == seg1Len -ensures (currINFIdx == 1 && seg2Len > 0 && res != none[seq[io.IO_as]]) ==> len(get(res)) == seg2Len -decreases -pure func getAsidsRight(dp io.DataPlaneSpec, raw []byte, numINF int, currINFIdx int, seg1Len int, seg2Len int, seg3Len int, asid io.IO_as) (res option[seq[io.IO_as]]){ - return (currINFIdx == 1 && seg2Len > 0) ? - let consDir := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getConsDir(raw, currINFIdx) in - getAsidSeq(dp, raw, numINF, seg1Len+seg2Len-1, seg1Len+seg2Len, seg1Len, consDir, asid) : - (currINFIdx == 0) ? - let consDir := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getConsDir(raw, currINFIdx) in - getAsidSeq(dp, raw, numINF, seg1Len-1, seg1Len, 0, consDir, asid) : - some(seq[io.IO_as]{}) -} - -ghost -requires dp.Valid() -requires 1 <= numINF -requires 0 < seg1Len -requires 0 <= seg2Len -requires 0 <= seg3Len -requires hopFieldOffset(numINF, seg1Len + seg2Len + seg3Len) <= len(raw) -requires currINFIdx <= numINF + 1 -requires 2 <= currINFIdx && currINFIdx < 5 -requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -requires (currINFIdx == 4 && seg2Len > 0) ==> asid != none[io.IO_as] -requires (currINFIdx == 2 && seg2Len > 0 && seg3Len > 0) ==> asid != none[io.IO_as] -decreases -pure func getAsidsMid(dp io.DataPlaneSpec, raw []byte, numINF int, currINFIdx int, seg1Len int, seg2Len int, seg3Len int, asid option[io.IO_as]) (res option[seq[io.IO_as]]){ - return (currINFIdx == 4 && seg2Len > 0) ? - let consDir := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getConsDir(raw, 1) in - getAsidSeq(dp, raw, numINF, seg1Len-1, seg1Len, 0, consDir, get(asid)) : - (currINFIdx == 2 && seg2Len > 0 && seg3Len > 0) ? - let consDir := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getConsDir(raw, 2) in - getAsidSeq(dp, raw, numINF, seg1Len + seg2Len, seg1Len + seg2Len + seg3Len, seg1Len + seg2Len, consDir, get(asid)) : - some(seq[io.IO_as]{}) -} - -ghost -requires idx + 12 <= len(raw) -requires 0 <= idx -requires acc(&raw[idx+2], _) && acc(&raw[idx+3], _) && acc(&raw[idx+4], _) && acc(&raw[idx+5], _) -ensures len(res.HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_) > 0 -decreases -pure func getHopField(raw []byte, idx int, beta set[io.IO_msgterm], asid io.IO_as, ainfo io.IO_ainfo) (res io.IO_HF) { - return let inif2 := binary.BigEndian.Uint16(raw[idx+2:idx+4]) in - let egif2 := binary.BigEndian.Uint16(raw[idx+4:idx+6]) in - let op_inif2 := inif2 == 0 ? none[io.IO_ifs] : some(io.IO_ifs(inif2)) in - let op_egif2 := egif2 == 0 ? none[io.IO_ifs] : some(io.IO_ifs(egif2)) in - let ts := io.IO_msgterm(io.MsgTerm_Num{ainfo}) in - let l := io.IO_msgterm(io.MsgTerm_L{seq[io.IO_msgterm]{ts, io.if2term(op_inif2), io.if2term(op_egif2), - io.IO_msgterm(io.MsgTerm_FS{beta})}}) in - let hvf := io.mac(io.macKey(io.asidToKey(asid)), l) in - io.IO_HF(io.IO_HF_{ - InIF2 : op_inif2, - EgIF2 : op_egif2, - HVF : hvf, - }) -} - -ghost -requires 0 <= offset -requires 0 <= currHFIdx && currHFIdx <= segLen -requires offset + 12 * segLen <= len(raw) -requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -requires len(asid) == segLen -ensures len(res) == segLen - currHFIdx -ensures forall k int :: {res[k]} 0 <= k && k < len(res) ==> - len(res[k].HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_) > 0 -decreases segLen - currHFIdx -pure func getHopfieldsConsDir( - raw []byte, - offset int, - currHFIdx int, - segLen int, - beta set[io.IO_msgterm], - asid seq[io.IO_as], - ainfo io.IO_ainfo) (res seq[io.IO_HF]){ - - return currHFIdx == segLen ? seq[io.IO_HF]{} : - let hf := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in - getHopField(raw, offset + 12 * currHFIdx, beta, asid[currHFIdx], ainfo)) in - seq[io.IO_HF]{hf} ++ getHopfieldsConsDir(raw, offset, currHFIdx + 1, segLen, (beta union set[io.IO_msgterm]{hf.HVF}), asid, ainfo) -} - -ghost -requires 0 <= offset -requires -1 <= currHFIdx && currHFIdx < segLen -requires offset + 12 * currHFIdx + 12 <= len(raw) -requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -requires len(asid) == segLen -ensures len(res) == currHFIdx + 1 -ensures forall k int :: {res[k]} 0 <= k && k < len(res) ==> - len(res[k].HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_) > 0 -decreases currHFIdx + 1 -pure func getHopfieldsNotConsDir( - raw []byte, - offset int, - currHFIdx int, - segLen int, - beta set[io.IO_msgterm], - asid seq[io.IO_as], - ainfo io.IO_ainfo) (res seq[io.IO_HF]){ - - return currHFIdx == -1 ? seq[io.IO_HF]{} : - let hf := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in - getHopField(raw, offset + 12 * currHFIdx, beta, asid[currHFIdx], ainfo)) in - getHopfieldsNotConsDir(raw, offset, currHFIdx -1, segLen, (beta union set[io.IO_msgterm]{hf.HVF}), asid, ainfo) ++ seq[io.IO_HF]{hf} -} - -ghost -requires -1 <= currHFIdx && currHFIdx < len(hopfields) -decreases currHFIdx + 1 -pure func getSegPast(hopfields seq[io.IO_HF], currHFIdx int) seq[io.IO_HF]{ - return currHFIdx == -1 ? - seq[io.IO_HF]{} : - seq[io.IO_HF]{hopfields[currHFIdx]} ++ getSegPast(hopfields, currHFIdx - 1) -} - -ghost -requires 0 <= currHFIdx && currHFIdx <= len(hopfields) -decreases len(hopfields) - currHFIdx -pure func getSegFuture(hopfields seq[io.IO_HF], currHFIdx int) seq[io.IO_HF]{ - return currHFIdx == len(hopfields) ? seq[io.IO_HF]{} : - seq[io.IO_HF]{hopfields[currHFIdx]} ++ getSegFuture(hopfields, currHFIdx + 1) -} - -ghost -requires -1 <= currHFIdx && currHFIdx < len(hopfields) -decreases currHFIdx + 1 -pure func getSegHistory(hopfields seq[io.IO_HF], currHFIdx int) seq[io.IO_ahi]{ - return currHFIdx == -1 ? seq[io.IO_ahi]{} : - seq[io.IO_ahi]{hopfields[currHFIdx].Toab()} ++ getSegHistory(hopfields, currHFIdx - 1) - -} - -ghost -requires 0 <= offset -requires 0 < segLen -requires offset + 12 * segLen <= len(raw) -requires 0 <= currHFIdx && currHFIdx <= segLen -requires len(asid) == segLen -requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -decreases -pure func getSegment(raw []byte, - offset int, - currHFIdx int, - segLen int, - asid seq[io.IO_as], - ainfo io.IO_ainfo, - consDir bool, - peer bool) io.IO_seg2{ - - return let hopfields := consDir ? - getHopfieldsConsDir(raw, offset, 0, segLen, set[io.IO_msgterm]{}, asid, ainfo) : - getHopfieldsNotConsDir(raw, offset, segLen - 1, segLen, set[io.IO_msgterm]{}, asid, ainfo) in - let uinfo := getUInfo(hopfields, currHFIdx, consDir) in - io.IO_seg2(io.IO_seg3_{ - AInfo :ainfo, - UInfo : uinfo, - ConsDir : consDir, - Peer : peer, - Past : getSegPast(hopfields, currHFIdx - 1), - Future : getSegFuture(hopfields, currHFIdx), - History : getSegHistory(hopfields, currHFIdx - 1), - }) -} - -ghost -requires 4 + 8 * currINFIdx + 8 <= offset -requires 0 < segLen -requires offset + 12 * segLen <= len(raw) -requires 0 <= currHFIdx && currHFIdx <= segLen -requires 0 <= currINFIdx && currINFIdx < 3 -requires len(asid) == segLen -requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -decreases -pure func getCurrSeg(raw []byte, offset int, currINFIdx int, currHFIdx int, segLen int, asid seq[io.IO_as]) io.IO_seg3 { - return unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in - let ainfo := getTimestamp(raw, currINFIdx) in - let consDir := getConsDir(raw, currINFIdx) in - let peer := getPeer(raw, currINFIdx) in - getSegment(raw, offset, currHFIdx, segLen, asid, ainfo, consDir, peer) -} - -ghost -requires 0 < seg1Len -requires 0 <= seg2Len -requires 0 <= seg3Len -requires 4 + 8 * numInfoFields(seg1Len, seg2Len, seg3Len) == offset -requires offset + 12 * (seg1Len + seg2Len + seg3Len) <= len(raw) -requires 1 <= currINFIdx && currINFIdx < 4 -requires (currINFIdx == 1 && seg2Len > 0) ==> len(asid) == seg2Len -requires (currINFIdx == 2 && seg2Len > 0 && seg3Len > 0) ==> len(asid) == seg3Len -requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -decreases -pure func getLeftSeg( - raw []byte, - offset int, - currINFIdx int, - seg1Len int, - seg2Len int, - seg3Len int, - asid seq[io.IO_as]) option[io.IO_seg3] { - - return (currINFIdx == 1 && seg2Len > 0) ? - some(getCurrSeg(raw, offset + 12 * seg1Len, currINFIdx, 0, seg2Len, asid)) : - (currINFIdx == 2 && seg2Len > 0 && seg3Len > 0) ? - some(getCurrSeg(raw, offset + 12 * (seg1Len + seg2Len), currINFIdx, 0, seg3Len, asid)) : - none[io.IO_seg3] -} - -ghost -requires 0 < seg1Len -requires 0 <= seg2Len -requires 0 <= seg3Len -requires 4 + 8 * numInfoFields(seg1Len, seg2Len, seg3Len) == offset -requires offset + 12 * (seg1Len + seg2Len + seg3Len) <= len(raw) -requires -1 <= currINFIdx && currINFIdx < 2 -requires (currINFIdx == 1 && seg2Len > 0 && seg3Len > 0) ==> len(asid) == seg2Len -requires (currINFIdx == 0 && seg2Len > 0) ==> len(asid) == seg1Len -requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -decreases -pure func getRightSeg( - raw []byte, - offset int, - currINFIdx int, - seg1Len int, - seg2Len int, - seg3Len int, - asid seq[io.IO_as]) option[io.IO_seg3] { - - return (currINFIdx == 1 && seg2Len > 0 && seg3Len > 0) ? - some(getCurrSeg(raw, offset + 12 * seg1Len, currINFIdx, seg2Len, seg2Len, asid)) : - (currINFIdx == 0 && seg2Len > 0) ? - some(getCurrSeg(raw, offset, currINFIdx, seg1Len, seg1Len, asid)) : - none[io.IO_seg3] -} - -ghost -requires 0 < seg1Len -requires 0 <= seg2Len -requires 0 <= seg3Len -requires 4 + 8 * numInfoFields(seg1Len, seg2Len, seg3Len) == offset -requires offset + 12 * (seg1Len + seg2Len + seg3Len) <= len(raw) -requires 2 <= currINFIdx && currINFIdx < 5 -requires (currINFIdx == 4 && seg2Len > 0) ==> len(asid) == seg1Len -requires (currINFIdx == 2 && seg2Len > 0 && seg3Len > 0) ==> len(asid) == seg3Len -requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -decreases -pure func getMidSeg( - raw []byte, - offset int, - currINFIdx int, - seg1Len int, - seg2Len int, - seg3Len int, - asid seq[io.IO_as]) option[io.IO_seg3] { - - return (currINFIdx == 4 && seg2Len > 0) ? - some(getCurrSeg(raw, offset, 0, seg1Len, seg1Len, asid)) : - (currINFIdx == 2 && seg2Len > 0 && seg3Len > 0) ? - some(getCurrSeg(raw, offset + 12 * (seg1Len + seg2Len), currINFIdx, 0, seg3Len, asid)) : - none[io.IO_seg3] -} - -ghost -requires dp.Valid() -requires len(raw) > 4 -requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -requires unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in - let hdr := binary.BigEndian.Uint32(raw[0:4]) in - 0 <= getCurrINF(hdr) && getCurrINF(hdr) < 3 && - getCurrINF(hdr) + 1 <= numInfoFields(int(getSeg1Len(hdr)), int(getSeg2Len(hdr)), int(getSeg3Len(hdr))) && - 0 <= getCurrHF(hdr) && getCurrHF(hdr) < getSeg1Len(hdr) + getSeg2Len(hdr) + getSeg3Len(hdr) && - 0 < getSeg1Len(hdr) && - 0 <= getSeg2Len(hdr) && - 0 <= getSeg3Len(hdr) && - 4 + 8 * numInfoFields(int(getSeg1Len(hdr)), int(getSeg2Len(hdr)), int(getSeg3Len(hdr))) + 12 * (int(getSeg1Len(hdr)) + int(getSeg2Len(hdr)) + int(getSeg3Len(hdr))) == len(raw) -decreases -pure func getPkt(dp io.DataPlaneSpec, raw []byte, asid io.IO_as) option[io.IO_pkt2]{ - return let hdr := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in binary.BigEndian.Uint32(raw[0:4]) in - let currINFIdx := int(getCurrINF(hdr)) in - let currHFIdx := int(getCurrHF(hdr)) in - let seg1Len := int(getSeg1Len(hdr)) in - let seg2Len := int(getSeg2Len(hdr)) in - let seg3Len := int(getSeg3Len(hdr)) in - let segLen := lengthOfCurrSeg(currHFIdx, seg1Len, seg2Len, seg3Len) in - let prevSegLen := lengthOfPrevSeg(currHFIdx, seg1Len, seg2Len, seg3Len) in - let numINF := int(numInfoFields(seg1Len, seg2Len, seg3Len)) in - let offset := 4 + 8 * numINF in - let consDir := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getConsDir(raw, currINFIdx) in - let currAsidSeq := getAsidSeq(dp, raw, numINF, currHFIdx, prevSegLen+segLen, prevSegLen, consDir, dp.Asid()) in - currAsidSeq == none[seq[io.IO_as]] ? none[io.IO_pkt2] : - let last := get(currAsidSeq)[segLen-1] in - let first := get(currAsidSeq)[0] in - let leftAsidSeq := getAsidsLeft(dp, raw, numINF, currINFIdx + 1, seg1Len, seg2Len, seg3Len, last) in - let rightAsidSeq := getAsidsRight(dp, raw, numINF, currINFIdx - 1, seg1Len, seg2Len, seg3Len, first) in - (leftAsidSeq == none[seq[io.IO_as]] || rightAsidSeq == none[seq[io.IO_as]]) ? none[io.IO_pkt2] : - let midAsid := ((currINFIdx == 0 && seg2Len > 0 && seg3Len > 0) ? some(get(leftAsidSeq)[len(get(leftAsidSeq))-1]) : - (currINFIdx == 2 && seg2Len > 0) ? some(get(rightAsidSeq)[0]) : none[io.IO_as]) in - let midAsidSeq := getAsidsMid(dp, raw, numINF, currINFIdx + 2, seg1Len, seg2Len, seg3Len, midAsid) in - midAsidSeq == none[seq[io.IO_as]] ? none[io.IO_pkt2] : - some(io.IO_pkt2(io.IO_Packet2{ - CurrSeg : getCurrSeg(raw, offset+prevSegLen, currINFIdx, currHFIdx-prevSegLen, segLen, get(currAsidSeq)), - LeftSeg : getLeftSeg(raw, offset, currINFIdx + 1, seg1Len, seg2Len , seg3Len, get(leftAsidSeq)), - MidSeg : getMidSeg(raw, offset, currINFIdx + 2, seg1Len, seg2Len , seg3Len, get(midAsidSeq)), - RightSeg : getRightSeg(raw, offset, currINFIdx - 1, seg1Len, seg2Len , seg3Len, get(rightAsidSeq)), - })) -} - -ghost -decreases -pure func getCurrINF(hdr uint32) uint8{ - return uint8(hdr >> 30) -} - -ghost -decreases -pure func getCurrHF(hdr uint32) uint8{ - return uint8(hdr >> 24) & 0x3F -} - -ghost -decreases -pure func getSeg1Len(hdr uint32) uint8{ - return uint8(hdr >> 12) & 0x3F -} - -ghost -decreases -pure func getSeg2Len(hdr uint32) uint8{ - return uint8(hdr >> 6) & 0x3F -} - -ghost -decreases -pure func getSeg3Len(hdr uint32) uint8{ - return uint8(hdr) & 0x3F -} - -ghost -requires 0 <= offset -requires infoFieldOffset(offset) < len(raw) -requires acc(&raw[infoFieldOffset(offset)], _) -decreases -pure func getConsDir(raw []byte, offset int) bool{ - return raw[infoFieldOffset(offset)] & 0x1 == 0x1 -} - -ghost -requires 0 <= offset -requires infoFieldOffset(offset) < len(raw) -requires acc(&raw[infoFieldOffset(offset)], _) -decreases -pure func getPeer(raw []byte, offset int) bool{ - return raw[infoFieldOffset(offset)] & 0x2 == 0x2 -} - -ghost -requires 0 <= offset -requires infoFieldOffset(offset) + 8 < len(raw) -requires acc(&raw[infoFieldOffset(offset) + 4], _) -requires acc(&raw[infoFieldOffset(offset) + 5], _) -requires acc(&raw[infoFieldOffset(offset) + 6], _) -requires acc(&raw[infoFieldOffset(offset) + 7], _) -decreases -pure func getTimestamp(raw []byte, offset int) io.IO_ainfo{ - return let idx := infoFieldOffset(offset) + 4 in - io.IO_ainfo(binary.BigEndian.Uint32(raw[idx : idx + 4])) -} - -ghost -requires len(hopfield.HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_) > 0 -decreases -pure func getHVFSet(hopfield io.IO_HF) set[io.IO_msgterm]{ - return let l := hopfield.HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_ in - l[len(l) - 1].MsgTerm_FS_ -} - -ghost -requires 0 < len(hopfields) -requires 0 <= currHFIdx && currHFIdx <= len(hopfields) -requires forall idx int :: {hopfields[idx]} 0 <= idx && idx < len(hopfields) ==> - len(hopfields[idx].HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_) > 0 -decreases -pure func getUInfo(hopfields seq[io.IO_HF], currHFIdx int, consDir bool) set[io.IO_msgterm]{ - return currHFIdx == len(hopfields) ? - getHVFSet(hopfields[currHFIdx-1]) : - (currHFIdx == 0 ? - getHVFSet(hopfields[currHFIdx]) : - (consDir ? - getHVFSet(hopfields[currHFIdx]) : - getHVFSet(hopfields[currHFIdx-1])) -} - -/** End of io-spec helper functions **/ \ No newline at end of file diff --git a/router/io-spec.gobra b/router/io-spec.gobra new file mode 100644 index 000000000..45d9e1de6 --- /dev/null +++ b/router/io-spec.gobra @@ -0,0 +1,588 @@ +// Copyright 2022 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +gobra + +package router + +import ( + sl "github.com/scionproto/scion/verification/utils/slices" + "github.com/scionproto/scion/verification/io" + "github.com/scionproto/scion/verification/dependencies/encoding/binary" +) + +/** Start of io-spec helper functions **/ + +ghost +decreases +pure func numInfoFields(seg1Len int, seg2Len int, seg3Len int) int { + return seg3Len > 0 ? 3 : (seg2Len > 0 ? 2 : 1) +} + +ghost +decreases +pure func infoFieldOffset(currINF int) int { + return 4 + 8 * currINF +} + +ghost +decreases +pure func hopFieldOffset(numINF int, currHF int) int { + return infoFieldOffset(numINF) + 12 * currHF +} + + +ghost +decreases +pure func lengthOfCurrSeg(currHF int, seg1Len int, seg2Len int, seg3Len int) int { + return seg1Len > currHF ? seg1Len : ((seg1Len + seg2Len) > currHF ? seg2Len : seg3Len) +} + +ghost +requires 0 <= currHF +ensures res <= currHF +decreases +pure func lengthOfPrevSeg(currHF int, seg1Len int, seg2Len int, seg3Len int) (res int) { + return seg1Len > currHF ? 0 : ((seg1Len + seg2Len) > currHF ? seg1Len : seg1Len + seg2Len) +} + +ghost +requires 1 <= numINF +requires 0 <= currHFIdx +requires hopFieldOffset(numINF, currHFIdx) + 12 <= len(raw) +requires dp.Valid() +requires let idx := hopFieldOffset(numINF, currHFIdx) in + acc(&raw[idx+2], _) && acc(&raw[idx+3], _) && acc(&raw[idx+4], _) && acc(&raw[idx+5], _) +decreases +pure func getAsidFromIfs( + dp io.DataPlaneSpec, + raw []byte, + numINF int, + currHFIdx int, + consDir bool, + asid io.IO_as) (res option[io.IO_as]) { + + return let idx := hopFieldOffset(numINF, currHFIdx) in + let ifs := consDir ? binary.BigEndian.Uint16(raw[idx+4:idx+6]) : binary.BigEndian.Uint16(raw[idx+2:idx+4]) in + let asIfPair := io.AsIfsPair{asid, io.IO_ifs(ifs)} in + (asIfPair in domain(dp.GetLinks()) ? + some(dp.Lookup(asIfPair).asid) : none[io.IO_as]) +} + +ghost +requires 1 <= numINF +requires 0 <= prevSegLen && prevSegLen <= currHFIdx +requires hopFieldOffset(numINF, currHFIdx) + 12 <= len(raw) +requires dp.Valid() +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +ensures res != none[seq[io.IO_as]] ==> len(get(res)) == currHFIdx - prevSegLen + 1 +decreases currHFIdx - prevSegLen +pure func getAsidsBefore( + dp io.DataPlaneSpec, + raw []byte, + numINF int, + currHFIdx int, + prevSegLen int, + consDir bool, + asid io.IO_as) (res option[seq[io.IO_as]]) { + + return let next_asid := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getAsidFromIfs(dp, raw, numINF, currHFIdx, !consDir, asid)) in + match next_asid{ + case none[io.IO_as]: + none[seq[io.IO_as]] + default: + currHFIdx == prevSegLen ? some(seq[io.IO_as]{get(next_asid)}) : + let next_asid_seq := getAsidsBefore(dp, raw, numINF, currHFIdx-1, prevSegLen, consDir, get(next_asid)) in + match next_asid_seq{ + case none[seq[io.IO_as]]: + none[seq[io.IO_as]] + default: + some(get(next_asid_seq) ++ seq[io.IO_as]{get(next_asid)}) + } + } +} + +ghost +requires 1 <= numINF +requires 0 <= currHFIdx && currHFIdx < segLen +requires hopFieldOffset(numINF, segLen) <= len(raw) +requires dp.Valid() +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +ensures res != none[seq[io.IO_as]] ==> len(get(res)) == segLen - currHFIdx +decreases segLen - currHFIdx + 1 +pure func getAsidsAfter( + dp io.DataPlaneSpec, + raw []byte, + numINF int, + currHFIdx int, + segLen int, + consDir bool, + asid io.IO_as) (res option[seq[io.IO_as]]) { + + return let next_asid := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getAsidFromIfs(dp, raw, numINF, currHFIdx, consDir, asid)) in + match next_asid{ + case none[io.IO_as]: + none[seq[io.IO_as]] + default: + currHFIdx == segLen - 1 ? some(seq[io.IO_as]{get(next_asid)}) : + let next_asid_seq := getAsidsAfter(dp, raw, numINF, currHFIdx+1, segLen, consDir, get(next_asid)) in + match next_asid_seq{ + case none[seq[io.IO_as]]: + none[seq[io.IO_as]] + default: + some(seq[io.IO_as]{get(next_asid)} ++ get(next_asid_seq)) + } + } +} + +ghost +requires 1 <= numINF +requires 0 <= prevSegLen && prevSegLen <= currHFIdx +requires currHFIdx < segLen +requires hopFieldOffset(numINF, segLen) <= len(raw) +requires dp.Valid() +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +ensures res != none[seq[io.IO_as]] ==> len(get(res)) == segLen - prevSegLen +decreases +pure func getAsidSeq(dp io.DataPlaneSpec, raw []byte, numINF int, currHFIdx int, segLen int, prevSegLen int, consDir bool, asid io.IO_as) (res option[seq[io.IO_as]]) { + return segLen == 0 ? some(seq[io.IO_as]{}) : + let left := getAsidsBefore(dp, raw, numINF, currHFIdx, prevSegLen, consDir, asid) in + let right := getAsidsAfter(dp, raw, numINF, currHFIdx, segLen, consDir, asid) in + (left == none[seq[io.IO_as]] || right == none[seq[io.IO_as]]) ? none[seq[io.IO_as]] : + some(get(left) ++ get(right)[1:]) +} + +ghost +requires dp.Valid() +requires 1 <= numINF +requires 0 < seg1Len +requires 0 <= seg2Len +requires 0 <= seg3Len +requires hopFieldOffset(numINF, seg1Len + seg2Len + seg3Len) <= len(raw) +requires currINFIdx <= numINF + 1 +requires 1 <= currINFIdx && currINFIdx < 4 +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +decreases +pure func getAsidsLeft(dp io.DataPlaneSpec, raw []byte, numINF int, currINFIdx int, seg1Len int, seg2Len int, seg3Len int, asid io.IO_as) (res option[seq[io.IO_as]]) { + return let consDir := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getConsDir(raw, currINFIdx) in + (currINFIdx == 1 && seg2Len > 0) ? + getAsidSeq(dp, raw, numINF, seg1Len, seg1Len+seg2Len, seg1Len, consDir, asid) : + (currINFIdx == 2 && seg2Len > 0 && seg3Len > 0) ? + getAsidSeq(dp, raw, numINF, seg1Len+seg2Len, seg1Len+seg2Len+seg3Len, seg1Len+seg2Len, consDir, asid) : + some(seq[io.IO_as]{}) +} + +ghost +requires dp.Valid() +requires 1 <= numINF +requires 0 < seg1Len +requires 0 <= seg2Len +requires 0 <= seg3Len +requires hopFieldOffset(numINF, seg1Len + seg2Len + seg3Len) <= len(raw) +requires currINFIdx <= numINF + 1 +requires -1 <= currINFIdx && currINFIdx < 2 +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +ensures (currINFIdx == 0 && res != none[seq[io.IO_as]]) ==> len(get(res)) == seg1Len +ensures (currINFIdx == 1 && seg2Len > 0 && res != none[seq[io.IO_as]]) ==> len(get(res)) == seg2Len +decreases +pure func getAsidsRight(dp io.DataPlaneSpec, raw []byte, numINF int, currINFIdx int, seg1Len int, seg2Len int, seg3Len int, asid io.IO_as) (res option[seq[io.IO_as]]) { + return (currINFIdx == 1 && seg2Len > 0) ? + let consDir := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getConsDir(raw, currINFIdx) in + getAsidSeq(dp, raw, numINF, seg1Len+seg2Len-1, seg1Len+seg2Len, seg1Len, consDir, asid) : + (currINFIdx == 0) ? + let consDir := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getConsDir(raw, currINFIdx) in + getAsidSeq(dp, raw, numINF, seg1Len-1, seg1Len, 0, consDir, asid) : + some(seq[io.IO_as]{}) +} + +ghost +requires dp.Valid() +requires 1 <= numINF +requires 0 < seg1Len +requires 0 <= seg2Len +requires 0 <= seg3Len +requires hopFieldOffset(numINF, seg1Len + seg2Len + seg3Len) <= len(raw) +requires currINFIdx <= numINF + 1 +requires 2 <= currINFIdx && currINFIdx < 5 +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +requires (currINFIdx == 4 && seg2Len > 0) ==> asid != none[io.IO_as] +requires (currINFIdx == 2 && seg2Len > 0 && seg3Len > 0) ==> asid != none[io.IO_as] +decreases +pure func getAsidsMid(dp io.DataPlaneSpec, raw []byte, numINF int, currINFIdx int, seg1Len int, seg2Len int, seg3Len int, asid option[io.IO_as]) (res option[seq[io.IO_as]]) { + return (currINFIdx == 4 && seg2Len > 0) ? + let consDir := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getConsDir(raw, 1) in + getAsidSeq(dp, raw, numINF, seg1Len-1, seg1Len, 0, consDir, get(asid)) : + (currINFIdx == 2 && seg2Len > 0 && seg3Len > 0) ? + let consDir := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getConsDir(raw, 2) in + getAsidSeq(dp, raw, numINF, seg1Len + seg2Len, seg1Len + seg2Len + seg3Len, seg1Len + seg2Len, consDir, get(asid)) : + some(seq[io.IO_as]{}) +} + +ghost +requires idx + 12 <= len(raw) +requires 0 <= idx +requires acc(&raw[idx+2], _) && acc(&raw[idx+3], _) && acc(&raw[idx+4], _) && acc(&raw[idx+5], _) +ensures len(res.HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_) > 0 +decreases +pure func getHopField(raw []byte, idx int, beta set[io.IO_msgterm], asid io.IO_as, ainfo io.IO_ainfo) (res io.IO_HF) { + return let inif2 := binary.BigEndian.Uint16(raw[idx+2:idx+4]) in + let egif2 := binary.BigEndian.Uint16(raw[idx+4:idx+6]) in + let op_inif2 := inif2 == 0 ? none[io.IO_ifs] : some(io.IO_ifs(inif2)) in + let op_egif2 := egif2 == 0 ? none[io.IO_ifs] : some(io.IO_ifs(egif2)) in + let ts := io.IO_msgterm(io.MsgTerm_Num{ainfo}) in + let l := io.IO_msgterm(io.MsgTerm_L{seq[io.IO_msgterm]{ts, io.if2term(op_inif2), io.if2term(op_egif2), + io.IO_msgterm(io.MsgTerm_FS{beta})}}) in + let hvf := io.mac(io.macKey(io.asidToKey(asid)), l) in + io.IO_HF(io.IO_HF_{ + InIF2 : op_inif2, + EgIF2 : op_egif2, + HVF : hvf, + }) +} + +ghost +requires 0 <= offset +requires 0 <= currHFIdx && currHFIdx <= segLen +requires offset + 12 * segLen <= len(raw) +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +requires len(asid) == segLen +ensures len(res) == segLen - currHFIdx +ensures forall k int :: {res[k]} 0 <= k && k < len(res) ==> + len(res[k].HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_) > 0 +decreases segLen - currHFIdx +pure func getHopfieldsConsDir( + raw []byte, + offset int, + currHFIdx int, + segLen int, + beta set[io.IO_msgterm], + asid seq[io.IO_as], + ainfo io.IO_ainfo) (res seq[io.IO_HF]) { + + return currHFIdx == segLen ? seq[io.IO_HF]{} : + let hf := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in + getHopField(raw, offset + 12 * currHFIdx, beta, asid[currHFIdx], ainfo)) in + seq[io.IO_HF]{hf} ++ getHopfieldsConsDir(raw, offset, currHFIdx + 1, segLen, (beta union set[io.IO_msgterm]{hf.HVF}), asid, ainfo) +} + +ghost +requires 0 <= offset +requires -1 <= currHFIdx && currHFIdx < segLen +requires offset + 12 * currHFIdx + 12 <= len(raw) +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +requires len(asid) == segLen +ensures len(res) == currHFIdx + 1 +ensures forall k int :: {res[k]} 0 <= k && k < len(res) ==> + len(res[k].HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_) > 0 +decreases currHFIdx + 1 +pure func getHopfieldsNotConsDir( + raw []byte, + offset int, + currHFIdx int, + segLen int, + beta set[io.IO_msgterm], + asid seq[io.IO_as], + ainfo io.IO_ainfo) (res seq[io.IO_HF]) { + + return currHFIdx == -1 ? seq[io.IO_HF]{} : + let hf := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in + getHopField(raw, offset + 12 * currHFIdx, beta, asid[currHFIdx], ainfo)) in + getHopfieldsNotConsDir(raw, offset, currHFIdx -1, segLen, (beta union set[io.IO_msgterm]{hf.HVF}), asid, ainfo) ++ seq[io.IO_HF]{hf} +} + +ghost +requires -1 <= currHFIdx && currHFIdx < len(hopfields) +decreases currHFIdx + 1 +pure func getSegPast(hopfields seq[io.IO_HF], currHFIdx int) seq[io.IO_HF] { + return currHFIdx == -1 ? + seq[io.IO_HF]{} : + seq[io.IO_HF]{hopfields[currHFIdx]} ++ getSegPast(hopfields, currHFIdx - 1) +} + +ghost +requires 0 <= currHFIdx && currHFIdx <= len(hopfields) +decreases len(hopfields) - currHFIdx +pure func getSegFuture(hopfields seq[io.IO_HF], currHFIdx int) seq[io.IO_HF] { + return currHFIdx == len(hopfields) ? seq[io.IO_HF]{} : + seq[io.IO_HF]{hopfields[currHFIdx]} ++ getSegFuture(hopfields, currHFIdx + 1) +} + +ghost +requires -1 <= currHFIdx && currHFIdx < len(hopfields) +decreases currHFIdx + 1 +pure func getSegHistory(hopfields seq[io.IO_HF], currHFIdx int) seq[io.IO_ahi] { + return currHFIdx == -1 ? seq[io.IO_ahi]{} : + seq[io.IO_ahi]{hopfields[currHFIdx].Toab()} ++ getSegHistory(hopfields, currHFIdx - 1) + +} + +ghost +requires 0 <= offset +requires 0 < segLen +requires offset + 12 * segLen <= len(raw) +requires 0 <= currHFIdx && currHFIdx <= segLen +requires len(asid) == segLen +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +decreases +pure func getSegment(raw []byte, + offset int, + currHFIdx int, + segLen int, + asid seq[io.IO_as], + ainfo io.IO_ainfo, + consDir bool, + peer bool) io.IO_seg2 { + + return let hopfields := consDir ? + getHopfieldsConsDir(raw, offset, 0, segLen, set[io.IO_msgterm]{}, asid, ainfo) : + getHopfieldsNotConsDir(raw, offset, segLen - 1, segLen, set[io.IO_msgterm]{}, asid, ainfo) in + let uinfo := getUInfo(hopfields, currHFIdx, consDir) in + io.IO_seg2(io.IO_seg3_{ + AInfo :ainfo, + UInfo : uinfo, + ConsDir : consDir, + Peer : peer, + Past : getSegPast(hopfields, currHFIdx - 1), + Future : getSegFuture(hopfields, currHFIdx), + History : getSegHistory(hopfields, currHFIdx - 1), + }) +} + +ghost +requires 4 + 8 * currINFIdx + 8 <= offset +requires 0 < segLen +requires offset + 12 * segLen <= len(raw) +requires 0 <= currHFIdx && currHFIdx <= segLen +requires 0 <= currINFIdx && currINFIdx < 3 +requires len(asid) == segLen +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +decreases +pure func getCurrSeg(raw []byte, offset int, currINFIdx int, currHFIdx int, segLen int, asid seq[io.IO_as]) io.IO_seg3 { + return unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in + let ainfo := getTimestamp(raw, currINFIdx) in + let consDir := getConsDir(raw, currINFIdx) in + let peer := getPeer(raw, currINFIdx) in + getSegment(raw, offset, currHFIdx, segLen, asid, ainfo, consDir, peer) +} + +ghost +requires 0 < seg1Len +requires 0 <= seg2Len +requires 0 <= seg3Len +requires 4 + 8 * numInfoFields(seg1Len, seg2Len, seg3Len) == offset +requires offset + 12 * (seg1Len + seg2Len + seg3Len) <= len(raw) +requires 1 <= currINFIdx && currINFIdx < 4 +requires (currINFIdx == 1 && seg2Len > 0) ==> len(asid) == seg2Len +requires (currINFIdx == 2 && seg2Len > 0 && seg3Len > 0) ==> len(asid) == seg3Len +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +decreases +pure func getLeftSeg( + raw []byte, + offset int, + currINFIdx int, + seg1Len int, + seg2Len int, + seg3Len int, + asid seq[io.IO_as]) option[io.IO_seg3] { + + return (currINFIdx == 1 && seg2Len > 0) ? + some(getCurrSeg(raw, offset + 12 * seg1Len, currINFIdx, 0, seg2Len, asid)) : + (currINFIdx == 2 && seg2Len > 0 && seg3Len > 0) ? + some(getCurrSeg(raw, offset + 12 * (seg1Len + seg2Len), currINFIdx, 0, seg3Len, asid)) : + none[io.IO_seg3] +} + +ghost +requires 0 < seg1Len +requires 0 <= seg2Len +requires 0 <= seg3Len +requires 4 + 8 * numInfoFields(seg1Len, seg2Len, seg3Len) == offset +requires offset + 12 * (seg1Len + seg2Len + seg3Len) <= len(raw) +requires -1 <= currINFIdx && currINFIdx < 2 +requires (currINFIdx == 1 && seg2Len > 0 && seg3Len > 0) ==> len(asid) == seg2Len +requires (currINFIdx == 0 && seg2Len > 0) ==> len(asid) == seg1Len +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +decreases +pure func getRightSeg( + raw []byte, + offset int, + currINFIdx int, + seg1Len int, + seg2Len int, + seg3Len int, + asid seq[io.IO_as]) option[io.IO_seg3] { + + return (currINFIdx == 1 && seg2Len > 0 && seg3Len > 0) ? + some(getCurrSeg(raw, offset + 12 * seg1Len, currINFIdx, seg2Len, seg2Len, asid)) : + (currINFIdx == 0 && seg2Len > 0) ? + some(getCurrSeg(raw, offset, currINFIdx, seg1Len, seg1Len, asid)) : + none[io.IO_seg3] +} + +ghost +requires 0 < seg1Len +requires 0 <= seg2Len +requires 0 <= seg3Len +requires 4 + 8 * numInfoFields(seg1Len, seg2Len, seg3Len) == offset +requires offset + 12 * (seg1Len + seg2Len + seg3Len) <= len(raw) +requires 2 <= currINFIdx && currINFIdx < 5 +requires (currINFIdx == 4 && seg2Len > 0) ==> len(asid) == seg1Len +requires (currINFIdx == 2 && seg2Len > 0 && seg3Len > 0) ==> len(asid) == seg3Len +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +decreases +pure func getMidSeg( + raw []byte, + offset int, + currINFIdx int, + seg1Len int, + seg2Len int, + seg3Len int, + asid seq[io.IO_as]) option[io.IO_seg3] { + + return (currINFIdx == 4 && seg2Len > 0) ? + some(getCurrSeg(raw, offset, 0, seg1Len, seg1Len, asid)) : + (currINFIdx == 2 && seg2Len > 0 && seg3Len > 0) ? + some(getCurrSeg(raw, offset + 12 * (seg1Len + seg2Len), currINFIdx, 0, seg3Len, asid)) : + none[io.IO_seg3] +} + +ghost +requires dp.Valid() +requires len(raw) > 4 +requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) +requires unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in + let hdr := binary.BigEndian.Uint32(raw[0:4]) in + 0 <= getCurrINF(hdr) && getCurrINF(hdr) < 3 && + getCurrINF(hdr) + 1 <= numInfoFields(int(getSeg1Len(hdr)), int(getSeg2Len(hdr)), int(getSeg3Len(hdr))) && + 0 <= getCurrHF(hdr) && getCurrHF(hdr) < getSeg1Len(hdr) + getSeg2Len(hdr) + getSeg3Len(hdr) && + 0 < getSeg1Len(hdr) && + 0 <= getSeg2Len(hdr) && + 0 <= getSeg3Len(hdr) && + 4 + 8 * numInfoFields(int(getSeg1Len(hdr)), int(getSeg2Len(hdr)), int(getSeg3Len(hdr))) + 12 * (int(getSeg1Len(hdr)) + int(getSeg2Len(hdr)) + int(getSeg3Len(hdr))) == len(raw) +decreases +pure func getPkt(dp io.DataPlaneSpec, raw []byte, asid io.IO_as) option[io.IO_pkt2] { + return let hdr := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in binary.BigEndian.Uint32(raw[0:4]) in + let currINFIdx := int(getCurrINF(hdr)) in + let currHFIdx := int(getCurrHF(hdr)) in + let seg1Len := int(getSeg1Len(hdr)) in + let seg2Len := int(getSeg2Len(hdr)) in + let seg3Len := int(getSeg3Len(hdr)) in + let segLen := lengthOfCurrSeg(currHFIdx, seg1Len, seg2Len, seg3Len) in + let prevSegLen := lengthOfPrevSeg(currHFIdx, seg1Len, seg2Len, seg3Len) in + let numINF := int(numInfoFields(seg1Len, seg2Len, seg3Len)) in + let offset := 4 + 8 * numINF in + let consDir := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getConsDir(raw, currINFIdx) in + let currAsidSeq := getAsidSeq(dp, raw, numINF, currHFIdx, prevSegLen+segLen, prevSegLen, consDir, dp.Asid()) in + currAsidSeq == none[seq[io.IO_as]] ? none[io.IO_pkt2] : + let last := get(currAsidSeq)[segLen-1] in + let first := get(currAsidSeq)[0] in + let leftAsidSeq := getAsidsLeft(dp, raw, numINF, currINFIdx + 1, seg1Len, seg2Len, seg3Len, last) in + let rightAsidSeq := getAsidsRight(dp, raw, numINF, currINFIdx - 1, seg1Len, seg2Len, seg3Len, first) in + (leftAsidSeq == none[seq[io.IO_as]] || rightAsidSeq == none[seq[io.IO_as]]) ? none[io.IO_pkt2] : + let midAsid := ((currINFIdx == 0 && seg2Len > 0 && seg3Len > 0) ? some(get(leftAsidSeq)[len(get(leftAsidSeq))-1]) : + (currINFIdx == 2 && seg2Len > 0) ? some(get(rightAsidSeq)[0]) : none[io.IO_as]) in + let midAsidSeq := getAsidsMid(dp, raw, numINF, currINFIdx + 2, seg1Len, seg2Len, seg3Len, midAsid) in + midAsidSeq == none[seq[io.IO_as]] ? none[io.IO_pkt2] : + some(io.IO_pkt2(io.IO_Packet2{ + CurrSeg : getCurrSeg(raw, offset+prevSegLen, currINFIdx, currHFIdx-prevSegLen, segLen, get(currAsidSeq)), + LeftSeg : getLeftSeg(raw, offset, currINFIdx + 1, seg1Len, seg2Len , seg3Len, get(leftAsidSeq)), + MidSeg : getMidSeg(raw, offset, currINFIdx + 2, seg1Len, seg2Len , seg3Len, get(midAsidSeq)), + RightSeg : getRightSeg(raw, offset, currINFIdx - 1, seg1Len, seg2Len , seg3Len, get(rightAsidSeq)), + })) +} + +ghost +decreases +pure func getCurrINF(hdr uint32) uint8 { + return uint8(hdr >> 30) +} + +ghost +decreases +pure func getCurrHF(hdr uint32) uint8 { + return uint8(hdr >> 24) & 0x3F +} + +ghost +decreases +pure func getSeg1Len(hdr uint32) uint8 { + return uint8(hdr >> 12) & 0x3F +} + +ghost +decreases +pure func getSeg2Len(hdr uint32) uint8 { + return uint8(hdr >> 6) & 0x3F +} + +ghost +decreases +pure func getSeg3Len(hdr uint32) uint8 { + return uint8(hdr) & 0x3F +} + +ghost +requires 0 <= offset +requires infoFieldOffset(offset) < len(raw) +requires acc(&raw[infoFieldOffset(offset)], _) +decreases +pure func getConsDir(raw []byte, offset int) bool { + return raw[infoFieldOffset(offset)] & 0x1 == 0x1 +} + +ghost +requires 0 <= offset +requires infoFieldOffset(offset) < len(raw) +requires acc(&raw[infoFieldOffset(offset)], _) +decreases +pure func getPeer(raw []byte, offset int) bool { + return raw[infoFieldOffset(offset)] & 0x2 == 0x2 +} + +ghost +requires 0 <= offset +requires infoFieldOffset(offset) + 8 < len(raw) +requires acc(&raw[infoFieldOffset(offset) + 4], _) +requires acc(&raw[infoFieldOffset(offset) + 5], _) +requires acc(&raw[infoFieldOffset(offset) + 6], _) +requires acc(&raw[infoFieldOffset(offset) + 7], _) +decreases +pure func getTimestamp(raw []byte, offset int) io.IO_ainfo { + return let idx := infoFieldOffset(offset) + 4 in + io.IO_ainfo(binary.BigEndian.Uint32(raw[idx : idx + 4])) +} + +ghost +requires len(hopfield.HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_) > 0 +decreases +pure func getHVFSet(hopfield io.IO_HF) set[io.IO_msgterm] { + return let l := hopfield.HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_ in + l[len(l) - 1].MsgTerm_FS_ +} + +ghost +requires 0 < len(hopfields) +requires 0 <= currHFIdx && currHFIdx <= len(hopfields) +requires forall idx int :: {hopfields[idx]} 0 <= idx && idx < len(hopfields) ==> + len(hopfields[idx].HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_) > 0 +decreases +pure func getUInfo(hopfields seq[io.IO_HF], currHFIdx int, consDir bool) set[io.IO_msgterm] { + return currHFIdx == len(hopfields) ? + getHVFSet(hopfields[currHFIdx-1]) : + (currHFIdx == 0 ? + getHVFSet(hopfields[currHFIdx]) : + (consDir ? + getHVFSet(hopfields[currHFIdx]) : + getHVFSet(hopfields[currHFIdx-1]))) +} From 24d19e13a8d027958f36bc6b83a04c7621bce22b Mon Sep 17 00:00:00 2001 From: mlimbeck Date: Wed, 22 Nov 2023 15:36:28 +0100 Subject: [PATCH 27/33] further improvements --- pkg/slayers/path/hopfield_spec.gobra | 25 ++ router/io-spec.gobra | 356 ++++++++++++--------------- 2 files changed, 185 insertions(+), 196 deletions(-) diff --git a/pkg/slayers/path/hopfield_spec.gobra b/pkg/slayers/path/hopfield_spec.gobra index 23510eef1..80120d335 100644 --- a/pkg/slayers/path/hopfield_spec.gobra +++ b/pkg/slayers/path/hopfield_spec.gobra @@ -19,3 +19,28 @@ package path pred (h *HopField) Mem() { acc(h) && h.ConsIngress >= 0 && h.ConsEgress >= 0 } + +//TODO how to import MetaLen from scion +ghost +decreases +pure func infoFieldOffset(currINF int) int { + return 4 + InfoLen * currINF +} + +ghost +requires 0 <= currINF +requires infoFieldOffset(currINF) < len(raw) +requires acc(&raw[infoFieldOffset(currINF)], _) +decreases +pure func ConsDir(raw []byte, currINF int) bool { + return raw[infoFieldOffset(currINF)] & 0x1 == 0x1 +} + +ghost +requires 0 <= currINF +requires infoFieldOffset(currINF) < len(raw) +requires acc(&raw[infoFieldOffset(currINF)], _) +decreases +pure func Peer(raw []byte, currINF int) bool { + return raw[infoFieldOffset(currINF)] & 0x2 == 0x2 +} diff --git a/router/io-spec.gobra b/router/io-spec.gobra index 45d9e1de6..3396e76cb 100644 --- a/router/io-spec.gobra +++ b/router/io-spec.gobra @@ -20,6 +20,8 @@ import ( sl "github.com/scionproto/scion/verification/utils/slices" "github.com/scionproto/scion/verification/io" "github.com/scionproto/scion/verification/dependencies/encoding/binary" + "github.com/scionproto/scion/pkg/slayers/path" + "github.com/scionproto/scion/pkg/slayers/path/scion" ) /** Start of io-spec helper functions **/ @@ -33,13 +35,20 @@ pure func numInfoFields(seg1Len int, seg2Len int, seg3Len int) int { ghost decreases pure func infoFieldOffset(currINF int) int { - return 4 + 8 * currINF + return scion.MetaLen + path.InfoLen * currINF } ghost decreases pure func hopFieldOffset(numINF int, currHF int) int { - return infoFieldOffset(numINF) + 12 * currHF + return infoFieldOffset(numINF) + path.HopLen * currHF +} + +ghost +decreases +pure func pktLen(seg1Len int, seg2Len int, seg3Len int) int { + return hopFieldOffset(numInfoFields(seg1Len, seg2Len, seg3Len), 0) + + path.HopLen * (seg1Len + seg2Len + seg3Len) } @@ -57,22 +66,22 @@ pure func lengthOfPrevSeg(currHF int, seg1Len int, seg2Len int, seg3Len int) (re return seg1Len > currHF ? 0 : ((seg1Len + seg2Len) > currHF ? seg1Len : seg1Len + seg2Len) } +// returns the ASid of a hopfield ghost requires 1 <= numINF requires 0 <= currHFIdx -requires hopFieldOffset(numINF, currHFIdx) + 12 <= len(raw) +requires hopFieldOffset(numINF, currHFIdx) + path.HopLen <= len(raw) requires dp.Valid() requires let idx := hopFieldOffset(numINF, currHFIdx) in acc(&raw[idx+2], _) && acc(&raw[idx+3], _) && acc(&raw[idx+4], _) && acc(&raw[idx+5], _) decreases -pure func getAsidFromIfs( +pure func asidFromIfs( dp io.DataPlaneSpec, raw []byte, numINF int, currHFIdx int, consDir bool, asid io.IO_as) (res option[io.IO_as]) { - return let idx := hopFieldOffset(numINF, currHFIdx) in let ifs := consDir ? binary.BigEndian.Uint16(raw[idx+4:idx+6]) : binary.BigEndian.Uint16(raw[idx+2:idx+4]) in let asIfPair := io.AsIfsPair{asid, io.IO_ifs(ifs)} in @@ -80,15 +89,16 @@ pure func getAsidFromIfs( some(dp.Lookup(asIfPair).asid) : none[io.IO_as]) } +// returns a list of ASids of hopfields that are before the current hopfield in a segment ghost requires 1 <= numINF requires 0 <= prevSegLen && prevSegLen <= currHFIdx -requires hopFieldOffset(numINF, currHFIdx) + 12 <= len(raw) +requires hopFieldOffset(numINF, currHFIdx) + path.HopLen <= len(raw) requires dp.Valid() requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) ensures res != none[seq[io.IO_as]] ==> len(get(res)) == currHFIdx - prevSegLen + 1 decreases currHFIdx - prevSegLen -pure func getAsidsBefore( +pure func asidsBefore( dp io.DataPlaneSpec, raw []byte, numINF int, @@ -96,14 +106,13 @@ pure func getAsidsBefore( prevSegLen int, consDir bool, asid io.IO_as) (res option[seq[io.IO_as]]) { - - return let next_asid := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getAsidFromIfs(dp, raw, numINF, currHFIdx, !consDir, asid)) in + return let next_asid := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in asidFromIfs(dp, raw, numINF, currHFIdx, !consDir, asid)) in match next_asid{ case none[io.IO_as]: none[seq[io.IO_as]] default: currHFIdx == prevSegLen ? some(seq[io.IO_as]{get(next_asid)}) : - let next_asid_seq := getAsidsBefore(dp, raw, numINF, currHFIdx-1, prevSegLen, consDir, get(next_asid)) in + let next_asid_seq := asidsBefore(dp, raw, numINF, currHFIdx-1, prevSegLen, consDir, get(next_asid)) in match next_asid_seq{ case none[seq[io.IO_as]]: none[seq[io.IO_as]] @@ -113,6 +122,7 @@ pure func getAsidsBefore( } } +// returns a list of ASids of hopfields that are after the current hopfield in a segment ghost requires 1 <= numINF requires 0 <= currHFIdx && currHFIdx < segLen @@ -121,7 +131,7 @@ requires dp.Valid() requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) ensures res != none[seq[io.IO_as]] ==> len(get(res)) == segLen - currHFIdx decreases segLen - currHFIdx + 1 -pure func getAsidsAfter( +pure func asidsAfter( dp io.DataPlaneSpec, raw []byte, numINF int, @@ -129,23 +139,23 @@ pure func getAsidsAfter( segLen int, consDir bool, asid io.IO_as) (res option[seq[io.IO_as]]) { - - return let next_asid := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getAsidFromIfs(dp, raw, numINF, currHFIdx, consDir, asid)) in - match next_asid{ - case none[io.IO_as]: - none[seq[io.IO_as]] - default: - currHFIdx == segLen - 1 ? some(seq[io.IO_as]{get(next_asid)}) : - let next_asid_seq := getAsidsAfter(dp, raw, numINF, currHFIdx+1, segLen, consDir, get(next_asid)) in - match next_asid_seq{ - case none[seq[io.IO_as]]: - none[seq[io.IO_as]] - default: - some(seq[io.IO_as]{get(next_asid)} ++ get(next_asid_seq)) - } - } -} - + return let next_asid := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in asidFromIfs(dp, raw, numINF, currHFIdx, consDir, asid)) in + match next_asid{ + case none[io.IO_as]: + none[seq[io.IO_as]] + default: + currHFIdx == segLen - 1 ? some(seq[io.IO_as]{get(next_asid)}) : + let next_asid_seq := asidsAfter(dp, raw, numINF, currHFIdx+1, segLen, consDir, get(next_asid)) in + match next_asid_seq{ + case none[seq[io.IO_as]]: + none[seq[io.IO_as]] + default: + some(seq[io.IO_as]{get(next_asid)} ++ get(next_asid_seq)) + } + } +} + +// returns a list of ASids of hopfields for CurrSeg in the abstract packet ghost requires 1 <= numINF requires 0 <= prevSegLen && prevSegLen <= currHFIdx @@ -155,14 +165,23 @@ requires dp.Valid() requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) ensures res != none[seq[io.IO_as]] ==> len(get(res)) == segLen - prevSegLen decreases -pure func getAsidSeq(dp io.DataPlaneSpec, raw []byte, numINF int, currHFIdx int, segLen int, prevSegLen int, consDir bool, asid io.IO_as) (res option[seq[io.IO_as]]) { +pure func asidForCurrSeg( + dp io.DataPlaneSpec, + raw []byte, + numINF int, + currHFIdx int, + segLen int, + prevSegLen int, + consDir bool, + asid io.IO_as) (res option[seq[io.IO_as]]) { return segLen == 0 ? some(seq[io.IO_as]{}) : - let left := getAsidsBefore(dp, raw, numINF, currHFIdx, prevSegLen, consDir, asid) in - let right := getAsidsAfter(dp, raw, numINF, currHFIdx, segLen, consDir, asid) in + let left := asidsBefore(dp, raw, numINF, currHFIdx, prevSegLen, consDir, asid) in + let right := asidsAfter(dp, raw, numINF, currHFIdx, segLen, consDir, asid) in (left == none[seq[io.IO_as]] || right == none[seq[io.IO_as]]) ? none[seq[io.IO_as]] : some(get(left) ++ get(right)[1:]) } +// returns a list of ASids of hopfields for LeftSeg in the abstract packet ghost requires dp.Valid() requires 1 <= numINF @@ -174,15 +193,16 @@ requires currINFIdx <= numINF + 1 requires 1 <= currINFIdx && currINFIdx < 4 requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases -pure func getAsidsLeft(dp io.DataPlaneSpec, raw []byte, numINF int, currINFIdx int, seg1Len int, seg2Len int, seg3Len int, asid io.IO_as) (res option[seq[io.IO_as]]) { - return let consDir := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getConsDir(raw, currINFIdx) in +pure func asidsForLeftSeg(dp io.DataPlaneSpec, raw []byte, numINF int, currINFIdx int, seg1Len int, seg2Len int, seg3Len int, asid io.IO_as) (res option[seq[io.IO_as]]) { + return let consDir := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in path.ConsDir(raw, currINFIdx) in (currINFIdx == 1 && seg2Len > 0) ? - getAsidSeq(dp, raw, numINF, seg1Len, seg1Len+seg2Len, seg1Len, consDir, asid) : + asidForCurrSeg(dp, raw, numINF, seg1Len, seg1Len+seg2Len, seg1Len, consDir, asid) : (currINFIdx == 2 && seg2Len > 0 && seg3Len > 0) ? - getAsidSeq(dp, raw, numINF, seg1Len+seg2Len, seg1Len+seg2Len+seg3Len, seg1Len+seg2Len, consDir, asid) : + asidForCurrSeg(dp, raw, numINF, seg1Len+seg2Len, seg1Len+seg2Len+seg3Len, seg1Len+seg2Len, consDir, asid) : some(seq[io.IO_as]{}) } +// returns a list of ASids of hopfields for RightSeg in the abstract packet ghost requires dp.Valid() requires 1 <= numINF @@ -196,16 +216,17 @@ requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) ensures (currINFIdx == 0 && res != none[seq[io.IO_as]]) ==> len(get(res)) == seg1Len ensures (currINFIdx == 1 && seg2Len > 0 && res != none[seq[io.IO_as]]) ==> len(get(res)) == seg2Len decreases -pure func getAsidsRight(dp io.DataPlaneSpec, raw []byte, numINF int, currINFIdx int, seg1Len int, seg2Len int, seg3Len int, asid io.IO_as) (res option[seq[io.IO_as]]) { +pure func asidsForRightSeg(dp io.DataPlaneSpec, raw []byte, numINF int, currINFIdx int, seg1Len int, seg2Len int, seg3Len int, asid io.IO_as) (res option[seq[io.IO_as]]) { return (currINFIdx == 1 && seg2Len > 0) ? - let consDir := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getConsDir(raw, currINFIdx) in - getAsidSeq(dp, raw, numINF, seg1Len+seg2Len-1, seg1Len+seg2Len, seg1Len, consDir, asid) : + let consDir := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in path.ConsDir(raw, currINFIdx) in + asidForCurrSeg(dp, raw, numINF, seg1Len+seg2Len-1, seg1Len+seg2Len, seg1Len, consDir, asid) : (currINFIdx == 0) ? - let consDir := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getConsDir(raw, currINFIdx) in - getAsidSeq(dp, raw, numINF, seg1Len-1, seg1Len, 0, consDir, asid) : + let consDir := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in path.ConsDir(raw, currINFIdx) in + asidForCurrSeg(dp, raw, numINF, seg1Len-1, seg1Len, 0, consDir, asid) : some(seq[io.IO_as]{}) } +// returns a list of ASids of hopfields for MidSeg in the abstract packet ghost requires dp.Valid() requires 1 <= numINF @@ -219,23 +240,23 @@ requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) requires (currINFIdx == 4 && seg2Len > 0) ==> asid != none[io.IO_as] requires (currINFIdx == 2 && seg2Len > 0 && seg3Len > 0) ==> asid != none[io.IO_as] decreases -pure func getAsidsMid(dp io.DataPlaneSpec, raw []byte, numINF int, currINFIdx int, seg1Len int, seg2Len int, seg3Len int, asid option[io.IO_as]) (res option[seq[io.IO_as]]) { +pure func asidsForMidSeg(dp io.DataPlaneSpec, raw []byte, numINF int, currINFIdx int, seg1Len int, seg2Len int, seg3Len int, asid option[io.IO_as]) (res option[seq[io.IO_as]]) { return (currINFIdx == 4 && seg2Len > 0) ? - let consDir := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getConsDir(raw, 1) in - getAsidSeq(dp, raw, numINF, seg1Len-1, seg1Len, 0, consDir, get(asid)) : + let consDir := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in path.ConsDir(raw, 1) in + asidForCurrSeg(dp, raw, numINF, seg1Len-1, seg1Len, 0, consDir, get(asid)) : (currINFIdx == 2 && seg2Len > 0 && seg3Len > 0) ? - let consDir := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getConsDir(raw, 2) in - getAsidSeq(dp, raw, numINF, seg1Len + seg2Len, seg1Len + seg2Len + seg3Len, seg1Len + seg2Len, consDir, get(asid)) : + let consDir := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in path.ConsDir(raw, 2) in + asidForCurrSeg(dp, raw, numINF, seg1Len + seg2Len, seg1Len + seg2Len + seg3Len, seg1Len + seg2Len, consDir, get(asid)) : some(seq[io.IO_as]{}) } ghost -requires idx + 12 <= len(raw) +requires idx + path.HopLen <= len(raw) requires 0 <= idx requires acc(&raw[idx+2], _) && acc(&raw[idx+3], _) && acc(&raw[idx+4], _) && acc(&raw[idx+5], _) ensures len(res.HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_) > 0 decreases -pure func getHopField(raw []byte, idx int, beta set[io.IO_msgterm], asid io.IO_as, ainfo io.IO_ainfo) (res io.IO_HF) { +pure func hopField(raw []byte, idx int, beta set[io.IO_msgterm], asid io.IO_as, ainfo io.IO_ainfo) (res io.IO_HF) { return let inif2 := binary.BigEndian.Uint16(raw[idx+2:idx+4]) in let egif2 := binary.BigEndian.Uint16(raw[idx+4:idx+6]) in let op_inif2 := inif2 == 0 ? none[io.IO_ifs] : some(io.IO_ifs(inif2)) in @@ -253,153 +274,141 @@ pure func getHopField(raw []byte, idx int, beta set[io.IO_msgterm], asid io.IO_a ghost requires 0 <= offset -requires 0 <= currHFIdx && currHFIdx <= segLen -requires offset + 12 * segLen <= len(raw) +requires 0 <= currHFIdx && currHFIdx <= len(asid) +requires offset + path.HopLen * len(asid) <= len(raw) requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -requires len(asid) == segLen -ensures len(res) == segLen - currHFIdx +ensures len(res) == len(asid) - currHFIdx ensures forall k int :: {res[k]} 0 <= k && k < len(res) ==> len(res[k].HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_) > 0 -decreases segLen - currHFIdx -pure func getHopfieldsConsDir( +decreases len(asid) - currHFIdx +pure func hopFieldsConsDir( raw []byte, offset int, currHFIdx int, - segLen int, beta set[io.IO_msgterm], asid seq[io.IO_as], ainfo io.IO_ainfo) (res seq[io.IO_HF]) { - - return currHFIdx == segLen ? seq[io.IO_HF]{} : + return currHFIdx == len(asid) ? seq[io.IO_HF]{} : let hf := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in - getHopField(raw, offset + 12 * currHFIdx, beta, asid[currHFIdx], ainfo)) in - seq[io.IO_HF]{hf} ++ getHopfieldsConsDir(raw, offset, currHFIdx + 1, segLen, (beta union set[io.IO_msgterm]{hf.HVF}), asid, ainfo) + hopField(raw, offset + path.HopLen * currHFIdx, beta, asid[currHFIdx], ainfo)) in + seq[io.IO_HF]{hf} ++ hopFieldsConsDir(raw, offset, currHFIdx + 1, (beta union set[io.IO_msgterm]{hf.HVF}), asid, ainfo) } ghost requires 0 <= offset -requires -1 <= currHFIdx && currHFIdx < segLen -requires offset + 12 * currHFIdx + 12 <= len(raw) +requires -1 <= currHFIdx && currHFIdx < len(asid) +requires offset + path.HopLen * currHFIdx + path.HopLen <= len(raw) requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) -requires len(asid) == segLen ensures len(res) == currHFIdx + 1 ensures forall k int :: {res[k]} 0 <= k && k < len(res) ==> len(res[k].HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_) > 0 decreases currHFIdx + 1 -pure func getHopfieldsNotConsDir( +pure func hopFieldsNotConsDir( raw []byte, offset int, currHFIdx int, - segLen int, beta set[io.IO_msgterm], asid seq[io.IO_as], ainfo io.IO_ainfo) (res seq[io.IO_HF]) { - return currHFIdx == -1 ? seq[io.IO_HF]{} : let hf := (unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in - getHopField(raw, offset + 12 * currHFIdx, beta, asid[currHFIdx], ainfo)) in - getHopfieldsNotConsDir(raw, offset, currHFIdx -1, segLen, (beta union set[io.IO_msgterm]{hf.HVF}), asid, ainfo) ++ seq[io.IO_HF]{hf} + hopField(raw, offset + path.HopLen * currHFIdx, beta, asid[currHFIdx], ainfo)) in + hopFieldsNotConsDir(raw, offset, currHFIdx -1, (beta union set[io.IO_msgterm]{hf.HVF}), asid, ainfo) ++ seq[io.IO_HF]{hf} } ghost requires -1 <= currHFIdx && currHFIdx < len(hopfields) decreases currHFIdx + 1 -pure func getSegPast(hopfields seq[io.IO_HF], currHFIdx int) seq[io.IO_HF] { +pure func segPast(hopfields seq[io.IO_HF], currHFIdx int) seq[io.IO_HF] { return currHFIdx == -1 ? seq[io.IO_HF]{} : - seq[io.IO_HF]{hopfields[currHFIdx]} ++ getSegPast(hopfields, currHFIdx - 1) + seq[io.IO_HF]{hopfields[currHFIdx]} ++ segPast(hopfields, currHFIdx - 1) } ghost requires 0 <= currHFIdx && currHFIdx <= len(hopfields) decreases len(hopfields) - currHFIdx -pure func getSegFuture(hopfields seq[io.IO_HF], currHFIdx int) seq[io.IO_HF] { +pure func segFuture(hopfields seq[io.IO_HF], currHFIdx int) seq[io.IO_HF] { return currHFIdx == len(hopfields) ? seq[io.IO_HF]{} : - seq[io.IO_HF]{hopfields[currHFIdx]} ++ getSegFuture(hopfields, currHFIdx + 1) + seq[io.IO_HF]{hopfields[currHFIdx]} ++ segFuture(hopfields, currHFIdx + 1) } ghost requires -1 <= currHFIdx && currHFIdx < len(hopfields) decreases currHFIdx + 1 -pure func getSegHistory(hopfields seq[io.IO_HF], currHFIdx int) seq[io.IO_ahi] { +pure func segHistory(hopfields seq[io.IO_HF], currHFIdx int) seq[io.IO_ahi] { return currHFIdx == -1 ? seq[io.IO_ahi]{} : - seq[io.IO_ahi]{hopfields[currHFIdx].Toab()} ++ getSegHistory(hopfields, currHFIdx - 1) + seq[io.IO_ahi]{hopfields[currHFIdx].Toab()} ++ segHistory(hopfields, currHFIdx - 1) } ghost requires 0 <= offset -requires 0 < segLen -requires offset + 12 * segLen <= len(raw) -requires 0 <= currHFIdx && currHFIdx <= segLen -requires len(asid) == segLen +requires 0 < len(asid) +requires offset + path.HopLen * len(asid) <= len(raw) +requires 0 <= currHFIdx && currHFIdx <= len(asid) requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases -pure func getSegment(raw []byte, +pure func segment(raw []byte, offset int, currHFIdx int, - segLen int, asid seq[io.IO_as], ainfo io.IO_ainfo, consDir bool, peer bool) io.IO_seg2 { - return let hopfields := consDir ? - getHopfieldsConsDir(raw, offset, 0, segLen, set[io.IO_msgterm]{}, asid, ainfo) : - getHopfieldsNotConsDir(raw, offset, segLen - 1, segLen, set[io.IO_msgterm]{}, asid, ainfo) in - let uinfo := getUInfo(hopfields, currHFIdx, consDir) in + hopFieldsConsDir(raw, offset, 0, set[io.IO_msgterm]{}, asid, ainfo) : + hopFieldsNotConsDir(raw, offset, len(asid) - 1, set[io.IO_msgterm]{}, asid, ainfo) in + let uinfo := uInfo(hopfields, currHFIdx, consDir) in io.IO_seg2(io.IO_seg3_{ AInfo :ainfo, UInfo : uinfo, ConsDir : consDir, Peer : peer, - Past : getSegPast(hopfields, currHFIdx - 1), - Future : getSegFuture(hopfields, currHFIdx), - History : getSegHistory(hopfields, currHFIdx - 1), + Past : segPast(hopfields, currHFIdx - 1), + Future : segFuture(hopfields, currHFIdx), + History : segHistory(hopfields, currHFIdx - 1), }) } ghost requires 4 + 8 * currINFIdx + 8 <= offset -requires 0 < segLen -requires offset + 12 * segLen <= len(raw) -requires 0 <= currHFIdx && currHFIdx <= segLen +requires 0 < len(asid) +requires offset + path.HopLen * len(asid) <= len(raw) +requires 0 <= currHFIdx && currHFIdx <= len(asid) requires 0 <= currINFIdx && currINFIdx < 3 -requires len(asid) == segLen requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases -pure func getCurrSeg(raw []byte, offset int, currINFIdx int, currHFIdx int, segLen int, asid seq[io.IO_as]) io.IO_seg3 { +pure func currSeg(raw []byte, offset int, currINFIdx int, currHFIdx int, asid seq[io.IO_as]) io.IO_seg3 { return unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in - let ainfo := getTimestamp(raw, currINFIdx) in - let consDir := getConsDir(raw, currINFIdx) in - let peer := getPeer(raw, currINFIdx) in - getSegment(raw, offset, currHFIdx, segLen, asid, ainfo, consDir, peer) + let ainfo := timestamp(raw, currINFIdx) in + let consDir := path.ConsDir(raw, currINFIdx) in + let peer := path.Peer(raw, currINFIdx) in + segment(raw, offset, currHFIdx, asid, ainfo, consDir, peer) } ghost requires 0 < seg1Len requires 0 <= seg2Len requires 0 <= seg3Len -requires 4 + 8 * numInfoFields(seg1Len, seg2Len, seg3Len) == offset -requires offset + 12 * (seg1Len + seg2Len + seg3Len) <= len(raw) +requires pktLen(seg1Len, seg2Len, seg3Len) <= len(raw) requires 1 <= currINFIdx && currINFIdx < 4 requires (currINFIdx == 1 && seg2Len > 0) ==> len(asid) == seg2Len requires (currINFIdx == 2 && seg2Len > 0 && seg3Len > 0) ==> len(asid) == seg3Len requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases -pure func getLeftSeg( +pure func leftSeg( raw []byte, - offset int, currINFIdx int, seg1Len int, seg2Len int, seg3Len int, asid seq[io.IO_as]) option[io.IO_seg3] { - - return (currINFIdx == 1 && seg2Len > 0) ? - some(getCurrSeg(raw, offset + 12 * seg1Len, currINFIdx, 0, seg2Len, asid)) : + return let offset := hopFieldOffset(numInfoFields(seg1Len, seg2Len, seg3Len), 0) in + (currINFIdx == 1 && seg2Len > 0) ? + some(currSeg(raw, offset + path.HopLen * seg1Len, currINFIdx, 0, asid)) : (currINFIdx == 2 && seg2Len > 0 && seg3Len > 0) ? - some(getCurrSeg(raw, offset + 12 * (seg1Len + seg2Len), currINFIdx, 0, seg3Len, asid)) : + some(currSeg(raw, offset + path.HopLen * (seg1Len + seg2Len), currINFIdx, 0, asid)) : none[io.IO_seg3] } @@ -407,26 +416,24 @@ ghost requires 0 < seg1Len requires 0 <= seg2Len requires 0 <= seg3Len -requires 4 + 8 * numInfoFields(seg1Len, seg2Len, seg3Len) == offset -requires offset + 12 * (seg1Len + seg2Len + seg3Len) <= len(raw) +requires pktLen(seg1Len, seg2Len, seg3Len) <= len(raw) requires -1 <= currINFIdx && currINFIdx < 2 requires (currINFIdx == 1 && seg2Len > 0 && seg3Len > 0) ==> len(asid) == seg2Len requires (currINFIdx == 0 && seg2Len > 0) ==> len(asid) == seg1Len requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases -pure func getRightSeg( +pure func rightSeg( raw []byte, - offset int, currINFIdx int, seg1Len int, seg2Len int, seg3Len int, asid seq[io.IO_as]) option[io.IO_seg3] { - - return (currINFIdx == 1 && seg2Len > 0 && seg3Len > 0) ? - some(getCurrSeg(raw, offset + 12 * seg1Len, currINFIdx, seg2Len, seg2Len, asid)) : + return let offset := hopFieldOffset(numInfoFields(seg1Len, seg2Len, seg3Len), 0) in + (currINFIdx == 1 && seg2Len > 0 && seg3Len > 0) ? + some(currSeg(raw, offset + path.HopLen * seg1Len, currINFIdx, seg2Len, asid)) : (currINFIdx == 0 && seg2Len > 0) ? - some(getCurrSeg(raw, offset, currINFIdx, seg1Len, seg1Len, asid)) : + some(currSeg(raw, offset, currINFIdx, seg1Len, asid)) : none[io.IO_seg3] } @@ -434,26 +441,24 @@ ghost requires 0 < seg1Len requires 0 <= seg2Len requires 0 <= seg3Len -requires 4 + 8 * numInfoFields(seg1Len, seg2Len, seg3Len) == offset -requires offset + 12 * (seg1Len + seg2Len + seg3Len) <= len(raw) +requires pktLen(seg1Len, seg2Len, seg3Len) <= len(raw) requires 2 <= currINFIdx && currINFIdx < 5 requires (currINFIdx == 4 && seg2Len > 0) ==> len(asid) == seg1Len requires (currINFIdx == 2 && seg2Len > 0 && seg3Len > 0) ==> len(asid) == seg3Len requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) decreases -pure func getMidSeg( +pure func midSeg( raw []byte, - offset int, currINFIdx int, seg1Len int, seg2Len int, seg3Len int, asid seq[io.IO_as]) option[io.IO_seg3] { - - return (currINFIdx == 4 && seg2Len > 0) ? - some(getCurrSeg(raw, offset, 0, seg1Len, seg1Len, asid)) : + return let offset := hopFieldOffset(numInfoFields(seg1Len, seg2Len, seg3Len), 0) in + (currINFIdx == 4 && seg2Len > 0) ? + some(currSeg(raw, offset, 0, seg1Len, asid)) : (currINFIdx == 2 && seg2Len > 0 && seg3Len > 0) ? - some(getCurrSeg(raw, offset + 12 * (seg1Len + seg2Len), currINFIdx, 0, seg3Len, asid)) : + some(currSeg(raw, offset + path.HopLen * (seg1Len + seg2Len), currINFIdx, 0, asid)) : none[io.IO_seg3] } @@ -463,92 +468,51 @@ requires len(raw) > 4 requires acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) requires unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in let hdr := binary.BigEndian.Uint32(raw[0:4]) in - 0 <= getCurrINF(hdr) && getCurrINF(hdr) < 3 && - getCurrINF(hdr) + 1 <= numInfoFields(int(getSeg1Len(hdr)), int(getSeg2Len(hdr)), int(getSeg3Len(hdr))) && - 0 <= getCurrHF(hdr) && getCurrHF(hdr) < getSeg1Len(hdr) + getSeg2Len(hdr) + getSeg3Len(hdr) && - 0 < getSeg1Len(hdr) && - 0 <= getSeg2Len(hdr) && - 0 <= getSeg3Len(hdr) && - 4 + 8 * numInfoFields(int(getSeg1Len(hdr)), int(getSeg2Len(hdr)), int(getSeg3Len(hdr))) + 12 * (int(getSeg1Len(hdr)) + int(getSeg2Len(hdr)) + int(getSeg3Len(hdr))) == len(raw) + let metaHdr := scion.DecodedFrom(hdr) in + let seg1 := int(metaHdr.SegLen[0]) in + let seg2 := int(metaHdr.SegLen[1]) in + let seg3 := int(metaHdr.SegLen[2]) in + let base := scion.Base{metaHdr, + numInfoFields(seg1, seg2, seg3), + seg1 + seg2 + seg3} in + metaHdr.InBounds() && + 0 < metaHdr.SegLen[0] && + base.ValidCurrInfSpec() && + base.ValidCurrHfSpec() && + len(raw) == pktLen(seg1, seg2, seg3) decreases -pure func getPkt(dp io.DataPlaneSpec, raw []byte, asid io.IO_as) option[io.IO_pkt2] { +pure func absPkt(dp io.DataPlaneSpec, raw []byte, asid io.IO_as) option[io.IO_pkt2] { return let hdr := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in binary.BigEndian.Uint32(raw[0:4]) in - let currINFIdx := int(getCurrINF(hdr)) in - let currHFIdx := int(getCurrHF(hdr)) in - let seg1Len := int(getSeg1Len(hdr)) in - let seg2Len := int(getSeg2Len(hdr)) in - let seg3Len := int(getSeg3Len(hdr)) in + let metaHdr := scion.DecodedFrom(hdr) in + let currINFIdx := int(metaHdr.CurrINF) in + let currHFIdx := int(metaHdr.CurrHF) in + let seg1Len := int(metaHdr.SegLen[0]) in + let seg2Len := int(metaHdr.SegLen[1]) in + let seg3Len := int(metaHdr.SegLen[2]) in let segLen := lengthOfCurrSeg(currHFIdx, seg1Len, seg2Len, seg3Len) in let prevSegLen := lengthOfPrevSeg(currHFIdx, seg1Len, seg2Len, seg3Len) in - let numINF := int(numInfoFields(seg1Len, seg2Len, seg3Len)) in - let offset := 4 + 8 * numINF in - let consDir := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in getConsDir(raw, currINFIdx) in - let currAsidSeq := getAsidSeq(dp, raw, numINF, currHFIdx, prevSegLen+segLen, prevSegLen, consDir, dp.Asid()) in + let numINF := numInfoFields(seg1Len, seg2Len, seg3Len) in + let offset := hopFieldOffset(numINF, 0) in + let consDir := unfolding acc(sl.AbsSlice_Bytes(raw, 0, len(raw)), _) in path.ConsDir(raw, currINFIdx) in + let currAsidSeq := asidForCurrSeg(dp, raw, numINF, currHFIdx, prevSegLen+segLen, prevSegLen, consDir, dp.Asid()) in currAsidSeq == none[seq[io.IO_as]] ? none[io.IO_pkt2] : let last := get(currAsidSeq)[segLen-1] in let first := get(currAsidSeq)[0] in - let leftAsidSeq := getAsidsLeft(dp, raw, numINF, currINFIdx + 1, seg1Len, seg2Len, seg3Len, last) in - let rightAsidSeq := getAsidsRight(dp, raw, numINF, currINFIdx - 1, seg1Len, seg2Len, seg3Len, first) in + let leftAsidSeq := asidsForLeftSeg(dp, raw, numINF, currINFIdx + 1, seg1Len, seg2Len, seg3Len, last) in + let rightAsidSeq := asidsForRightSeg(dp, raw, numINF, currINFIdx - 1, seg1Len, seg2Len, seg3Len, first) in (leftAsidSeq == none[seq[io.IO_as]] || rightAsidSeq == none[seq[io.IO_as]]) ? none[io.IO_pkt2] : let midAsid := ((currINFIdx == 0 && seg2Len > 0 && seg3Len > 0) ? some(get(leftAsidSeq)[len(get(leftAsidSeq))-1]) : (currINFIdx == 2 && seg2Len > 0) ? some(get(rightAsidSeq)[0]) : none[io.IO_as]) in - let midAsidSeq := getAsidsMid(dp, raw, numINF, currINFIdx + 2, seg1Len, seg2Len, seg3Len, midAsid) in + let midAsidSeq := asidsForMidSeg(dp, raw, numINF, currINFIdx + 2, seg1Len, seg2Len, seg3Len, midAsid) in midAsidSeq == none[seq[io.IO_as]] ? none[io.IO_pkt2] : some(io.IO_pkt2(io.IO_Packet2{ - CurrSeg : getCurrSeg(raw, offset+prevSegLen, currINFIdx, currHFIdx-prevSegLen, segLen, get(currAsidSeq)), - LeftSeg : getLeftSeg(raw, offset, currINFIdx + 1, seg1Len, seg2Len , seg3Len, get(leftAsidSeq)), - MidSeg : getMidSeg(raw, offset, currINFIdx + 2, seg1Len, seg2Len , seg3Len, get(midAsidSeq)), - RightSeg : getRightSeg(raw, offset, currINFIdx - 1, seg1Len, seg2Len , seg3Len, get(rightAsidSeq)), + CurrSeg : currSeg(raw, offset+prevSegLen, currINFIdx, currHFIdx-prevSegLen, get(currAsidSeq)), + LeftSeg : leftSeg(raw, currINFIdx + 1, seg1Len, seg2Len , seg3Len, get(leftAsidSeq)), + MidSeg : midSeg(raw, currINFIdx + 2, seg1Len, seg2Len , seg3Len, get(midAsidSeq)), + RightSeg : rightSeg(raw, currINFIdx - 1, seg1Len, seg2Len , seg3Len, get(rightAsidSeq)), })) } -ghost -decreases -pure func getCurrINF(hdr uint32) uint8 { - return uint8(hdr >> 30) -} - -ghost -decreases -pure func getCurrHF(hdr uint32) uint8 { - return uint8(hdr >> 24) & 0x3F -} - -ghost -decreases -pure func getSeg1Len(hdr uint32) uint8 { - return uint8(hdr >> 12) & 0x3F -} - -ghost -decreases -pure func getSeg2Len(hdr uint32) uint8 { - return uint8(hdr >> 6) & 0x3F -} - -ghost -decreases -pure func getSeg3Len(hdr uint32) uint8 { - return uint8(hdr) & 0x3F -} - -ghost -requires 0 <= offset -requires infoFieldOffset(offset) < len(raw) -requires acc(&raw[infoFieldOffset(offset)], _) -decreases -pure func getConsDir(raw []byte, offset int) bool { - return raw[infoFieldOffset(offset)] & 0x1 == 0x1 -} - -ghost -requires 0 <= offset -requires infoFieldOffset(offset) < len(raw) -requires acc(&raw[infoFieldOffset(offset)], _) -decreases -pure func getPeer(raw []byte, offset int) bool { - return raw[infoFieldOffset(offset)] & 0x2 == 0x2 -} ghost requires 0 <= offset @@ -558,7 +522,7 @@ requires acc(&raw[infoFieldOffset(offset) + 5], _) requires acc(&raw[infoFieldOffset(offset) + 6], _) requires acc(&raw[infoFieldOffset(offset) + 7], _) decreases -pure func getTimestamp(raw []byte, offset int) io.IO_ainfo { +pure func timestamp(raw []byte, offset int) io.IO_ainfo { return let idx := infoFieldOffset(offset) + 4 in io.IO_ainfo(binary.BigEndian.Uint32(raw[idx : idx + 4])) } @@ -566,7 +530,7 @@ pure func getTimestamp(raw []byte, offset int) io.IO_ainfo { ghost requires len(hopfield.HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_) > 0 decreases -pure func getHVFSet(hopfield io.IO_HF) set[io.IO_msgterm] { +pure func hvfSet(hopfield io.IO_HF) set[io.IO_msgterm] { return let l := hopfield.HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_ in l[len(l) - 1].MsgTerm_FS_ } @@ -577,12 +541,12 @@ requires 0 <= currHFIdx && currHFIdx <= len(hopfields) requires forall idx int :: {hopfields[idx]} 0 <= idx && idx < len(hopfields) ==> len(hopfields[idx].HVF.MsgTerm_Hash_.MsgTerm_MPair_2.MsgTerm_L_) > 0 decreases -pure func getUInfo(hopfields seq[io.IO_HF], currHFIdx int, consDir bool) set[io.IO_msgterm] { +pure func uInfo(hopfields seq[io.IO_HF], currHFIdx int, consDir bool) set[io.IO_msgterm] { return currHFIdx == len(hopfields) ? - getHVFSet(hopfields[currHFIdx-1]) : + hvfSet(hopfields[currHFIdx-1]) : (currHFIdx == 0 ? - getHVFSet(hopfields[currHFIdx]) : + hvfSet(hopfields[currHFIdx]) : (consDir ? - getHVFSet(hopfields[currHFIdx]) : - getHVFSet(hopfields[currHFIdx-1]))) + hvfSet(hopfields[currHFIdx]) : + hvfSet(hopfields[currHFIdx-1]))) } From e923c4046a2030f62a1ca09126b5dc26598dcec2 Mon Sep 17 00:00:00 2001 From: mlimbeck Date: Wed, 22 Nov 2023 15:57:06 +0100 Subject: [PATCH 28/33] replace 4 by its constant InfoLen --- router/io-spec.gobra | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/router/io-spec.gobra b/router/io-spec.gobra index 3396e76cb..7f908e82f 100644 --- a/router/io-spec.gobra +++ b/router/io-spec.gobra @@ -372,7 +372,7 @@ pure func segment(raw []byte, } ghost -requires 4 + 8 * currINFIdx + 8 <= offset +requires infoFieldOffset(currINFIdx) + path.InfoLen <= offset requires 0 < len(asid) requires offset + path.HopLen * len(asid) <= len(raw) requires 0 <= currHFIdx && currHFIdx <= len(asid) From 45b432ed28bf1d67f7d1f445aaf4cfbeb3d32e3a Mon Sep 17 00:00:00 2001 From: mlimbeck Date: Wed, 22 Nov 2023 17:16:20 +0100 Subject: [PATCH 29/33] readability improvement --- router/io-spec.gobra | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/router/io-spec.gobra b/router/io-spec.gobra index 7f908e82f..fc6b6f8ec 100644 --- a/router/io-spec.gobra +++ b/router/io-spec.gobra @@ -20,8 +20,8 @@ import ( sl "github.com/scionproto/scion/verification/utils/slices" "github.com/scionproto/scion/verification/io" "github.com/scionproto/scion/verification/dependencies/encoding/binary" - "github.com/scionproto/scion/pkg/slayers/path" - "github.com/scionproto/scion/pkg/slayers/path/scion" + "github.com/scionproto/scion/pkg/slayers/path" + "github.com/scionproto/scion/pkg/slayers/path/scion" ) /** Start of io-spec helper functions **/ From 8f15113679d31b2be35d892f08780ca0e07678f8 Mon Sep 17 00:00:00 2001 From: mlimbeck Date: Wed, 22 Nov 2023 17:17:03 +0100 Subject: [PATCH 30/33] constant for metaLen in package path --- pkg/slayers/path/hopfield_spec.gobra | 5 +++-- pkg/slayers/path/scion/base_spec.gobra | 8 ++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/pkg/slayers/path/hopfield_spec.gobra b/pkg/slayers/path/hopfield_spec.gobra index 80120d335..c320cd73d 100644 --- a/pkg/slayers/path/hopfield_spec.gobra +++ b/pkg/slayers/path/hopfield_spec.gobra @@ -16,15 +16,16 @@ package path +ghost const MetaLen = 4 + pred (h *HopField) Mem() { acc(h) && h.ConsIngress >= 0 && h.ConsEgress >= 0 } -//TODO how to import MetaLen from scion ghost decreases pure func infoFieldOffset(currINF int) int { - return 4 + InfoLen * currINF + return MetaLen + InfoLen * currINF } ghost diff --git a/pkg/slayers/path/scion/base_spec.gobra b/pkg/slayers/path/scion/base_spec.gobra index 04c3031ab..b933026cb 100644 --- a/pkg/slayers/path/scion/base_spec.gobra +++ b/pkg/slayers/path/scion/base_spec.gobra @@ -18,6 +18,7 @@ package scion import ( "encoding/binary" + "github.com/scionproto/scion/pkg/slayers/path" sl "github.com/scionproto/scion/verification/utils/slices" ) @@ -44,6 +45,13 @@ pred (b *Base) Mem() { (0 < b.NumINF ==> 0 < b.NumHops) } +ghost +ensures res +decreases +pure func validMetaLenInPath() (res bool) { + return MetaLen == path.MetaLen +} + ghost decreases pure func (b Base) ValidCurrInfSpec() bool { From 503b0e04885d7540d401f13b1311c2cc533f765c Mon Sep 17 00:00:00 2001 From: Markus Limbeck <92801626+mlimbeck@users.noreply.github.com> Date: Wed, 22 Nov 2023 20:16:47 +0100 Subject: [PATCH 31/33] Update router/io-spec.gobra MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: João Pereira --- router/io-spec.gobra | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/router/io-spec.gobra b/router/io-spec.gobra index fc6b6f8ec..eaa11af11 100644 --- a/router/io-spec.gobra +++ b/router/io-spec.gobra @@ -177,7 +177,8 @@ pure func asidForCurrSeg( return segLen == 0 ? some(seq[io.IO_as]{}) : let left := asidsBefore(dp, raw, numINF, currHFIdx, prevSegLen, consDir, asid) in let right := asidsAfter(dp, raw, numINF, currHFIdx, segLen, consDir, asid) in - (left == none[seq[io.IO_as]] || right == none[seq[io.IO_as]]) ? none[seq[io.IO_as]] : + (left == none[seq[io.IO_as]] || right == none[seq[io.IO_as]]) ? + none[seq[io.IO_as]] : some(get(left) ++ get(right)[1:]) } From c292a84a1ece18349c6555219c0a9965ee79ae74 Mon Sep 17 00:00:00 2001 From: mlimbeck Date: Wed, 22 Nov 2023 20:20:59 +0100 Subject: [PATCH 32/33] minor improvements --- pkg/slayers/path/hopfield_spec.gobra | 14 +++++++------- router/dataplane_spec.gobra | 2 -- router/io-spec.gobra | 24 ++++++++---------------- 3 files changed, 15 insertions(+), 25 deletions(-) diff --git a/pkg/slayers/path/hopfield_spec.gobra b/pkg/slayers/path/hopfield_spec.gobra index c320cd73d..53a84309e 100644 --- a/pkg/slayers/path/hopfield_spec.gobra +++ b/pkg/slayers/path/hopfield_spec.gobra @@ -24,24 +24,24 @@ pred (h *HopField) Mem() { ghost decreases -pure func infoFieldOffset(currINF int) int { +pure func InfoFieldOffset(currINF int) int { return MetaLen + InfoLen * currINF } ghost requires 0 <= currINF -requires infoFieldOffset(currINF) < len(raw) -requires acc(&raw[infoFieldOffset(currINF)], _) +requires InfoFieldOffset(currINF) < len(raw) +requires acc(&raw[InfoFieldOffset(currINF)], _) decreases pure func ConsDir(raw []byte, currINF int) bool { - return raw[infoFieldOffset(currINF)] & 0x1 == 0x1 + return raw[InfoFieldOffset(currINF)] & 0x1 == 0x1 } ghost requires 0 <= currINF -requires infoFieldOffset(currINF) < len(raw) -requires acc(&raw[infoFieldOffset(currINF)], _) +requires InfoFieldOffset(currINF) < len(raw) +requires acc(&raw[InfoFieldOffset(currINF)], _) decreases pure func Peer(raw []byte, currINF int) bool { - return raw[infoFieldOffset(currINF)] & 0x2 == 0x2 + return raw[InfoFieldOffset(currINF)] & 0x2 == 0x2 } diff --git a/router/dataplane_spec.gobra b/router/dataplane_spec.gobra index 33094c185..abd138460 100644 --- a/router/dataplane_spec.gobra +++ b/router/dataplane_spec.gobra @@ -21,8 +21,6 @@ import ( "hash" . "github.com/scionproto/scion/verification/utils/definitions" sl "github.com/scionproto/scion/verification/utils/slices" - "github.com/scionproto/scion/verification/io" - "github.com/scionproto/scion/verification/dependencies/encoding/binary" "github.com/scionproto/scion/pkg/scrypto" "github.com/scionproto/scion/pkg/addr" ) diff --git a/router/io-spec.gobra b/router/io-spec.gobra index eaa11af11..dd742fc71 100644 --- a/router/io-spec.gobra +++ b/router/io-spec.gobra @@ -24,24 +24,16 @@ import ( "github.com/scionproto/scion/pkg/slayers/path/scion" ) -/** Start of io-spec helper functions **/ - ghost decreases pure func numInfoFields(seg1Len int, seg2Len int, seg3Len int) int { return seg3Len > 0 ? 3 : (seg2Len > 0 ? 2 : 1) } -ghost -decreases -pure func infoFieldOffset(currINF int) int { - return scion.MetaLen + path.InfoLen * currINF -} - ghost decreases pure func hopFieldOffset(numINF int, currHF int) int { - return infoFieldOffset(numINF) + path.HopLen * currHF + return path.InfoFieldOffset(numINF) + path.HopLen * currHF } ghost @@ -373,7 +365,7 @@ pure func segment(raw []byte, } ghost -requires infoFieldOffset(currINFIdx) + path.InfoLen <= offset +requires path.InfoFieldOffset(currINFIdx) + path.InfoLen <= offset requires 0 < len(asid) requires offset + path.HopLen * len(asid) <= len(raw) requires 0 <= currHFIdx && currHFIdx <= len(asid) @@ -517,14 +509,14 @@ pure func absPkt(dp io.DataPlaneSpec, raw []byte, asid io.IO_as) option[io.IO_pk ghost requires 0 <= offset -requires infoFieldOffset(offset) + 8 < len(raw) -requires acc(&raw[infoFieldOffset(offset) + 4], _) -requires acc(&raw[infoFieldOffset(offset) + 5], _) -requires acc(&raw[infoFieldOffset(offset) + 6], _) -requires acc(&raw[infoFieldOffset(offset) + 7], _) +requires path.InfoFieldOffset(offset) + 8 < len(raw) +requires acc(&raw[path.InfoFieldOffset(offset) + 4], _) +requires acc(&raw[path.InfoFieldOffset(offset) + 5], _) +requires acc(&raw[path.InfoFieldOffset(offset) + 6], _) +requires acc(&raw[path.InfoFieldOffset(offset) + 7], _) decreases pure func timestamp(raw []byte, offset int) io.IO_ainfo { - return let idx := infoFieldOffset(offset) + 4 in + return let idx := path.InfoFieldOffset(offset) + 4 in io.IO_ainfo(binary.BigEndian.Uint32(raw[idx : idx + 4])) } From a68a3e791c310e1fc809df3834507c412b248064 Mon Sep 17 00:00:00 2001 From: mlimbeck Date: Wed, 22 Nov 2023 21:29:31 +0100 Subject: [PATCH 33/33] move validMetaLenInPath() to test file --- pkg/slayers/path/scion/base_spec.gobra | 7 ------- pkg/slayers/path/scion/base_spec_test.gobra | 11 +++++++++++ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/pkg/slayers/path/scion/base_spec.gobra b/pkg/slayers/path/scion/base_spec.gobra index b933026cb..b12aec326 100644 --- a/pkg/slayers/path/scion/base_spec.gobra +++ b/pkg/slayers/path/scion/base_spec.gobra @@ -45,13 +45,6 @@ pred (b *Base) Mem() { (0 < b.NumINF ==> 0 < b.NumHops) } -ghost -ensures res -decreases -pure func validMetaLenInPath() (res bool) { - return MetaLen == path.MetaLen -} - ghost decreases pure func (b Base) ValidCurrInfSpec() bool { diff --git a/pkg/slayers/path/scion/base_spec_test.gobra b/pkg/slayers/path/scion/base_spec_test.gobra index d48116d9b..5d07d6a53 100644 --- a/pkg/slayers/path/scion/base_spec_test.gobra +++ b/pkg/slayers/path/scion/base_spec_test.gobra @@ -16,7 +16,18 @@ package scion +import ( + "github.com/scionproto/scion/pkg/slayers/path" +) + func canAllocateBase() { b := &Base{} fold b.Mem() +} + +ghost +ensures res +decreases +pure func validMetaLenInPath() (res bool) { + return MetaLen == path.MetaLen } \ No newline at end of file