Event Transition Tables

PALISADE v1.2 — Informative Appendix

This document provides event transition tables for the PALISADE v1.2 epoch state machine. These tables specify the actions taken in response to events in each state, as implemented in the reference implementation.

These tables are informative and should be read together with the normative text of the main specification (Section 11.11). If a discrepancy appears, the normative text wins.

1. Decryptor Epoch State Transitions

The decryptor maintains an epoch state machine with STEADY and TRANSITION states. State transitions are triggered by authenticated control frames and commit criteria.

Current StateEventActionNext StateImplementation Method
STEADYAuthenticated CTRL_REKEY received
  • Validate next epoch ID = current + 1
  • Derive and cache next epoch keys (AEAD, IV)
  • Set armedNextEpoch = true
  • Record armedAt timestamp
  • Reset packetsOnNextEpoch = 0
TRANSITIONArmNextEpoch()
TRANSITIONCommit threshold reached (packetsOnNextEpoch >= commitThreshold)
  • Install next epoch in epochDecryptor
  • Update payloadKey
  • Zero old keys (forward secrecy)
  • Set armedNextEpoch = false
  • Reset packetsOnNextEpoch = 0
STEADYCommitEpochTransition()
TRANSITIONTimeout exceeded (time.Since(armedAt) > maxTransitionTime)
  • Same as commit threshold action
  • Enforced during packet processing (opportunistic check)
STEADYCheckTransitionTimeout() + CommitEpochTransition()
STEADYPacket received with key_phase=0
  • Attempt decryption with current epoch keys
  • Validate replay window
  • Process packet if valid
STEADYDecrypt()decryptDeterministic()
STEADYPacket received with key_phase=1
  • Reject: IsKeyPhaseValid() returns false
  • Decryption fails (expected)
  • Increment DecryptionFailures stat
STEADYIsKeyPhaseValid() validation
TRANSITIONPacket received with key_phase=0
  • Attempt decryption with current epoch keys (indicated key_phase)
  • If successful, process packet
  • If failed, attempt with alternate key_phase (next epoch)
TRANSITIONdecryptDeterministic() with fallback
TRANSITIONPacket received with key_phase=1
  • Attempt decryption with next epoch keys (indicated key_phase)
  • If successful, increment packetsOnNextEpoch
  • Check commit threshold (may trigger transition to STEADY)
  • If failed, attempt with alternate key_phase (current epoch)
TRANSITION (or STEADY if threshold met)RecordPacketOnNextEpoch() + commit check

State Validation Rules

  • ArmNextEpoch(): MUST be in STEADY state, returns error if already in TRANSITION
  • CommitEpochTransition(): MUST be in TRANSITION state, returns error if not
  • IsKeyPhaseValid(): key_phase=0 always valid, key_phase=1 only valid in TRANSITION
  • Maximum 2 decrypt attempts per packet in TRANSITION state (indicated key_phase first, then alternate)

2. Encryptor Transition State

The encryptor maintains a transition flag (inTransition) that controls the key_phase bit in the PublicHeader.

Transition StateEventActionkey_phase ValueImplementation Method
inTransition = falseNew epoch installed
  • Install epoch in epochEncryptor
  • Set inTransition = true
  • Set transitionEpoch = epochID
  • Record transitionStarted timestamp
key_phase=1 (for new epoch packets)InstallEpoch()
inTransition = trueEncrypt packet on transitionEpoch
  • Check if epoch == transitionEpoch
  • Set flags |= FlagKeyPhase (bit 2)
  • Encrypt with new epoch keys
key_phase=1Encrypt() (conditional flag setting)
inTransition = trueTransition completed (decryptor committed)
  • Set inTransition = false
  • Set transitionEpoch = 0
key_phase=0 (for all packets)CompleteTransition()
inTransition = trueTimeout exceeded (time.Since(transitionStarted) > maxTransitionTime)
  • Opportunistic check during Encrypt()
  • Set inTransition = false
  • Set transitionEpoch = 0
key_phase=0 (after timeout)CheckTransitionTimeout() (in Encrypt())

Key Phase Setting Logic

var flags uint8 = 0
if e.inTransition && epoch == e.transitionEpoch {
    // key_phase=1 indicates new epoch during transition
    flags |= packet.FlagKeyPhase
}

The key_phase bit (bit 2) is set to 1 only when:

  • inTransition = true, AND
  • The packet is being encrypted for transitionEpoch

3. Key Phase Behavior Summary

This table summarizes how key_phase is interpreted and validated in each state.

Statekey_phase ValueSender BehaviorReceiver BehaviorValid?
STEADY0Always set to 0 (current epoch)Decrypt with current epoch keys (1 attempt)✓ Valid
STEADY1Never set (invalid state)Reject: IsKeyPhaseValid() returns false✗ Invalid
TRANSITION0Set to 0 for packets on current epochDecrypt with current epoch keys first, fallback to next epoch if fails (max 2 attempts)✓ Valid
TRANSITION1Set to 1 for packets on new epoch (transitionEpoch)Decrypt with next epoch keys first, fallback to current epoch if fails (max 2 attempts)✓ Valid

4. Transition Commit Criteria

The transition from TRANSITION to STEADY state is committed when any of the following criteria are met:

CriterionConditionCheck LocationImplementation
Packet ThresholdpacketsOnNextEpoch >= commitThresholdAfter successful decryption with key_phase=1RecordPacketOnNextEpoch() returns shouldCommit = true
Time Thresholdtime.Since(armedAt) > maxTransitionTimeOpportunistic check during Decrypt()CheckTransitionTimeout() returns shouldCommit = true
Explicit Control FrameFuture: Explicit commit control frame (if supported)Upon control frame processingNot currently implemented

Default Configuration

  • maxTransitionTime: 30 seconds (default)
  • commitThreshold: Configurable per session (default may vary)
  • Normative Requirement: MUST NOT remain in TRANSITION indefinitely. Timeout MUST be enforced.

5. Error Conditions and Invalid Transitions

The following error conditions are detected and handled by the state machine:

Error ConditionDetectionActionImplementation
ArmNextEpoch() called in TRANSITIONState validation: epochState != EpochStateSteadyReturn error: "cannot arm next epoch: already in transition"ArmNextEpoch() validation
CommitEpochTransition() called in STEADYState validation: epochState != EpochStateTransitionReturn error: "cannot commit: not in transition state"CommitEpochTransition() validation
Invalid next epoch IDnextEpochID != currentEpoch + 1Return error: "invalid next epoch: expected X, got Y"ArmNextEpoch() validation
key_phase=1 in STEADY stateIsKeyPhaseValid() returns falseReject packet, increment DecryptionFailuresdecryptDeterministic() validation
CommitEpochTransition() with no armed epoch!armedNextEpochReturn error: "no epoch armed"CommitEpochTransition() validation

PALISADE Protocol Specification Draft 00

INFORMATIONAL