Message Flow Diagrams

PALISADE v1.2 — Informative Appendix

This section provides ASCII art diagrams illustrating the message flows for the initial handshake and resumption. These diagrams show the high-level message exchange and cryptographic operations.

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

1. Initial Handshake (1-RTT)

The full handshake establishes a new PALISADE session with mutual authentication and post-quantum key establishment.

Client                                                Server
------                                                ------

Generate ephemeral KEM keypair (K_c)
ClientNonce = random(32)

ClientHello:
  version (0x12)
  supported_kems[] (list)
  supported_sigs[] (list)
  supported_aeads[] (list)
  client_nonce (32 bytes)
  K_c (ephemeral KEM public key)
  client_certificate (mandatory)
  [client_signature] (if mutual auth)
  [extensions]                              ------->

                                         Verify ClientHello
                                         Select algorithms:
                                           kem_choice, sig_choice, aead_choice
                                         Generate K_s, ServerNonce
                                         ss_c = Encap(K_c) → CT_c
                                         ss_s = Encap(K_s) → CT_s
                                         Derive shared secrets
                                         Encode canonical transcript
                                         Sign transcript_hash

                               <-------  ServerHello:
                                           version (0x12)
                                           kem_choice
                                           sig_choice
                                           aead_choice
                                           server_nonce (32 bytes)
                                           K_s (ephemeral KEM public key)
                                           CT_c (KEM ciphertext for client)
                                           CT_s (KEM ciphertext for server)
                                           server_certificate
                                           server_signature
                                           [extensions]

ss_c = Decap(CT_c)
ss_s = Decap(CT_s)
Encode canonical transcript
Verify ServerSig(transcript_hash)
Derive keys via key schedule:
  - early_secret
  - handshake_secret
  - master_secret
  - epoch 0 keys (C2S, S2C)

[Encrypted Data]               <------>  [Encrypted Data]

                    === ESTABLISHED ===

Round Trips: 1-RTT (one round trip time)

Key Points:

  • ClientHello includes lists of supported algorithms (not single values)
  • ServerHello contains single choices from the client's lists
  • Version is a single byte (0x12 for PALISADE v1.2)
  • Client certificate is mandatory in full handshake
  • Transcript encoding excludes signatures (canonical form)
  • Both endpoints derive the same keys from shared secrets

2. Resumption Handshake (0-RTT)

The resumption handshake allows clients to resume a previous session using a resumption ticket, enabling 0-RTT early data.

Client                                                Server
------                                                ------

Retrieve ResumeTicket (from previous session)
Generate new ephemeral KEM keypair (K'_c)
resume_nonce = random(32)

ZeroRTTRequest:
  resume_ticket
  K'_c (new ephemeral KEM public key)
  resume_nonce (32 bytes)
  [early_data] (0-RTT data, optional)        ------->

                                         Validate ResumeTicket
                                         Extract PSK from ticket
                                         Generate server_nonce'
                                         ss'_c = Encap(K'_c) → CT'_c
                                         Encode canonical transcript
                                         Sign transcript_hash
                                         Derive keys using resumption
                                           key schedule (PSK-based)

                               <-------  ServerHelloResume:
                                           version (0x12)
                                           server_nonce' (32 bytes)
                                           CT'_c (KEM ciphertext)
                                           server_certificate
                                           server_signature

ss'_c = Decap(CT'_c)
Encode canonical transcript
Verify ServerSig(transcript_hash)
Derive keys via resumption key schedule:
  - Uses PSK from ticket
  - Binds to transcript_hash
  - Derives epoch 0 keys

[Encrypted Data]               <------>  [Encrypted Data]

                    === ESTABLISHED ===

Round Trips: 0-RTT (zero round trip time) for early data, 1-RTT for full resumption

Key Points:

  • Client uses a previously obtained ResumeTicket
  • Early data (0-RTT) can be sent with ZeroRTTRequest
  • Server MUST enforce ticket-defined max_early_data_bytes limit
  • Resumption key schedule uses PSK from ticket, not full handshake secrets
  • Early data uses epoch ID 0xFFFFFFFF and seq >= 1
  • Early data is replayable and MUST only be used for idempotent operations

3. Message Field Details (v1.2)

MessageFieldTypeNotes
ClientHelloversionuint80x12 for PALISADE v1.2
supported_kems[]list<uint16>Ordered list of KEM algorithm IDs
supported_sigs[]list<uint16>Ordered list of signature algorithm IDs
supported_aeads[]list<uint16>Ordered list of AEAD algorithm IDs
client_nonce32 bytesCryptographically random
K_cvariableClient's ephemeral KEM public key
ServerHelloversionuint80x12 for PALISADE v1.2
kem_choiceuint16Selected from client's supported_kems[]
sig_choiceuint16Selected from client's supported_sigs[]
aead_choiceuint16Selected from client's supported_aeads[]
server_nonce32 bytesCryptographically random
K_svariableServer's ephemeral KEM public key
CT_cvariableKEM encapsulation to K_c
CT_svariableKEM encapsulation to K_s
server_certificatevariableServer's post-quantum public key

4. Key Derivation Flow

After the handshake completes, both endpoints derive the same keys using the key schedule:

Shared Secrets:
  ss_c = Decap(CT_c)  (client decapsulates)
  ss_s = Decap(CT_s)  (server decapsulates)

Key Schedule Input:
  IKM = ss_c || ss_s || client_nonce || server_nonce
  (96 bytes total for ML-KEM-768)

Key Derivation (HKDF):
  early_secret = HKDF-Extract(salt=0, IKM)
  handshake_secret = HKDF-Extract(salt=early_secret, IKM)
  master_secret = HKDF-Extract(salt=handshake_secret, IKM)

Epoch 0 Keys:
  epoch_0_keys = HKDF-Expand(master_secret, "palisade epoch 0", 64)
  C2S_key = epoch_0_keys[0:32]  (client-to-server)
  S2C_key = epoch_0_keys[32:64]  (server-to-client)
  C2S_IV = HKDF-Expand(master_secret, "palisade iv c2s 0", 12)
  S2C_IV = HKDF-Expand(master_secret, "palisade iv s2c 0", 12)

RID Derivation (for session identification):
  steering_prefix = HKDF-Expand(client_secret, "palisade rid steering", 8)
  privacy_suffix = HKDF-Expand(client_secret, salt || "palisade rid privacy", 14)
  RID = steering_prefix || rotation_epoch || privacy_suffix (24 bytes)

PALISADE Protocol Specification Draft 00

INFORMATIONAL