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 State | Event | Action | Next State | Implementation Method |
|---|---|---|---|---|
| STEADY | Authenticated CTRL_REKEY received |
| TRANSITION | ArmNextEpoch() |
| TRANSITION | Commit threshold reached (packetsOnNextEpoch >= commitThreshold) |
| STEADY | CommitEpochTransition() |
| TRANSITION | Timeout exceeded (time.Since(armedAt) > maxTransitionTime) |
| STEADY | CheckTransitionTimeout() + CommitEpochTransition() |
| STEADY | Packet received with key_phase=0 |
| STEADY | Decrypt() → decryptDeterministic() |
| STEADY | Packet received with key_phase=1 |
| STEADY | IsKeyPhaseValid() validation |
| TRANSITION | Packet received with key_phase=0 |
| TRANSITION | decryptDeterministic() with fallback |
| TRANSITION | Packet received with key_phase=1 |
| 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=0always valid,key_phase=1only 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 State | Event | Action | key_phase Value | Implementation Method |
|---|---|---|---|---|
inTransition = false | New epoch installed |
| key_phase=1 (for new epoch packets) | InstallEpoch() |
inTransition = true | Encrypt packet on transitionEpoch |
| key_phase=1 | Encrypt() (conditional flag setting) |
inTransition = true | Transition completed (decryptor committed) |
| key_phase=0 (for all packets) | CompleteTransition() |
inTransition = true | Timeout exceeded (time.Since(transitionStarted) > maxTransitionTime) |
| 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.
| State | key_phase Value | Sender Behavior | Receiver Behavior | Valid? |
|---|---|---|---|---|
| STEADY | 0 | Always set to 0 (current epoch) | Decrypt with current epoch keys (1 attempt) | ✓ Valid |
| STEADY | 1 | Never set (invalid state) | Reject: IsKeyPhaseValid() returns false | ✗ Invalid |
| TRANSITION | 0 | Set to 0 for packets on current epoch | Decrypt with current epoch keys first, fallback to next epoch if fails (max 2 attempts) | ✓ Valid |
| TRANSITION | 1 | Set 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:
| Criterion | Condition | Check Location | Implementation |
|---|---|---|---|
| Packet Threshold | packetsOnNextEpoch >= commitThreshold | After successful decryption with key_phase=1 | RecordPacketOnNextEpoch() returns shouldCommit = true |
| Time Threshold | time.Since(armedAt) > maxTransitionTime | Opportunistic check during Decrypt() | CheckTransitionTimeout() returns shouldCommit = true |
| Explicit Control Frame | Future: Explicit commit control frame (if supported) | Upon control frame processing | Not 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 Condition | Detection | Action | Implementation |
|---|---|---|---|
| ArmNextEpoch() called in TRANSITION | State validation: epochState != EpochStateSteady | Return error: "cannot arm next epoch: already in transition" | ArmNextEpoch() validation |
| CommitEpochTransition() called in STEADY | State validation: epochState != EpochStateTransition | Return error: "cannot commit: not in transition state" | CommitEpochTransition() validation |
| Invalid next epoch ID | nextEpochID != currentEpoch + 1 | Return error: "invalid next epoch: expected X, got Y" | ArmNextEpoch() validation |
| key_phase=1 in STEADY state | IsKeyPhaseValid() returns false | Reject packet, increment DecryptionFailures | decryptDeterministic() validation |
| CommitEpochTransition() with no armed epoch | !armedNextEpoch | Return error: "no epoch armed" | CommitEpochTransition() validation |
PALISADE Protocol Specification Draft 00
INFORMATIONAL