States.lean
Declarations on this page (171)
- def u64ToBeBytes
- def bytesToVector?
- inductive StatesPanic
- class ToStatesPanic
- instance L84
- instance L87
- def liftSpqrPanic
- instance L95
- inductive StatesError
- abbrev StatesResult
- def ofPanic
- structure PolyApi
- def AUTHENTICATOR_MACSIZE
- structure AuthApi
- def CIPHERTEXT1_SIZE
- def CIPHERTEXT2_SIZE
- def HEADER_SIZE
- def ENCAPSULATION_KEY_SIZE
- def ENCAPSULATION_STATE_SIZE
- def DECAPSULATION_KEY_SIZE
- def KEY_GENERATION_SEED_SIZE
- def SHARED_SECRET_SIZE
- abbrev Ciphertext1
- abbrev EncapsulationState
- abbrev Ciphertext2
- abbrev Header
- abbrev EncapsulationKey
- abbrev DecapsulationKey
- structure Keys
- def swapAdjacentPairs
-
def flip
Endianness Of Encapsulation State Bytes -
def flip_
endianness_ of_ encapsulation_ state - def issue1275NeedsFlip
-
def potentially_
fix_ state_ incorrectly_ encoded_ by_ libcrux_ issue_ 1275 - def ek_matches_header
- def generate
- def encaps1
- def encaps2
- def decaps
- def sckaKeyInfoPrefix
- structure NoHeaderReceived
- structure HeaderReceived
- structure Ct1Sent
- structure Ct1SentEkReceived
- structure Ct2Sent
- structure KeysUnsampled
- structure HeaderSent
- structure EkSent
- structure EkSentCt1Received
- def new
- def send_header
- def into_pb
- def from_pb
- def send_ek
- def into_pb
- def from_pb
- def recv_ct1
- def into_pb
- def from_pb
- def recv_ct2
- def into_pb
- def from_pb
- def new
- def recv_header
- def into_pb
- def from_pb
- def send_ct1
- def into_pb
- def from_pb
- def recv_ek
- def into_pb
- def from_pb
- def send_ct2
- def into_pb
- def from_pb
- def recv_next_epoch
- def into_pb
- def from_pb
- def expectEncodeBytes
- def expectDecoderNew
- def encoderFromPbStateDecode
- def decoderFromPbStateDecode
- structure NoHeaderReceived
- structure HeaderReceived
- structure Ct1Sampled
- structure EkReceivedCt1Sampled
- structure Ct1Acknowledged
- structure Ct2Sampled
- structure KeysUnsampled
- structure KeysSampled
- structure HeaderSent
- structure Ct1Received
- structure EkSentCt1Received
- inductive HeaderSentRecvChunk
- inductive EkSentCt1ReceivedRecvChunk
- def new
- def epoch
- def send_hdr_chunk
- def into_pb
- def from_pb
- def epoch
- def send_hdr_chunk
- def recv_ct1_chunk
- def into_pb
- def from_pb
- def epoch
- def send_ek_chunk
- def recv_ct1_chunk
- def into_pb
- def from_pb
- def epoch
- def send_ek_chunk
- def recv_ct2_chunk
- def into_pb
- def from_pb
- def epoch
- def recv_ct2_chunk
- def into_pb
- def from_pb
- inductive NoHeaderReceivedRecvChunk
- inductive Ct1SampledRecvChunk
- inductive Ct1AcknowledgedRecvChunk
- def send_ct2_encoder
- def new
- def epoch
- def recv_hdr_chunk
- def into_pb
- def from_pb
- def epoch
- def send_ct1_chunk
- def into_pb
- def from_pb
- def epoch
- def recv_ek_chunk
- def send_ct1_chunk
- def into_pb
- def from_pb
- def epoch
- def send_ct1_chunk
- def recv_ct1_ack
- def into_pb
- def from_pb
- def epoch
- def recv_ek_chunk
- def into_pb
- def from_pb
- def epoch
- def send_ct2_chunk
- def recv_next_epoch
- def into_pb
- def from_pb
- inductive MessagePayload
- structure Message
- inductive MessageType
- def toU8
- def tryFromU8
- def from_payload
- def encode_chunk
- def decode_chunk
- def serialize
- def deserialize
- inductive States
- structure V1Send
- structure V1Recv
- def init_a
- def init_b
- def epoch
- def into_pb
- def from_pb
- def send
- def recv
SPQR V1: braid state machine and incremental ML-KEM-768 (src/, src/)
Trusted in part. The theorems of Computational/ use only part of this file (see Computational/): the rest is mostly the camelCase aliases (fromPb / intoPb), model-only helpers (SharedSecret, KeyPair, decapsulate, validate_pk, States.), the self-test stubs (stubMlKem, stubPolyApi, stubAuthApi, StubEncoder, StubDecoder), and the check* / guard_* test drivers (guard_issue1275, guard_message_serialize, guard_, guard_panics_and_errors), all checked by Lean.
Models SPQR V1 sparse continuous key agreement (SCKA) over abstract MlKem, erasure-coding PolyApi, and authenticator/KDF AuthApi, with explicit panic/error outcomes (StatesPanic, StatesError, StatesResult):
-
src/:incremental_mlkem768.rs Keys,generate,encaps1,encaps2,decaps,ek_matches_header(validate_pk_bytes),potentially_, andfix_ state_ incorrectly_ encoded_ by_ libcrux_ issue_ 1275 flip_.endianness_ of_ encapsulation_ state -
src/: unchunked states (v1/ unchunked/ {send_ek, send_ct} KeysUnsampled,HeaderSent,EkSent,EkSentCt1Received;NoHeaderReceived,HeaderReceived,Ct1Sent,Ct1SentEkReceived,Ct2Sent), transitions (send_ek, ...), andinto_pb/from_pb. -
src/: the 11-variantv1/ chunked/ Statesbraid machine (States.,init_a States.,init_b States.->send V1Send,States.->recv V1Recv,States.,into_pb States.) and SCKA wire messages (from_pb MessagePayload,Message,MessageType,Message.,serialize Message.).deserialize
@[expose] public sectionnamespace CryptoVerification.LibsignalSpqrV1Byte helpers
def u64ToBeBytes
Big-endian 8-byte encoding (u64::to_be_bytes).
def u64ToBeBytes (v : BitVec 64) : Bytes :=
[ v.extractLsb' 56 8, v.extractLsb' 48 8, v.extractLsb' 40 8, v.extractLsb' 32 8,
v.extractLsb' 24 8, v.extractLsb' 16 8, v.extractLsb' 8 8, v.extractLsb' 0 8 ]def bytesToVector?
def bytesToVector? (n : Nat) (xs : Bytes) : Option (List.Vector (BitVec 8) n) :=
if h : xs.length = n then some ⟨xs, h⟩ else none
Panics and results (src/, src/)
inductive StatesPanic
Explicit Rust panic sites in src/ and src/.
inductive StatesPanic where
| spqr (p : SpqrPanic)
| rngExhausted (needed available : Nat)
| encaps1Failed
| encaps2BadSize (esLen ekLen : Nat)
| issue1275BadLen (esLen : Nat)
| flipEndiannessBadLen (esLen : Nat)
| decapsBadSize (dkLen ct1Len ct2Len : Nat)
| unchunkedRecvCt1EpochMismatch (epoch selfEpoch : Epoch)
| unchunkedRecvCt2EpochOverflow
| unchunkedRecvHeaderEpochMismatch (epoch selfEpoch : Epoch)
| unchunkedRecvEkEpochMismatch (epoch selfEpoch : Epoch)
| unchunkedRecvNextEpochOverflow
| unchunkedRecvNextEpochMismatch (expected nextEpoch : Epoch)
| polyExpectFailed (site : String)
| chunkedEpochMismatch (site : String) (epoch selfEpoch : Epoch)
| decodedSliceBounds (site : String) (decodedLen splitAt : Nat)
deriving DecidableEq, Repr, Inhabitedclass ToStatesPanic
class ToStatesPanic (ε : Type) where
toStatesPanic : ε → StatesPanicinstance
instance : ToStatesPanic StatesPanic where
toStatesPanic := idinstance
instance : ToStatesPanic SpqrPanic where
toStatesPanic := StatesPanic.spqrdef liftSpqrPanic
def liftSpqrPanic {α : Type} (r : Except SpqrPanic α) : Except StatesPanic α :=
match r with
| .ok v => .ok v
| .error p => .error (.spqr p)instance
instance : MonadLift (Except SpqrPanic) (Except StatesPanic) where
monadLift r := liftSpqrPanic rinductive StatesError
Clean Err(Error) return versus Rust panic (StatesPanic).
inductive StatesError where
| err (e : Error)
| panic (p : StatesPanic)
deriving DecidableEq, Repr, Inhabited1 declaration not shown (lines 106–108): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
abbrev StatesResult
abbrev StatesResult (α : Type) := Except StatesError αnamespace StatesResultdef ofPanic
def ofPanic {ε : Type} [ToStatesPanic ε] (r : Except ε α) : StatesResult α :=
match r with
| .ok v => .ok v
| .error p => .error (.panic (ToStatesPanic.toStatesPanic p))2 declarations not shown (lines 121–129): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification., CryptoVerification.
end StatesResultstructure PolyApi
Abstract polynomial erasure-coding interface (src/, src/).
structure PolyApi where
Chunk : Type
PolynomialError : Type
EncodingError : Type
PolyEncoder : Type
PolyDecoder : Type
[decEqChunk : DecidableEq Chunk]
[reprChunk : Repr Chunk]
[inhabitedChunk : Inhabited Chunk]
[decEqPolyErr : DecidableEq PolynomialError]
[reprPolyErr : Repr PolynomialError]
[decEqEncErr : DecidableEq EncodingError]
[reprEncErr : Repr EncodingError]
[decEqEncoder : DecidableEq PolyEncoder]
[decEqDecoder : DecidableEq PolyDecoder]
[reprEncoder : Repr PolyEncoder]
[reprDecoder : Repr PolyDecoder]
mkChunk : BitVec 16 → List.Vector (BitVec 8) 32 → Chunk
chunkIndex : Chunk → BitVec 16
chunkData : Chunk → List.Vector (BitVec 8) 32
encode_bytes : Bytes → Except SpqrPanic (Except EncodingError PolyEncoder)
next_chunk : PolyEncoder → Except SpqrPanic (PolyEncoder × Chunk)
encoder_into_pb : PolyEncoder → PolynomialEncoder
encoder_from_pb : PolynomialEncoder → Except SpqrPanic (Except PolynomialError PolyEncoder)
decoder_new : Nat → Except SpqrPanic (Except EncodingError PolyDecoder)
add_chunk : PolyDecoder → Chunk → Except SpqrPanic PolyDecoder
decoded_message : PolyDecoder → Except SpqrPanic (Option Bytes)
decoder_into_pb : PolyDecoder → PolynomialDecoder
decoder_from_pb : PolynomialDecoder → Except SpqrPanic (Except PolynomialError PolyDecoder)def AUTHENTICATOR_MACSIZE
def AUTHENTICATOR_MACSIZE : Nat := 32structure AuthApi
Abstract authenticator and HKDF interface (src/, src/).
structure AuthApi where
Authenticator : Type
[decEqAuth : DecidableEq Authenticator]
[reprAuth : Repr Authenticator]
new : Bytes → Epoch → Except SpqrPanic Authenticator
update : Authenticator → Epoch → Bytes → Except SpqrPanic Authenticator
mac_hdr : Authenticator → Epoch → Bytes → Except SpqrPanic Bytes
mac_ct : Authenticator → Epoch → Bytes → Except SpqrPanic Bytes
/-- `Authenticator::verify_hdr` (`util::compare` panics if `expected_mac.len() > 32`). -/
verify_hdr : Authenticator → Epoch → Bytes → Bytes →
Except SpqrPanic (Except Error Unit)
/-- `Authenticator::verify_ct` (`util::compare` panics if `expected_mac.len() > 32`). -/
verify_ct : Authenticator → Epoch → Bytes → Bytes →
Except SpqrPanic (Except Error Unit)
into_pb : Authenticator → ProtoAuthenticator
from_pb : ProtoAuthenticator → Authenticator
/-- `kdf::hkdf_to_vec` (`src/kdf.rs:6–18`; panics if `okm_len > 255 * 32`). -/
hkdf_to_vec : Bytes → Bytes → Bytes → Nat → Except SpqrPanic Bytes
Incremental ML-KEM-768 and issue-1275 fix-up (src/)
def CIPHERTEXT1_SIZE
def CIPHERTEXT1_SIZE : Nat := 960def CIPHERTEXT2_SIZE
def CIPHERTEXT2_SIZE : Nat := 128def HEADER_SIZE
def HEADER_SIZE : Nat := 64def ENCAPSULATION_KEY_SIZE
def ENCAPSULATION_KEY_SIZE : Nat := 1152def ENCAPSULATION_STATE_SIZE
def ENCAPSULATION_STATE_SIZE : Nat := 2080def DECAPSULATION_KEY_SIZE
def DECAPSULATION_KEY_SIZE : Nat := 2400def KEY_GENERATION_SEED_SIZE
def KEY_GENERATION_SEED_SIZE : Nat := 64def SHARED_SECRET_SIZE
def SHARED_SECRET_SIZE : Nat := 32abbrev Ciphertext1
abbrev Ciphertext1 := Bytesabbrev EncapsulationState
abbrev EncapsulationState := Bytesabbrev Ciphertext2
abbrev Ciphertext2 := Bytesabbrev Header
abbrev Header := Bytesabbrev EncapsulationKey
abbrev EncapsulationKey := Bytesabbrev DecapsulationKey
abbrev DecapsulationKey := Bytes1 declaration not shown (lines 226–226): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
structure Keys
Split ML-KEM-768 key pair (pub struct Keys, src/).
structure Keys where
ek : EncapsulationKey
dk : DecapsulationKey
hdr : Header
deriving DecidableEq, Repr, Inhabited1 declaration not shown (lines 235–235): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
def swapAdjacentPairs
Swap adjacent byte pairs (b0, b1) ↦ (b1, b0).
def swapAdjacentPairs : Bytes → Bytes
| b0 :: b1 :: rest => b1 :: b0 :: swapAdjacentPairs rest
| xs => xs
def flip
Swap each 2-byte pair in es[0 .. es., leaving the trailing 32-byte randomness unchanged.
def flipEndiannessOfEncapsulationStateBytes (es : EncapsulationState) : EncapsulationState :=
let prefixLen := es.length - 32
swapAdjacentPairs (es.take prefixLen) ++ es.drop prefixLen
def flip_
flip_ (src/).
def flip_endianness_of_encapsulation_state (es : EncapsulationState) :
Except StatesPanic EncapsulationState :=
if es.length % 2 != 0 || !(es.length > 32) then
.error (.flipEndiannessBadLen es.length)
else
.ok (flipEndiannessOfEncapsulationStateBytes es)def issue1275NeedsFlip
Scan es[1536..2048] in 2-byte LE words (src/): skip 0/-1, return false on valid LE (1, 2, 0xFFFE), true on byte-swapped BE (0x0100, 0x0200, 0xFEFF), and false otherwise.
def issue1275NeedsFlip : Bytes → Bool
| b0 :: b1 :: rest =>
let w : BitVec 16 := (b1.zeroExtend 16 <<< 8) ||| b0.zeroExtend 16
if w == 0x0000#16 || w == 0xFFFF#16 then
issue1275NeedsFlip rest
else if w == 0x0001#16 || w == 0x0002#16 || w == 0xFFFE#16 then
false
else if w == 0x0100#16 || w == 0x0200#16 || w == 0xFEFF#16 then
true
else
false
| _ => false1 declaration not shown (lines 271–277): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
def potentially_
potentially_ (src/), checking es..
def potentially_fix_state_incorrectly_encoded_by_libcrux_issue_1275
(es : EncapsulationState) : Except StatesPanic (Option EncapsulationState) :=
if es.length != ENCAPSULATION_STATE_SIZE then
.error (.issue1275BadLen es.length)
else
let error2Bytes := (es.drop 1536).take (2080 - 32 - 1536)
if issue1275NeedsFlip error2Bytes then do
let fixed ← flip_endianness_of_encapsulation_state es
.ok (some fixed)
else
.ok nonedef ek_matches_header
ek_matches_header (src/).
def ek_matches_header (K : MlKem) (ek : EncapsulationKey) (hdr : Header) : Bool :=
K.validPkBytes hdr ek2 declarations not shown (lines 297–300): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification., CryptoVerification.
def generate
generate (src/): consumes 64 seed bytes from tape.
def generate (K : MlKem) (tape : Bytes) : Except StatesPanic (Keys × Bytes) :=
match bytesToVector? KEY_GENERATION_SEED_SIZE (tape.take KEY_GENERATION_SEED_SIZE) with
| none => .error (.rngExhausted KEY_GENERATION_SEED_SIZE tape.length)
| some seed =>
let (hdr, ek, dk) := K.fromSeed seed
.ok ({ ek := ek.toList, dk := dk.toList, hdr := hdr.toList },
tape.drop KEY_GENERATION_SEED_SIZE)def encaps1
encaps1 (src/): consumes 32 random bytes from tape and panics if K. returns none.
def encaps1 (K : MlKem) (hdr : Header) (tape : Bytes) :
Except StatesPanic ((Ciphertext1 × EncapsulationState × Secret) × Bytes) :=
match bytesToVector? SHARED_SECRET_SIZE (tape.take SHARED_SECRET_SIZE) with
| none => .error (.rngExhausted SHARED_SECRET_SIZE tape.length)
| some rand =>
match K.encaps1 hdr rand with
| none => .error .encaps1Failed
| some (ct1, es, ss) =>
.ok ((ct1.toList, es.toList, ss.toList), tape.drop SHARED_SECRET_SIZE)def encaps2
encaps2 (src/), applying the issue-1275 fix-up before K..
def encaps2 (K : MlKem) (ek : EncapsulationKey) (es : EncapsulationState) :
Except StatesPanic Ciphertext2 := do
let maybeFix ← potentially_fix_state_incorrectly_encoded_by_libcrux_issue_1275 es
let es' := maybeFix.getD es
match bytesToVector? ENCAPSULATION_STATE_SIZE es', bytesToVector? ENCAPSULATION_KEY_SIZE ek with
| some esVec, some ekVec => .ok (K.encaps2 esVec ekVec).toList
| _, _ => .error (.encaps2BadSize es'.length ek.length)def decaps
decaps (src/).
def decaps (K : MlKem) (dk : DecapsulationKey) (ct1 : Ciphertext1) (ct2 : Ciphertext2) :
Except StatesPanic Secret :=
match bytesToVector? CIPHERTEXT1_SIZE ct1,
bytesToVector? CIPHERTEXT2_SIZE ct2,
bytesToVector? DECAPSULATION_KEY_SIZE dk with
| some ct1Vec, some ct2Vec, some dkVec => .ok (K.decaps dkVec ct1Vec ct2Vec).toList
| _, _, _ => .error (.decapsBadSize dk.length ct1.length ct2.length)1 declaration not shown (lines 341–341): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
Unchunked state machine (src/)
def sckaKeyInfoPrefix
def sckaKeyInfoPrefix : Bytes :=
asciiBytes "Signal_PQCKA_V1_MLKEM768:SCKA Key"namespace Unchunkednamespace SendCtstructure NoHeaderReceived
structure NoHeaderReceived (Au : AuthApi) where
epoch : Epoch
auth : Au.Authenticator
deriving DecidableEq, Reprstructure HeaderReceived
structure HeaderReceived (Au : AuthApi) where
epoch : Epoch
auth : Au.Authenticator
hdr : Header
deriving DecidableEq, Reprstructure Ct1Sent
structure Ct1Sent (Au : AuthApi) where
epoch : Epoch
auth : Au.Authenticator
hdr : Header
es : EncapsulationState
ct1 : Ciphertext1
deriving DecidableEq, Reprstructure Ct1SentEkReceived
structure Ct1SentEkReceived (Au : AuthApi) where
epoch : Epoch
auth : Au.Authenticator
es : EncapsulationState
ek : EncapsulationKey
ct1 : Ciphertext1
deriving DecidableEq, Reprstructure Ct2Sent
structure Ct2Sent (Au : AuthApi) where
epoch : Epoch
auth : Au.Authenticator
deriving DecidableEq, Reprend SendCtnamespace SendEkstructure KeysUnsampled
structure KeysUnsampled (Au : AuthApi) where
epoch : Epoch
auth : Au.Authenticator
deriving DecidableEq, Reprstructure HeaderSent
structure HeaderSent (Au : AuthApi) where
epoch : Epoch
auth : Au.Authenticator
ek : EncapsulationKey
dk : DecapsulationKey
deriving DecidableEq, Reprstructure EkSent
structure EkSent (Au : AuthApi) where
epoch : Epoch
auth : Au.Authenticator
dk : DecapsulationKey
deriving DecidableEq, Reprstructure EkSentCt1Received
structure EkSentCt1Received (Au : AuthApi) where
epoch : Epoch
auth : Au.Authenticator
dk : DecapsulationKey
ct1 : Ciphertext1
deriving DecidableEq, Reprnamespace KeysUnsampleddef new
def new (Au : AuthApi) (authKey : Bytes) : Except StatesPanic (KeysUnsampled Au) := do
let auth ← Au.new authKey 1#64
.ok { epoch := 1#64, auth := auth }def send_header
KeysUnsampled::send_header (src/).
def send_header (K : MlKem) {Au : AuthApi} (self : KeysUnsampled Au) (tape : Bytes) :
Except StatesPanic (HeaderSent Au × Header × Mac × Bytes) := do
let (keys, tape') ← generate K tape
let mac ← Au.mac_hdr self.auth self.epoch keys.hdr
.ok ({ epoch := self.epoch, auth := self.auth, ek := keys.ek, dk := keys.dk },
keys.hdr, mac, tape')def into_pb
def into_pb {Au : AuthApi} (self : KeysUnsampled Au) : V1State.Unchunked.KeysUnsampled :=
{ epoch := self.epoch, auth := some (Au.into_pb self.auth) }1 declaration not shown (lines 430–430): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
def from_pb
def from_pb (Au : AuthApi) (pb : V1State.Unchunked.KeysUnsampled) : StatesResult (KeysUnsampled Au) :=
match pb.auth with
| none => .error (.err .stateDecode)
| some a => .ok { epoch := pb.epoch, auth := Au.from_pb a }1 declaration not shown (lines 437–437): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
end KeysUnsamplednamespace HeaderSentdef send_ek
HeaderSent::send_ek (src/).
def into_pb
1 declaration not shown (lines 450–450): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
def from_pb
def from_pb (Au : AuthApi) (pb : V1State.Unchunked.HeaderSent) : StatesResult (HeaderSent Au) :=
if pb.dk.length == DECAPSULATION_KEY_SIZE && pb.ek.length == ENCAPSULATION_KEY_SIZE then
match pb.auth with
| none => .error (.err .stateDecode)
| some a => .ok { epoch := pb.epoch, auth := Au.from_pb a, ek := pb.ek, dk := pb.dk }
else
.error (.err .stateDecode)1 declaration not shown (lines 460–460): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
end HeaderSentnamespace EkSentdef recv_ct1
def recv_ct1 {Au : AuthApi} (self : EkSent Au) (epoch : Epoch) (ct1 : Ciphertext1) :
Except StatesPanic (EkSentCt1Received Au) :=
if epoch != self.epoch then
.error (.unchunkedRecvCt1EpochMismatch epoch self.epoch)
else
.ok { epoch := self.epoch, auth := self.auth, dk := self.dk, ct1 := ct1 }def into_pb
1 declaration not shown (lines 477–477): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
def from_pb
def from_pb (Au : AuthApi) (pb : V1State.Unchunked.EkSent) : StatesResult (EkSent Au) :=
if pb.dk.length == DECAPSULATION_KEY_SIZE then
match pb.auth with
| none => .error (.err .stateDecode)
| some a => .ok { epoch := pb.epoch, auth := Au.from_pb a, dk := pb.dk }
else
.error (.err .stateDecode)1 declaration not shown (lines 487–487): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
end EkSentnamespace EkSentCt1Receiveddef recv_ct2
EkSentCt1Received::recv_ct2 (src/).
def recv_ct2 (K : MlKem) {Au : AuthApi} (self : EkSentCt1Received Au)
(ct2 : Ciphertext2) (mac : Mac) : StatesResult (SendCt.NoHeaderReceived Au × EpochSecret) := do
let ss ← StatesResult.ofPanic (decaps K self.dk self.ct1 ct2)
let info := sckaKeyInfoPrefix ++ u64ToBeBytes self.epoch
let ss ← StatesResult.ofPanic (Au.hkdf_to_vec (List.replicate 32 0#8) ss info 32)
let auth ← StatesResult.ofPanic (Au.update self.auth self.epoch ss)
let ct1Full := self.ct1 ++ ct2
let verifyRes ← StatesResult.ofPanic (Au.verify_ct auth self.epoch ct1Full mac)
match verifyRes with
| .error _ => .error (.err .macVerifyFailed)
| .ok () =>
if self.epoch == BitVec.allOnes 64 then
.error (.panic .unchunkedRecvCt2EpochOverflow)
else
.ok ({ epoch := self.epoch + 1#64, auth := auth },
{ epoch := self.epoch, secret := ss })def into_pb
1 declaration not shown (lines 514–514): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
def from_pb
def from_pb (Au : AuthApi) (pb : V1State.Unchunked.EkSentCt1Received) :
StatesResult (EkSentCt1Received Au) :=
if pb.dk.length == DECAPSULATION_KEY_SIZE && pb.ct1.length == CIPHERTEXT1_SIZE then
match pb.auth with
| none => .error (.err .stateDecode)
| some a => .ok { epoch := pb.epoch, auth := Au.from_pb a, dk := pb.dk, ct1 := pb.ct1 }
else
.error (.err .stateDecode)1 declaration not shown (lines 525–525): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
end EkSentCt1Receivedend SendEknamespace SendCtnamespace NoHeaderReceiveddef new
def new (Au : AuthApi) (authKey : Bytes) : Except StatesPanic (NoHeaderReceived Au) := do
let auth ← Au.new authKey 1#64
.ok { epoch := 1#64, auth := auth }def recv_header
NoHeaderReceived::recv_header (src/).
def recv_header {Au : AuthApi} (self : NoHeaderReceived Au)
(epoch : Epoch) (hdr : Header) (mac : Mac) : StatesResult (HeaderReceived Au) := do
if epoch != self.epoch then
.error (.panic (.unchunkedRecvHeaderEpochMismatch epoch self.epoch))
else
let verifyRes ← StatesResult.ofPanic (Au.verify_hdr self.auth self.epoch hdr mac)
match verifyRes with
| .error _ => .error (.err .macVerifyFailed)
| .ok () => .ok { epoch := self.epoch, auth := self.auth, hdr := hdr }def into_pb
def into_pb {Au : AuthApi} (self : NoHeaderReceived Au) : V1State.Unchunked.NoHeaderReceived :=
{ epoch := self.epoch, auth := some (Au.into_pb self.auth) }1 declaration not shown (lines 553–553): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
def from_pb
def from_pb (Au : AuthApi) (pb : V1State.Unchunked.NoHeaderReceived) :
StatesResult (NoHeaderReceived Au) :=
match pb.auth with
| none => .error (.err .stateDecode)
| some a => .ok { epoch := pb.epoch, auth := Au.from_pb a }1 declaration not shown (lines 561–561): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
end NoHeaderReceivednamespace HeaderReceiveddef send_ct1
HeaderReceived::send_ct1 (src/).
def send_ct1 (K : MlKem) {Au : AuthApi} (self : HeaderReceived Au) (tape : Bytes) :
Except StatesPanic (Ct1Sent Au × Ciphertext1 × EpochSecret × Bytes) := do
let ((ct1, es, secret), tape') ← encaps1 K self.hdr tape
let info := sckaKeyInfoPrefix ++ u64ToBeBytes self.epoch
let secret ← Au.hkdf_to_vec (List.replicate 32 0#8) secret info 32
let auth ← Au.update self.auth self.epoch secret
.ok ({ epoch := self.epoch, auth := auth, hdr := self.hdr, es := es, ct1 := ct1 },
ct1, { epoch := self.epoch, secret := secret }, tape')def into_pb
def into_pb {Au : AuthApi} (self : HeaderReceived Au) : V1State.Unchunked.HeaderReceived :=
{ epoch := self.epoch, auth := some (Au.into_pb self.auth), hdr := self.hdr }1 declaration not shown (lines 580–580): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
def from_pb
def from_pb (Au : AuthApi) (pb : V1State.Unchunked.HeaderReceived) :
StatesResult (HeaderReceived Au) :=
if pb.hdr.length == HEADER_SIZE then
match pb.auth with
| none => .error (.err .stateDecode)
| some a => .ok { epoch := pb.epoch, auth := Au.from_pb a, hdr := pb.hdr }
else
.error (.err .stateDecode)1 declaration not shown (lines 591–591): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
end HeaderReceivednamespace Ct1Sentdef recv_ek
def recv_ek (K : MlKem) {Au : AuthApi} (self : Ct1Sent Au)
(epoch : Epoch) (ek : EncapsulationKey) : StatesResult (Ct1SentEkReceived Au) :=
if epoch != self.epoch then
.error (.panic (.unchunkedRecvEkEpochMismatch epoch self.epoch))
else if ek_matches_header K ek self.hdr then
.ok { epoch := self.epoch, auth := self.auth, es := self.es, ek := ek, ct1 := self.ct1 }
else
.error (.err .erroneousDataReceived)def into_pb
1 declaration not shown (lines 611–611): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
def from_pb
def from_pb (Au : AuthApi) (pb : V1State.Unchunked.Ct1Sent) : StatesResult (Ct1Sent Au) :=
if pb.hdr.length == HEADER_SIZE &&
pb.es.length == ENCAPSULATION_STATE_SIZE &&
pb.ct1.length == CIPHERTEXT1_SIZE then
match pb.auth with
| none => .error (.err .stateDecode)
| some a =>
.ok { epoch := pb.epoch, auth := Au.from_pb a, hdr := pb.hdr, es := pb.es, ct1 := pb.ct1 }
else
.error (.err .stateDecode)1 declaration not shown (lines 624–624): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
end Ct1Sentnamespace Ct1SentEkReceiveddef send_ct2
Ct1SentEkReceived::send_ct2 (src/).
def send_ct2 (K : MlKem) {Au : AuthApi} (self : Ct1SentEkReceived Au) :
Except StatesPanic (Ct2Sent Au × Ciphertext2 × Mac) := do
let ct2 ← encaps2 K self.ek self.es
let ct1Full := self.ct1 ++ ct2
let mac ← Au.mac_ct self.auth self.epoch ct1Full
.ok ({ epoch := self.epoch, auth := self.auth }, ct2, mac)def into_pb
1 declaration not shown (lines 642–642): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
def from_pb
def from_pb (Au : AuthApi) (pb : V1State.Unchunked.Ct1SentEkReceived) :
StatesResult (Ct1SentEkReceived Au) :=
if pb.es.length == ENCAPSULATION_STATE_SIZE &&
pb.ct1.length == CIPHERTEXT1_SIZE &&
pb.ek.length == ENCAPSULATION_KEY_SIZE then
match pb.auth with
| none => .error (.err .stateDecode)
| some a =>
.ok { epoch := pb.epoch, auth := Au.from_pb a, es := pb.es, ek := pb.ek, ct1 := pb.ct1 }
else
.error (.err .stateDecode)1 declaration not shown (lines 656–656): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
end Ct1SentEkReceivednamespace Ct2Sentdef recv_next_epoch
Ct2Sent::recv_next_epoch (src/).
def recv_next_epoch {Au : AuthApi} (self : Ct2Sent Au) (nextEpoch : Epoch) :
Except StatesPanic (SendEk.KeysUnsampled Au) :=
if self.epoch == BitVec.allOnes 64 then
.error .unchunkedRecvNextEpochOverflow
else
let next := self.epoch + 1#64
if next != nextEpoch then
.error (.unchunkedRecvNextEpochMismatch next nextEpoch)
else
.ok { epoch := next, auth := self.auth }def into_pb
1 declaration not shown (lines 677–677): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
def from_pb
def from_pb (Au : AuthApi) (pb : V1State.Unchunked.Ct2Sent) : StatesResult (Ct2Sent Au) :=
match pb.auth with
| none => .error (.err .stateDecode)
| some a => .ok { epoch := pb.epoch, auth := Au.from_pb a }1 declaration not shown (lines 684–684): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
end Ct2Sentend SendCtend Unchunked
Chunked braid state machine (src/)
def expectEncodeBytes
def expectEncodeBytes (P : PolyApi) (site : String) (msg : Bytes) :
Except StatesPanic P.PolyEncoder := do
let res ← P.encode_bytes msg
match res with
| .ok enc => .ok enc
| .error _ => .error (.polyExpectFailed site)def expectDecoderNew
def expectDecoderNew (P : PolyApi) (site : String) (lenBytes : Nat) :
Except StatesPanic P.PolyDecoder := do
let res ← P.decoder_new lenBytes
match res with
| .ok dec => .ok dec
| .error _ => .error (.polyExpectFailed site)def encoderFromPbStateDecode
def encoderFromPbStateDecode (P : PolyApi) (pb? : Option PolynomialEncoder) :
StatesResult P.PolyEncoder :=
match pb? with
| none => .error (.err .stateDecode)
| some pb => do
let res ← StatesResult.ofPanic (P.encoder_from_pb pb)
match res with
| .ok enc => .ok enc
| .error _ => .error (.err .stateDecode)def decoderFromPbStateDecode
def decoderFromPbStateDecode (P : PolyApi) (pb? : Option PolynomialDecoder) :
StatesResult P.PolyDecoder :=
match pb? with
| none => .error (.err .stateDecode)
| some pb => do
let res ← StatesResult.ofPanic (P.decoder_from_pb pb)
match res with
| .ok dec => .ok dec
| .error _ => .error (.err .stateDecode)namespace Chunkednamespace SendCtstructure NoHeaderReceived
structure NoHeaderReceived (P : PolyApi) (Au : AuthApi) where
uc : Unchunked.SendCt.NoHeaderReceived Au
receiving_hdr : P.PolyDecoder
deriving DecidableEq, Reprstructure HeaderReceived
structure HeaderReceived (P : PolyApi) (Au : AuthApi) where
uc : Unchunked.SendCt.HeaderReceived Au
receiving_ek : P.PolyDecoder
deriving DecidableEq, Reprstructure Ct1Sampled
structure Ct1Sampled (P : PolyApi) (Au : AuthApi) where
uc : Unchunked.SendCt.Ct1Sent Au
sending_ct1 : P.PolyEncoder
receiving_ek : P.PolyDecoder
deriving DecidableEq, Reprstructure EkReceivedCt1Sampled
structure EkReceivedCt1Sampled (P : PolyApi) (Au : AuthApi) where
uc : Unchunked.SendCt.Ct1SentEkReceived Au
sending_ct1 : P.PolyEncoder
deriving DecidableEq, Reprstructure Ct1Acknowledged
structure Ct1Acknowledged (P : PolyApi) (Au : AuthApi) where
uc : Unchunked.SendCt.Ct1Sent Au
receiving_ek : P.PolyDecoder
deriving DecidableEq, Reprstructure Ct2Sampled
structure Ct2Sampled (P : PolyApi) (Au : AuthApi) where
uc : Unchunked.SendCt.Ct2Sent Au
sending_ct2 : P.PolyEncoder
deriving DecidableEq, Reprend SendCtnamespace SendEkstructure KeysUnsampled
structure KeysUnsampled (Au : AuthApi) where
uc : Unchunked.SendEk.KeysUnsampled Au
deriving DecidableEq, Reprstructure KeysSampled
structure KeysSampled (P : PolyApi) (Au : AuthApi) where
uc : Unchunked.SendEk.HeaderSent Au
sending_hdr : P.PolyEncoder
deriving DecidableEq, Reprstructure HeaderSent
structure HeaderSent (P : PolyApi) (Au : AuthApi) where
uc : Unchunked.SendEk.EkSent Au
sending_ek : P.PolyEncoder
receiving_ct1 : P.PolyDecoder
deriving DecidableEq, Reprstructure Ct1Received
structure Ct1Received (P : PolyApi) (Au : AuthApi) where
uc : Unchunked.SendEk.EkSentCt1Received Au
sending_ek : P.PolyEncoder
deriving DecidableEq, Reprstructure EkSentCt1Received
structure EkSentCt1Received (P : PolyApi) (Au : AuthApi) where
uc : Unchunked.SendEk.EkSentCt1Received Au
receiving_ct2 : P.PolyDecoder
deriving DecidableEq, Reprinductive HeaderSentRecvChunk
inductive HeaderSentRecvChunk (P : PolyApi) (Au : AuthApi) where
| stillReceiving (s : HeaderSent P Au)
| done (s : Ct1Received P Au)
deriving DecidableEq, Reprinductive EkSentCt1ReceivedRecvChunk
inductive EkSentCt1ReceivedRecvChunk (P : PolyApi) (Au : AuthApi) where
| stillReceiving (s : EkSentCt1Received P Au)
| done (res : SendCt.NoHeaderReceived P Au × EpochSecret)
deriving DecidableEq, Reprnamespace KeysUnsampleddef new
def new (Au : AuthApi) (authKey : Bytes) : Except StatesPanic (KeysUnsampled Au) := do
let uc ← Unchunked.SendEk.KeysUnsampled.new Au authKey
.ok { uc := uc }def epoch
def epoch {Au : AuthApi} (self : KeysUnsampled Au) : Epoch := self.uc.epochdef send_hdr_chunk
KeysUnsampled::send_hdr_chunk (src/).
def send_hdr_chunk (K : MlKem) (P : PolyApi) {Au : AuthApi}
(self : KeysUnsampled Au) (tape : Bytes) :
Except StatesPanic (KeysSampled P Au × P.Chunk × Bytes) := do
let (uc, toSend, mac, tape') ← self.uc.send_header K tape
let toSendFull := toSend ++ mac
let sendingHdr ← expectEncodeBytes P "v1/chunked/send_ek.rs:63" toSendFull
let (sendingHdr, chunk) ← P.next_chunk sendingHdr
.ok ({ uc := uc, sending_hdr := sendingHdr }, chunk, tape')def into_pb
def into_pb {Au : AuthApi} (self : KeysUnsampled Au) : V1State.Chunked.KeysUnsampled :=
{ uc := some self.uc.into_pb }1 declaration not shown (lines 823–823): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
def from_pb
def from_pb (Au : AuthApi) (pb : V1State.Chunked.KeysUnsampled) : StatesResult (KeysUnsampled Au) :=
match pb.uc with
| none => .error (.err .stateDecode)
| some u => do
let uc ← Unchunked.SendEk.KeysUnsampled.from_pb Au u
.ok { uc := uc }1 declaration not shown (lines 832–832): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
end KeysUnsamplednamespace KeysSampleddef send_hdr_chunk
def send_hdr_chunk {P : PolyApi} {Au : AuthApi} (self : KeysSampled P Au) :
Except StatesPanic (KeysSampled P Au × P.Chunk) := do
let (sendingHdr, chunk) ← P.next_chunk self.sending_hdr
.ok ({ uc := self.uc, sending_hdr := sendingHdr }, chunk)def recv_ct1_chunk
KeysSampled::recv_ct1_chunk (src/).
def recv_ct1_chunk {P : PolyApi} {Au : AuthApi} (self : KeysSampled P Au)
(epoch : Epoch) (chunk : P.Chunk) : Except StatesPanic (HeaderSent P Au) := do
if epoch != self.uc.epoch then
.error (.chunkedEpochMismatch "v1/chunked/send_ek.rs:86" epoch self.uc.epoch)
else
let receivingCt1 ← expectDecoderNew P "v1/chunked/send_ek.rs:88" CIPHERTEXT1_SIZE
let receivingCt1 ← P.add_chunk receivingCt1 chunk
let (uc, ek) := self.uc.send_ek
let sendingEk ← expectEncodeBytes P "v1/chunked/send_ek.rs:92" ek
.ok { uc := uc, sending_ek := sendingEk, receiving_ct1 := receivingCt1 }def into_pb
def into_pb {P : PolyApi} {Au : AuthApi} (self : KeysSampled P Au) : V1State.Chunked.KeysSampled :=
{ uc := some self.uc.into_pb, sendingHdr := some (P.encoder_into_pb self.sending_hdr) }1 declaration not shown (lines 860–860): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
def from_pb
def from_pb (P : PolyApi) (Au : AuthApi) (pb : V1State.Chunked.KeysSampled) :
StatesResult (KeysSampled P Au) := do
let u ← match pb.uc with
| none => .error (.err .stateDecode)
| some u => .ok u
let uc ← Unchunked.SendEk.HeaderSent.from_pb Au u
let sendingHdr ← encoderFromPbStateDecode P pb.sendingHdr
.ok { uc := uc, sending_hdr := sendingHdr }1 declaration not shown (lines 871–871): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
end KeysSamplednamespace HeaderSentdef send_ek_chunk
def send_ek_chunk {P : PolyApi} {Au : AuthApi} (self : HeaderSent P Au) :
Except StatesPanic (HeaderSent P Au × P.Chunk) := do
let (sendingEk, chunk) ← P.next_chunk self.sending_ek
.ok ({ uc := self.uc, sending_ek := sendingEk, receiving_ct1 := self.receiving_ct1 }, chunk)def recv_ct1_chunk
HeaderSent::recv_ct1_chunk (src/).
def recv_ct1_chunk {P : PolyApi} {Au : AuthApi} (self : HeaderSent P Au)
(epoch : Epoch) (chunk : P.Chunk) : Except StatesPanic (HeaderSentRecvChunk P Au) := do
if epoch != self.uc.epoch then
.error (.chunkedEpochMismatch "v1/chunked/send_ek.rs:132" epoch self.uc.epoch)
else
let receivingCt1 ← P.add_chunk self.receiving_ct1 chunk
let decoded? ← P.decoded_message receivingCt1
match decoded? with
| some decoded =>
let uc ← self.uc.recv_ct1 epoch decoded
.ok (.done { uc := uc, sending_ek := self.sending_ek })
| none =>
.ok (.stillReceiving
{ uc := self.uc, sending_ek := self.sending_ek, receiving_ct1 := receivingCt1 })def into_pb
def into_pb {P : PolyApi} {Au : AuthApi} (self : HeaderSent P Au) : V1State.Chunked.HeaderSent :=
{ uc := some self.uc.into_pb,
sendingEk := some (P.encoder_into_pb self.sending_ek),
receivingCt1 := some (P.decoder_into_pb self.receiving_ct1) }1 declaration not shown (lines 905–905): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
def from_pb
HeaderSent::from_pb (src/; returns MsgDecode if receiving_ct1.).
def from_pb (P : PolyApi) (Au : AuthApi) (pb : V1State.Chunked.HeaderSent) :
StatesResult (HeaderSent P Au) := do
match pb.receivingCt1 with
| some d =>
if d.ptsNeeded.toNat != CIPHERTEXT1_SIZE / 2 then
.error (.err .msgDecode)
else
.ok ()
| none => .ok ()
let u ← match pb.uc with
| none => .error (.err .stateDecode)
| some u => .ok u
let uc ← Unchunked.SendEk.EkSent.from_pb Au u
let sendingEk ← encoderFromPbStateDecode P pb.sendingEk
let receivingCt1 ← decoderFromPbStateDecode P pb.receivingCt1
.ok { uc := uc, sending_ek := sendingEk, receiving_ct1 := receivingCt1 }1 declaration not shown (lines 926–926): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
end HeaderSentnamespace Ct1Receiveddef send_ek_chunk
def send_ek_chunk {P : PolyApi} {Au : AuthApi} (self : Ct1Received P Au) :
Except StatesPanic (Ct1Received P Au × P.Chunk) := do
let (sendingEk, chunk) ← P.next_chunk self.sending_ek
.ok ({ uc := self.uc, sending_ek := sendingEk }, chunk)def recv_ct2_chunk
Ct1Received::recv_ct2_chunk (src/).
def recv_ct2_chunk {P : PolyApi} {Au : AuthApi} (self : Ct1Received P Au)
(epoch : Epoch) (chunk : P.Chunk) : Except StatesPanic (EkSentCt1Received P Au) := do
if epoch != self.uc.epoch then
.error (.chunkedEpochMismatch "v1/chunked/send_ek.rs:166" epoch self.uc.epoch)
else
let receivingCt2 ←
expectDecoderNew P "v1/chunked/send_ek.rs:174" (CIPHERTEXT2_SIZE + AUTHENTICATOR_MACSIZE)
let receivingCt2 ← P.add_chunk receivingCt2 chunk
.ok { uc := self.uc, receiving_ct2 := receivingCt2 }def into_pb
def into_pb {P : PolyApi} {Au : AuthApi} (self : Ct1Received P Au) : V1State.Chunked.Ct1Received :=
{ uc := some self.uc.into_pb, sendingEk := some (P.encoder_into_pb self.sending_ek) }1 declaration not shown (lines 953–953): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
def from_pb
def from_pb (P : PolyApi) (Au : AuthApi) (pb : V1State.Chunked.Ct1Received) :
StatesResult (Ct1Received P Au) := do
let u ← match pb.uc with
| none => .error (.err .stateDecode)
| some u => .ok u
let uc ← Unchunked.SendEk.EkSentCt1Received.from_pb Au u
let sendingEk ← encoderFromPbStateDecode P pb.sendingEk
.ok { uc := uc, sending_ek := sendingEk }1 declaration not shown (lines 964–964): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
end Ct1Receivednamespace EkSentCt1Receiveddef epoch
def recv_ct2_chunk
EkSentCt1Received::recv_ct2_chunk (src/).
def recv_ct2_chunk (K : MlKem) {P : PolyApi} {Au : AuthApi} (self : EkSentCt1Received P Au)
(epoch : Epoch) (chunk : P.Chunk) : StatesResult (EkSentCt1ReceivedRecvChunk P Au) := do
if epoch != self.uc.epoch then
.error (.panic (.chunkedEpochMismatch "v1/chunked/send_ek.rs:200" epoch self.uc.epoch))
else
let receivingCt2 ← StatesResult.ofPanic (P.add_chunk self.receiving_ct2 chunk)
let decoded? ← StatesResult.ofPanic (P.decoded_message receivingCt2)
match decoded? with
| some ct2Full =>
if ct2Full.length < CIPHERTEXT2_SIZE then
.error (.panic (.decodedSliceBounds "v1/chunked/send_ek.rs:209" ct2Full.length CIPHERTEXT2_SIZE))
else
let mac := ct2Full.drop CIPHERTEXT2_SIZE
let ct2 := ct2Full.take CIPHERTEXT2_SIZE
let (uc, sec) ← self.uc.recv_ct2 K ct2 mac
let receivingHdr ← StatesResult.ofPanic
(expectDecoderNew P "v1/chunked/send_ek.rs:218" (HEADER_SIZE + AUTHENTICATOR_MACSIZE))
.ok (.done ({ uc := uc, receiving_hdr := receivingHdr }, sec))
| none =>
.ok (.stillReceiving { uc := self.uc, receiving_ct2 := receivingCt2 })def into_pb
def into_pb {P : PolyApi} {Au : AuthApi} (self : EkSentCt1Received P Au) :
V1State.Chunked.EkSentCt1Received :=
{ uc := some self.uc.into_pb, receivingCt2 := some (P.decoder_into_pb self.receiving_ct2) }1 declaration not shown (lines 998–998): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
def from_pb
EkSentCt1Received::from_pb (src/; returns MsgDecode if receiving_ct2.).
def from_pb (P : PolyApi) (Au : AuthApi) (pb : V1State.Chunked.EkSentCt1Received) :
StatesResult (EkSentCt1Received P Au) := do
match pb.receivingCt2 with
| some d =>
if d.ptsNeeded.toNat != (CIPHERTEXT2_SIZE + AUTHENTICATOR_MACSIZE) / 2 then
.error (.err .msgDecode)
else
.ok ()
| none => .ok ()
let u ← match pb.uc with
| none => .error (.err .stateDecode)
| some u => .ok u
let uc ← Unchunked.SendEk.EkSentCt1Received.from_pb Au u
let receivingCt2 ← decoderFromPbStateDecode P pb.receivingCt2
.ok { uc := uc, receiving_ct2 := receivingCt2 }1 declaration not shown (lines 1018–1018): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
end EkSentCt1Receivedend SendEknamespace SendCtinductive NoHeaderReceivedRecvChunk
inductive NoHeaderReceivedRecvChunk (P : PolyApi) (Au : AuthApi) where
| stillReceiving (s : NoHeaderReceived P Au)
| done (s : HeaderReceived P Au)
deriving DecidableEq, Reprinductive Ct1SampledRecvChunk
inductive Ct1SampledRecvChunk (P : PolyApi) (Au : AuthApi) where
| stillReceivingStillSending (s : Ct1Sampled P Au)
| stillReceiving (s : Ct1Acknowledged P Au)
| stillSending (s : EkReceivedCt1Sampled P Au)
| done (s : Ct2Sampled P Au)
deriving DecidableEq, Reprinductive Ct1AcknowledgedRecvChunk
inductive Ct1AcknowledgedRecvChunk (P : PolyApi) (Au : AuthApi) where
| stillReceiving (s : Ct1Acknowledged P Au)
| done (s : Ct2Sampled P Au)
deriving DecidableEq, Reprdef send_ct2_encoder
def send_ct2_encoder (P : PolyApi) (ct2 mac : Bytes) : Except StatesPanic P.PolyEncoder :=
expectEncodeBytes P "v1/chunked/send_ct.rs:162" (ct2 ++ mac)1 declaration not shown (lines 1046–1046): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
namespace NoHeaderReceiveddef new
NoHeaderReceived::new (src/), preserving Rust evaluation order: PolyDecoder::new, unchunked::NoHeaderReceived::new, then decoder..
def new (P : PolyApi) (Au : AuthApi) (authKey : Bytes) :
Except StatesPanic (NoHeaderReceived P Au) := do
let decoderRes ← P.decoder_new (HEADER_SIZE + AUTHENTICATOR_MACSIZE)
let uc ← Unchunked.SendCt.NoHeaderReceived.new Au authKey
match decoderRes with
| .ok decoder => .ok { uc := uc, receiving_hdr := decoder }
| .error _ => .error (.polyExpectFailed "v1/chunked/send_ct.rs:77")def epoch
def recv_hdr_chunk
NoHeaderReceived::recv_hdr_chunk (src/).
def recv_hdr_chunk {P : PolyApi} {Au : AuthApi} (self : NoHeaderReceived P Au)
(epoch : Epoch) (chunk : P.Chunk) : StatesResult (NoHeaderReceivedRecvChunk P Au) := do
if epoch != self.uc.epoch then
.error (.panic (.chunkedEpochMismatch "v1/chunked/send_ct.rs:87" epoch self.uc.epoch))
else
let receivingHdr ← StatesResult.ofPanic (P.add_chunk self.receiving_hdr chunk)
let decoded? ← StatesResult.ofPanic (P.decoded_message receivingHdr)
match decoded? with
| some hdrFull =>
if hdrFull.length < HEADER_SIZE then
.error (.panic (.decodedSliceBounds "v1/chunked/send_ct.rs:96" hdrFull.length HEADER_SIZE))
else
let mac := hdrFull.drop HEADER_SIZE
let hdr := hdrFull.take HEADER_SIZE
let receivingEkRes ← StatesResult.ofPanic (P.decoder_new ENCAPSULATION_KEY_SIZE)
let uc ← self.uc.recv_header epoch hdr mac
match receivingEkRes with
| .ok receivingEk =>
.ok (.done { uc := uc, receiving_ek := receivingEk })
| .error _ =>
.error (.panic (.polyExpectFailed "v1/chunked/send_ct.rs:102"))
| none =>
.ok (.stillReceiving { uc := self.uc, receiving_hdr := receivingHdr })def into_pb
def into_pb {P : PolyApi} {Au : AuthApi} (self : NoHeaderReceived P Au) :
V1State.Chunked.NoHeaderReceived :=
{ uc := some self.uc.into_pb, receivingHdr := some (P.decoder_into_pb self.receiving_hdr) }1 declaration not shown (lines 1091–1091): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
def from_pb
def from_pb (P : PolyApi) (Au : AuthApi) (pb : V1State.Chunked.NoHeaderReceived) :
StatesResult (NoHeaderReceived P Au) := do
match pb.receivingHdr with
| some rhdr =>
if rhdr.ptsNeeded != BitVec.ofNat 32 ((HEADER_SIZE + AUTHENTICATOR_MACSIZE) / 2) then
.error (.err .msgDecode)
else
.ok ()
| none => .ok ()
let u ← match pb.uc with
| none => .error (.err .stateDecode)
| some u => .ok u
let uc ← Unchunked.SendCt.NoHeaderReceived.from_pb Au u
let receivingHdr ← decoderFromPbStateDecode P pb.receivingHdr
.ok { uc := uc, receiving_hdr := receivingHdr }1 declaration not shown (lines 1109–1109): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
end NoHeaderReceivednamespace HeaderReceiveddef epoch
def send_ct1_chunk
HeaderReceived::send_ct1_chunk (src/).
def send_ct1_chunk (K : MlKem) {P : PolyApi} {Au : AuthApi}
(self : HeaderReceived P Au) (tape : Bytes) :
Except StatesPanic (Ct1Sampled P Au × P.Chunk × EpochSecret × Bytes) := do
let (uc, ct1, epochSecret, tape') ← self.uc.send_ct1 K tape
let sendingCt1 ← expectEncodeBytes P "v1/chunked/send_ct.rs:131" ct1
let (sendingCt1, chunk) ← P.next_chunk sendingCt1
.ok ({ uc := uc, sending_ct1 := sendingCt1, receiving_ek := self.receiving_ek },
chunk, epochSecret, tape')def into_pb
def into_pb {P : PolyApi} {Au : AuthApi} (self : HeaderReceived P Au) :
V1State.Chunked.HeaderReceived :=
{ uc := some self.uc.into_pb, receivingEk := some (P.decoder_into_pb self.receiving_ek) }1 declaration not shown (lines 1131–1131): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
def from_pb
def from_pb (P : PolyApi) (Au : AuthApi) (pb : V1State.Chunked.HeaderReceived) :
StatesResult (HeaderReceived P Au) := do
match pb.receivingEk with
| some d =>
if d.ptsNeeded.toNat != ENCAPSULATION_KEY_SIZE / 2 then
.error (.err .msgDecode)
else
.ok ()
| none => .ok ()
let u ← match pb.uc with
| none => .error (.err .stateDecode)
| some u => .ok u
let uc ← Unchunked.SendCt.HeaderReceived.from_pb Au u
let receivingEk ← decoderFromPbStateDecode P pb.receivingEk
.ok { uc := uc, receiving_ek := receivingEk }1 declaration not shown (lines 1149–1149): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
end HeaderReceivednamespace Ct1Sampleddef recv_ek_chunk
Ct1Sampled::recv_ek_chunk (src/; no chunk-level epoch assert).
def recv_ek_chunk (K : MlKem) {P : PolyApi} {Au : AuthApi} (self : Ct1Sampled P Au)
(epoch : Epoch) (chunk : P.Chunk) (ct1Ack : Bool) :
StatesResult (Ct1SampledRecvChunk P Au) := do
let receivingEk ← StatesResult.ofPanic (P.add_chunk self.receiving_ek chunk)
let decoded? ← StatesResult.ofPanic (P.decoded_message receivingEk)
match decoded? with
| some decoded =>
let uc ← self.uc.recv_ek K epoch decoded
if ct1Ack then
let (uc, ct2, mac) ← StatesResult.ofPanic (uc.send_ct2 K)
let sendingCt2 ← StatesResult.ofPanic (send_ct2_encoder P ct2 mac)
.ok (.done { uc := uc, sending_ct2 := sendingCt2 })
else
.ok (.stillSending { uc := uc, sending_ct1 := self.sending_ct1 })
| none =>
if ct1Ack then
.ok (.stillReceiving { uc := self.uc, receiving_ek := receivingEk })
else
.ok (.stillReceivingStillSending
{ uc := self.uc, sending_ct1 := self.sending_ct1, receiving_ek := receivingEk })def send_ct1_chunk
def send_ct1_chunk {P : PolyApi} {Au : AuthApi} (self : Ct1Sampled P Au) :
Except StatesPanic (Ct1Sampled P Au × P.Chunk) := do
let (sendingCt1, chunk) ← P.next_chunk self.sending_ct1
.ok ({ uc := self.uc, sending_ct1 := sendingCt1, receiving_ek := self.receiving_ek }, chunk)def into_pb
def into_pb {P : PolyApi} {Au : AuthApi} (self : Ct1Sampled P Au) : V1State.Chunked.Ct1Sampled :=
{ uc := some self.uc.into_pb,
sendingCt1 := some (P.encoder_into_pb self.sending_ct1),
receivingEk := some (P.decoder_into_pb self.receiving_ek) }1 declaration not shown (lines 1189–1189): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
def from_pb
def from_pb (P : PolyApi) (Au : AuthApi) (pb : V1State.Chunked.Ct1Sampled) :
StatesResult (Ct1Sampled P Au) := do
match pb.receivingEk with
| some d =>
if d.ptsNeeded.toNat != ENCAPSULATION_KEY_SIZE / 2 then
.error (.err .msgDecode)
else
.ok ()
| none => .ok ()
let u ← match pb.uc with
| none => .error (.err .stateDecode)
| some u => .ok u
let uc ← Unchunked.SendCt.Ct1Sent.from_pb Au u
let sendingCt1 ← encoderFromPbStateDecode P pb.sendingCt1
let receivingEk ← decoderFromPbStateDecode P pb.receivingEk
.ok { uc := uc, sending_ct1 := sendingCt1, receiving_ek := receivingEk }1 declaration not shown (lines 1208–1208): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
end Ct1Samplednamespace EkReceivedCt1Sampleddef epoch
def send_ct1_chunk
def send_ct1_chunk {P : PolyApi} {Au : AuthApi} (self : EkReceivedCt1Sampled P Au) :
Except StatesPanic (EkReceivedCt1Sampled P Au × P.Chunk) := do
let (sendingCt1, chunk) ← P.next_chunk self.sending_ct1
.ok ({ uc := self.uc, sending_ct1 := sendingCt1 }, chunk)def recv_ct1_ack
EkReceivedCt1Sampled::recv_ct1_ack (src/).
def recv_ct1_ack (K : MlKem) {P : PolyApi} {Au : AuthApi}
(self : EkReceivedCt1Sampled P Au) (epoch : Epoch) :
Except StatesPanic (Ct2Sampled P Au) := do
if epoch != self.uc.epoch then
.error (.chunkedEpochMismatch "v1/chunked/send_ct.rs:237" epoch self.uc.epoch)
else
let (uc, ct2, mac) ← self.uc.send_ct2 K
let sendingCt2 ← send_ct2_encoder P ct2 mac
.ok { uc := uc, sending_ct2 := sendingCt2 }def into_pb
def into_pb {P : PolyApi} {Au : AuthApi} (self : EkReceivedCt1Sampled P Au) :
V1State.Chunked.EkReceivedCt1Sampled :=
{ uc := some self.uc.into_pb, sendingCt1 := some (P.encoder_into_pb self.sending_ct1) }1 declaration not shown (lines 1236–1236): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
def from_pb
def from_pb (P : PolyApi) (Au : AuthApi) (pb : V1State.Chunked.EkReceivedCt1Sampled) :
StatesResult (EkReceivedCt1Sampled P Au) := do
let u ← match pb.uc with
| none => .error (.err .stateDecode)
| some u => .ok u
let uc ← Unchunked.SendCt.Ct1SentEkReceived.from_pb Au u
let sendingCt1 ← encoderFromPbStateDecode P pb.sendingCt1
.ok { uc := uc, sending_ct1 := sendingCt1 }1 declaration not shown (lines 1247–1247): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
end EkReceivedCt1Samplednamespace Ct1Acknowledgeddef epoch
def recv_ek_chunk
Ct1Acknowledged::recv_ek_chunk (src/; no chunk-level epoch assert).
def recv_ek_chunk (K : MlKem) {P : PolyApi} {Au : AuthApi} (self : Ct1Acknowledged P Au)
(epoch : Epoch) (chunk : P.Chunk) : StatesResult (Ct1AcknowledgedRecvChunk P Au) := do
let receivingEk ← StatesResult.ofPanic (P.add_chunk self.receiving_ek chunk)
let decoded? ← StatesResult.ofPanic (P.decoded_message receivingEk)
match decoded? with
| some decoded =>
let uc ← self.uc.recv_ek K epoch decoded
let (uc, ct2, mac) ← StatesResult.ofPanic (uc.send_ct2 K)
let sendingCt2 ← StatesResult.ofPanic (send_ct2_encoder P ct2 mac)
.ok (.done { uc := uc, sending_ct2 := sendingCt2 })
| none =>
.ok (.stillReceiving { uc := self.uc, receiving_ek := receivingEk })def into_pb
def into_pb {P : PolyApi} {Au : AuthApi} (self : Ct1Acknowledged P Au) :
V1State.Chunked.Ct1Acknowledged :=
{ uc := some self.uc.into_pb, receivingEk := some (P.decoder_into_pb self.receiving_ek) }1 declaration not shown (lines 1273–1273): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
def from_pb
def from_pb (P : PolyApi) (Au : AuthApi) (pb : V1State.Chunked.Ct1Acknowledged) :
StatesResult (Ct1Acknowledged P Au) := do
match pb.receivingEk with
| some d =>
if d.ptsNeeded.toNat != ENCAPSULATION_KEY_SIZE / 2 then
.error (.err .msgDecode)
else
.ok ()
| none => .ok ()
let u ← match pb.uc with
| none => .error (.err .stateDecode)
| some u => .ok u
let uc ← Unchunked.SendCt.Ct1Sent.from_pb Au u
let receivingEk ← decoderFromPbStateDecode P pb.receivingEk
.ok { uc := uc, receiving_ek := receivingEk }1 declaration not shown (lines 1291–1291): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
end Ct1Acknowledgednamespace Ct2Sampleddef send_ct2_chunk
def send_ct2_chunk {P : PolyApi} {Au : AuthApi} (self : Ct2Sampled P Au) :
Except StatesPanic (Ct2Sampled P Au × P.Chunk) := do
let (sendingCt2, chunk) ← P.next_chunk self.sending_ct2
.ok ({ uc := self.uc, sending_ct2 := sendingCt2 }, chunk)def recv_next_epoch
def recv_next_epoch {P : PolyApi} {Au : AuthApi} (self : Ct2Sampled P Au) (epoch : Epoch) :
Except StatesPanic (SendEk.KeysUnsampled Au) := do
let uc ← self.uc.recv_next_epoch epoch
.ok { uc := uc }def into_pb
def into_pb {P : PolyApi} {Au : AuthApi} (self : Ct2Sampled P Au) : V1State.Chunked.Ct2Sampled :=
{ uc := some self.uc.into_pb, sendingCt2 := some (P.encoder_into_pb self.sending_ct2) }1 declaration not shown (lines 1312–1312): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
def from_pb
def from_pb (P : PolyApi) (Au : AuthApi) (pb : V1State.Chunked.Ct2Sampled) :
StatesResult (Ct2Sampled P Au) := do
let u ← match pb.uc with
| none => .error (.err .stateDecode)
| some u => .ok u
let uc ← Unchunked.SendCt.Ct2Sent.from_pb Au u
let sendingCt2 ← encoderFromPbStateDecode P pb.sendingCt2
.ok { uc := uc, sending_ct2 := sendingCt2 }1 declaration not shown (lines 1323–1323): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
end Ct2Sampledend SendCtend Chunkedinductive MessagePayload
SCKA message payload (pub enum MessagePayload, src/).
structure Message
SCKA message (pub struct Message, src/).
structure Message (P : PolyApi) where
epoch : Epoch
payload : MessagePayload P
deriving DecidableEq, Repr, Inhabitedinductive MessageType
One-byte wire tag of MessagePayload (enum MessageType, src/).
inductive MessageType where
| none
| hdr
| ek
| ekCt1Ack
| ct1Ack
| ct1
| ct2
deriving DecidableEq, Repr, Inhabitednamespace MessageTypedef toU8
def tryFromU8
def from_payload
def from_payload {P : PolyApi} : MessagePayload P → MessageType
| .none => .none
| .hdr _ => .hdr
| .ek _ => .ek
| .ekCt1Ack _ => .ekCt1Ack
| .ct1Ack _ => .ct1Ack
| .ct1 _ => .ct1
| .ct2 _ => .ct2end MessageTypedef encode_chunk
def encode_chunk {P : PolyApi} (c : P.Chunk) (into : SerializedMessage := []) : SerializedMessage :=
encode_varint ((P.chunkIndex c).zeroExtend 64) into ++ (P.chunkData c).toListdef decode_chunk
def decode_chunk (P : PolyApi) (fromSlice : Bytes) : Except Error (P.Chunk × Bytes) := do
let (index, rest) ← decode_varint fromSlice
if rest.length < 32 || index.toNat > 65535 then
.error .msgDecode
else
match bytesToVector? 32 (rest.take 32) with
| some dataVec => .ok (P.mkChunk (index.truncate 16) dataVec, rest.drop 32)
| none => .error .msgDecodenamespace Messagedef serialize
def serialize {P : PolyApi} (self : Message P) (index : BitVec 32) : SerializedMessage :=
let into : SerializedMessage := [1#8]
let into := encode_varint self.epoch into
let into := encode_varint (index.zeroExtend 64) into
let into := into ++ [(MessageType.from_payload self.payload).toU8]
match self.payload with
| .hdr chunk | .ek chunk | .ekCt1Ack chunk | .ct1 chunk | .ct2 chunk =>
encode_chunk chunk into
| .none | .ct1Ack _ =>
intodef deserialize
Message::deserialize (src/).
def deserialize (P : PolyApi) (epoch : Epoch) (fromBytes : Bytes) : Except Error (Message P) :=
match fromBytes with
| [] => .error .msgDecode
| b0 :: rest =>
match MessageType.tryFromU8 b0 with
| Option.none => .error .msgDecode
| some msgType => do
let payload ← match msgType with
| .none => .ok MessagePayload.none
| .ct1Ack => .ok (MessagePayload.ct1Ack true)
| .hdr => do
let (c, _) ← decode_chunk P rest
.ok (MessagePayload.hdr c)
| .ek => do
let (c, _) ← decode_chunk P rest
.ok (MessagePayload.ek c)
| .ekCt1Ack => do
let (c, _) ← decode_chunk P rest
.ok (MessagePayload.ekCt1Ack c)
| .ct1 => do
let (c, _) ← decode_chunk P rest
.ok (MessagePayload.ct1 c)
| .ct2 => do
let (c, _) ← decode_chunk P rest
.ok (MessagePayload.ct2 c)
.ok { epoch := epoch, payload := payload }end Messageinductive States
Top-level 11-variant SPQR V1 SCKA state (pub enum States, src/).
inductive States (P : PolyApi) (Au : AuthApi) where
| keysUnsampled (s : Chunked.SendEk.KeysUnsampled Au)
| keysSampled (s : Chunked.SendEk.KeysSampled P Au)
| headerSent (s : Chunked.SendEk.HeaderSent P Au)
| ct1Received (s : Chunked.SendEk.Ct1Received P Au)
| ekSentCt1Received (s : Chunked.SendEk.EkSentCt1Received P Au)
| noHeaderReceived (s : Chunked.SendCt.NoHeaderReceived P Au)
| headerReceived (s : Chunked.SendCt.HeaderReceived P Au)
| ct1Sampled (s : Chunked.SendCt.Ct1Sampled P Au)
| ekReceivedCt1Sampled (s : Chunked.SendCt.EkReceivedCt1Sampled P Au)
| ct1Acknowledged (s : Chunked.SendCt.Ct1Acknowledged P Au)
| ct2Sampled (s : Chunked.SendCt.Ct2Sampled P Au)
deriving DecidableEq, Reprstructure V1Send
Output of States. (pub struct Send, src/).
structure V1Send (P : PolyApi) (Au : AuthApi) where
msg : Message P
key : Option EpochSecret
state : States P Au
deriving DecidableEq, Reprstructure V1Recv
Output of States. (pub struct Recv, src/).
structure V1Recv (P : PolyApi) (Au : AuthApi) where
key : Option EpochSecret
state : States P Au
deriving DecidableEq, Reprnamespace Statesdef init_a
def init_a (P : PolyApi) (Au : AuthApi) (authKey : Bytes) :
Except StatesPanic (States P Au) := do
let s ← Chunked.SendEk.KeysUnsampled.new Au authKey
.ok (.keysUnsampled s)1 declaration not shown (lines 1485–1485): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
def init_b
def init_b (P : PolyApi) (Au : AuthApi) (authKey : Bytes) :
Except StatesPanic (States P Au) := do
let s ← Chunked.SendCt.NoHeaderReceived.new P Au authKey
.ok (.noHeaderReceived s)1 declaration not shown (lines 1493–1493): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
def epoch
def epoch {P : PolyApi} {Au : AuthApi} : States P Au → Epoch
| .keysUnsampled s => s.epoch
| .keysSampled s => s.epoch
| .headerSent s => s.epoch
| .ct1Received s => s.epoch
| .ekSentCt1Received s => s.epoch
| .noHeaderReceived s => s.epoch
| .headerReceived s => s.epoch
| .ct1Sampled s => s.epoch
| .ekReceivedCt1Sampled s => s.epoch
| .ct1Acknowledged s => s.epoch
| .ct2Sampled s => s.epochdef into_pb
def into_pb {P : PolyApi} {Au : AuthApi} (self : States P Au) : V1State :=
{ innerState := some <| match self with
| .keysUnsampled s => .keysUnsampled s.into_pb
| .keysSampled s => .keysSampled s.into_pb
| .headerSent s => .headerSent s.into_pb
| .ct1Received s => .ct1Received s.into_pb
| .ekSentCt1Received s => .ekSentCt1Received s.into_pb
| .noHeaderReceived s => .noHeaderReceived s.into_pb
| .headerReceived s => .headerReceived s.into_pb
| .ct1Sampled s => .ct1Sampled s.into_pb
| .ekReceivedCt1Sampled s => .ekReceivedCt1Sampled s.into_pb
| .ct1Acknowledged s => .ct1Acknowledged s.into_pb
| .ct2Sampled s => .ct2Sampled s.into_pb }1 declaration not shown (lines 1522–1522): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
def from_pb
def from_pb (P : PolyApi) (Au : AuthApi) (pb : V1State) : StatesResult (States P Au) :=
match pb.innerState with
| none => .error (.err .stateDecode)
| some (.keysUnsampled s) => .keysUnsampled <$> Chunked.SendEk.KeysUnsampled.from_pb Au s
| some (.keysSampled s) => .keysSampled <$> Chunked.SendEk.KeysSampled.from_pb P Au s
| some (.headerSent s) => .headerSent <$> Chunked.SendEk.HeaderSent.from_pb P Au s
| some (.ct1Received s) => .ct1Received <$> Chunked.SendEk.Ct1Received.from_pb P Au s
| some (.ekSentCt1Received s) =>
.ekSentCt1Received <$> Chunked.SendEk.EkSentCt1Received.from_pb P Au s
| some (.noHeaderReceived s) =>
.noHeaderReceived <$> Chunked.SendCt.NoHeaderReceived.from_pb P Au s
| some (.headerReceived s) =>
.headerReceived <$> Chunked.SendCt.HeaderReceived.from_pb P Au s
| some (.ct1Sampled s) => .ct1Sampled <$> Chunked.SendCt.Ct1Sampled.from_pb P Au s
| some (.ekReceivedCt1Sampled s) =>
.ekReceivedCt1Sampled <$> Chunked.SendCt.EkReceivedCt1Sampled.from_pb P Au s
| some (.ct1Acknowledged s) =>
.ct1Acknowledged <$> Chunked.SendCt.Ct1Acknowledged.from_pb P Au s
| some (.ct2Sampled s) => .ct2Sampled <$> Chunked.SendCt.Ct2Sampled.from_pb P Au s1 declaration not shown (lines 1544–1544): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification.
def send
def send (K : MlKem) {P : PolyApi} {Au : AuthApi} (self : States P Au) (tape : Bytes) :
StatesResult (V1Send P Au × Bytes) :=
match self with
| .keysUnsampled state => do
let epoch := state.epoch
let (state', chunk, tape') ← StatesResult.ofPanic (state.send_hdr_chunk K P tape)
.ok ({ state := .keysSampled state',
msg := { epoch := epoch, payload := .hdr chunk },
key := none }, tape')
| .keysSampled state => do
let epoch := state.epoch
let (state', chunk) ← StatesResult.ofPanic state.send_hdr_chunk
.ok ({ state := .keysSampled state',
msg := { epoch := epoch, payload := .hdr chunk },
key := none }, tape)
| .headerSent state => do
let epoch := state.epoch
let (state', chunk) ← StatesResult.ofPanic state.send_ek_chunk
.ok ({ state := .headerSent state',
msg := { epoch := epoch, payload := .ek chunk },
key := none }, tape)
| .ct1Received state => do
let epoch := state.epoch
let (state', chunk) ← StatesResult.ofPanic state.send_ek_chunk
.ok ({ state := .ct1Received state',
msg := { epoch := epoch, payload := .ekCt1Ack chunk },
key := none }, tape)
| .ekSentCt1Received state =>
let epoch := state.epoch
.ok ({ state := .ekSentCt1Received state,
msg := { epoch := epoch, payload := .ct1Ack true },
key := none }, tape)
| .noHeaderReceived state =>
let epoch := state.epoch
.ok ({ state := .noHeaderReceived state,
msg := { epoch := epoch, payload := .none },
key := none }, tape)
| .headerReceived state => do
let epoch := state.epoch
let (state', chunk, epochSecret, tape') ← StatesResult.ofPanic (state.send_ct1_chunk K tape)
.ok ({ state := .ct1Sampled state',
msg := { epoch := epoch, payload := .ct1 chunk },
key := some epochSecret }, tape')
| .ct1Sampled state => do
let epoch := state.epoch
let (state', chunk) ← StatesResult.ofPanic state.send_ct1_chunk
.ok ({ state := .ct1Sampled state',
msg := { epoch := epoch, payload := .ct1 chunk },
key := none }, tape)
| .ekReceivedCt1Sampled state => do
let epoch := state.epoch
let (state', chunk) ← StatesResult.ofPanic state.send_ct1_chunk
.ok ({ state := .ekReceivedCt1Sampled state',
msg := { epoch := epoch, payload := .ct1 chunk },
key := none }, tape)
| .ct1Acknowledged state =>
let epoch := state.epoch
.ok ({ state := .ct1Acknowledged state,
msg := { epoch := epoch, payload := .none },
key := none }, tape)
| .ct2Sampled state => do
let epoch := state.epoch
let (state', chunk) ← StatesResult.ofPanic state.send_ct2_chunk
.ok ({ state := .ct2Sampled state',
msg := { epoch := epoch, payload := .ct2 chunk },
key := none }, tape)def recv
def recv (K : MlKem) {P : PolyApi} {Au : AuthApi} (self : States P Au) (msg : Message P) :
StatesResult (V1Recv P Au) :=
match self with
| .keysUnsampled state =>
if msg.epoch > state.epoch then
.error (.err (.epochOutOfRange msg.epoch))
else
.ok { key := none, state := .keysUnsampled state }
| .keysSampled state =>
if msg.epoch > state.epoch then
.error (.err (.epochOutOfRange msg.epoch))
else if msg.epoch < state.epoch then
.ok { key := none, state := .keysSampled state }
else
match msg.payload with
| .ct1 chunk => do
let s' ← StatesResult.ofPanic (state.recv_ct1_chunk msg.epoch chunk)
.ok { key := none, state := .headerSent s' }
| _ => .ok { key := none, state := .keysSampled state }
| .headerSent state =>
if msg.epoch > state.epoch then
.error (.err (.epochOutOfRange msg.epoch))
else if msg.epoch < state.epoch then
.ok { key := none, state := .headerSent state }
else
match msg.payload with
| .ct1 chunk => do
let res ← StatesResult.ofPanic (state.recv_ct1_chunk msg.epoch chunk)
match res with
| .stillReceiving s' => .ok { key := none, state := .headerSent s' }
| .done s' => .ok { key := none, state := .ct1Received s' }
| _ => .ok { key := none, state := .headerSent state }
| .ct1Received state =>
if msg.epoch > state.epoch then
.error (.err (.epochOutOfRange msg.epoch))
else if msg.epoch < state.epoch then
.ok { key := none, state := .ct1Received state }
else
match msg.payload with
| .ct2 chunk => do
let s' ← StatesResult.ofPanic (state.recv_ct2_chunk msg.epoch chunk)
.ok { key := none, state := .ekSentCt1Received s' }
| _ => .ok { key := none, state := .ct1Received state }
| .ekSentCt1Received state =>
if msg.epoch > state.epoch then
.error (.err (.epochOutOfRange msg.epoch))
else if msg.epoch < state.epoch then
.ok { key := none, state := .ekSentCt1Received state }
else
match msg.payload with
| .ct2 chunk => do
let res ← state.recv_ct2_chunk K msg.epoch chunk
match res with
| .stillReceiving s' => .ok { key := none, state := .ekSentCt1Received s' }
| .done (s', sec) => .ok { key := some sec, state := .noHeaderReceived s' }
| _ => .ok { key := none, state := .ekSentCt1Received state }
| .noHeaderReceived state =>
if msg.epoch > state.epoch then
.error (.err (.epochOutOfRange msg.epoch))
else if msg.epoch < state.epoch then
.ok { key := none, state := .noHeaderReceived state }
else
match msg.payload with
| .hdr chunk => do
let res ← state.recv_hdr_chunk msg.epoch chunk
match res with
| .stillReceiving s' => .ok { key := none, state := .noHeaderReceived s' }
| .done s' => .ok { key := none, state := .headerReceived s' }
| _ => .ok { key := none, state := .noHeaderReceived state }
| .headerReceived state =>
if msg.epoch > state.epoch then
.error (.err (.epochOutOfRange msg.epoch))
else
.ok { key := none, state := .headerReceived state }
| .ct1Sampled state =>
if msg.epoch > state.epoch then
.error (.err (.epochOutOfRange msg.epoch))
else if msg.epoch < state.epoch then
.ok { key := none, state := .ct1Sampled state }
else
let chunkAck? : Option (P.Chunk × Bool) := match msg.payload with
| .ek chunk => some (chunk, false)
| .ekCt1Ack chunk => some (chunk, true)
| _ => none
match chunkAck? with
| none => .ok { key := none, state := .ct1Sampled state }
| some (chunk, ack) => do
let res ← state.recv_ek_chunk K msg.epoch chunk ack
match res with
| .stillReceivingStillSending s' => .ok { key := none, state := .ct1Sampled s' }
| .stillReceiving s' => .ok { key := none, state := .ct1Acknowledged s' }
| .stillSending s' => .ok { key := none, state := .ekReceivedCt1Sampled s' }
| .done s' => .ok { key := none, state := .ct2Sampled s' }
| .ekReceivedCt1Sampled state =>
if msg.epoch > state.epoch then
.error (.err (.epochOutOfRange msg.epoch))
else if msg.epoch < state.epoch then
.ok { key := none, state := .ekReceivedCt1Sampled state }
else
let isAck := match msg.payload with
| .ct1Ack true => true
| .ekCt1Ack _ => true
| _ => false
if isAck then do
let s' ← StatesResult.ofPanic (state.recv_ct1_ack K msg.epoch)
.ok { key := none, state := .ct2Sampled s' }
else
.ok { key := none, state := .ekReceivedCt1Sampled state }
| .ct1Acknowledged state =>
if msg.epoch > state.epoch then
.error (.err (.epochOutOfRange msg.epoch))
else if msg.epoch < state.epoch then
.ok { key := none, state := .ct1Acknowledged state }
else
let chunk? : Option P.Chunk := match msg.payload with
| .ek chunk => some chunk
| .ekCt1Ack chunk => some chunk
| _ => none
match chunk? with
| none => .ok { key := none, state := .ct1Acknowledged state }
| some chunk => do
let res ← state.recv_ek_chunk K msg.epoch chunk
match res with
| .stillReceiving s' => .ok { key := none, state := .ct1Acknowledged s' }
| .done s' => .ok { key := none, state := .ct2Sampled s' }
| .ct2Sampled state =>
if msg.epoch > state.epoch then
-- `msg.epoch > state.epoch` implies `state.epoch < u64::MAX`, so `state.epoch + 1` cannot overflow.
if msg.epoch == state.epoch + 1#64 then do
let s' ← StatesResult.ofPanic (state.recv_next_epoch msg.epoch)
.ok { key := none, state := .keysUnsampled s' }
else
.error (.err (.epochOutOfRange msg.epoch))
else
.ok { key := none, state := .ct2Sampled state }end States16 declarations not shown (lines 1757–2079): theorems, which Lean checks, or definitions that no headline statement uses
CryptoVerification., CryptoVerification., CryptoVerification., CryptoVerification., CryptoVerification., CryptoVerification., CryptoVerification., CryptoVerification., CryptoVerification., CryptoVerification., CryptoVerification., CryptoVerification., CryptoVerification., CryptoVerification., CryptoVerification., CryptoVerification., CryptoVerification., CryptoVerification., CryptoVerification., CryptoVerification., CryptoVerification., CryptoVerification., CryptoVerification.
end CryptoVerification.LibsignalSpqrV1