<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt"?>

<rfc xmlns:xi="http://www.w3.org/2001/XInclude"
     category="exp"
     docName="draft-sgcp-state-graph-cryptographic-protocol-00"
     ipr="trust200902"
     obsoletes=""
     updates=""
     submissionType="independent"
     xml:lang="en"
     tocInclude="true"
     tocDepth="4"
     symRefs="true"
     sortRefs="true"
     version="3">

  <!-- ============================================================ -->
  <!--  FRONT MATTER                                                 -->
  <!-- ============================================================ -->
  <front>
    <title abbrev="SGCP">
      State Graph Cryptographic Protocol (SGCP)
    </title>

    <seriesInfo name="Internet-Draft"
                value="draft-sgcp-state-graph-cryptographic-protocol-00"/>

    <author fullname="Sripad Karthik" initials="S." surname="Karthik">
      <organization abbrev="Independent">Independent Submission</organization>
      <address>
        <email>sripadkarthik@gmail.com</email>
        <uri>https://datatracker.ietf.org/doc/draft-sgcp-state-graph-cryptographic-protocol/</uri>
      </address>
    </author>

    <date year="2026" month="August" day="15"/>

    <area>Security</area>
    <workgroup>Individual Submission</workgroup>

    <keyword>state graph</keyword>
    <keyword>cryptographic protocol</keyword>
    <keyword>session security</keyword>
    <keyword>ECDH</keyword>
    <keyword>ML-KEM</keyword>
    <keyword>epoch</keyword>
    <keyword>packet transformation</keyword>
    <keyword>context binding</keyword>
    <keyword>replay protection</keyword>
    <keyword>full-duplex</keyword>
    <keyword>media transfer</keyword>
    <keyword>MP3</keyword>

    <abstract>
      <t>
        This document specifies the State Graph Cryptographic Protocol
        (SGCP), a communication-security framework in which a client and
        server establish a cryptographically protected session and maintain
        a synchronized state graph throughout the lifetime of the
        communication session.
      </t>
      <t>
        SGCP combines device identity, port context, socket context,
        session identity, ECDH-based shared-secret establishment,
        cryptographic key derivation, epochs, packet sequence numbers,
        authenticated state transitions, state-dependent packet
        transformation, replay protection, continuous context verification,
        controlled reauthentication, and session recovery.
      </t>
      <t>
        The central principle is that both endpoints independently derive
        the same cryptographic state from a common authenticated session
        secret and deterministic state information. The state graph defines
        which communication states are valid and which transitions are
        permitted.
      </t>
      <t>
        This document also illustrates the protocol with a worked example
        of a full-duplex binary media file transfer (an MP3 audio file)
        showing the complete packet-level exchange.
      </t>
    </abstract>
  </front>

  <!-- ============================================================ -->
  <!--  MIDDLE                                                        -->
  <!-- ============================================================ -->
  <middle>

    <!-- ===== Section 1: Introduction ===== -->
    <section anchor="intro" numbered="true" toc="default">
      <name>Introduction</name>
      <t>
        Modern communication security protocols, such as TLS
        <xref target="RFC8446"/> and DTLS <xref target="RFC9147"/>,
        establish shared secrets and derive traffic keys but treat each
        packet largely independently from the perspective of the state
        machine governing what constitutes a valid packet at a given point
        in the session. Session context (the device, the port, the socket)
        is typically authenticated only at the handshake and not
        continuously bound to individual packet keys.
      </t>
      <t>
        The State Graph Cryptographic Protocol (SGCP) addresses this
        limitation by introducing the concept of a cryptographic state
        graph: a deterministically derived directed graph in which each
        node represents a valid cryptographic communication state (keyed
        to the current epoch, sequence number, and context binding) and
        each edge represents a cryptographically authenticated transition
        between two such states.
      </t>
      <t>SGCP provides the following security properties:</t>
      <ul spacing="normal">
        <li>Mutual device authentication via certificate-based
            challenge-response.</li>
        <li>Forward-secure key establishment via ECDH (with optional
            ML-KEM <xref target="FIPS203"/> hybridization for post-quantum
            protection).</li>
        <li>Per-packet key uniqueness: each packet uses a fresh key derived
            from the epoch key, direction, and sequence number.</li>
        <li>Context binding: the session cryptographic state is bound to the
            Device-Port-Socket tuple at key-derivation time.</li>
        <li>Authenticated state transitions: every transition in the state
            graph is cryptographically verified.</li>
        <li>Replay protection: a sequence-number window rejects replayed
            packets even if their cryptographic authentication were to
            pass.</li>
        <li>Epoch-based key rotation: significant context changes or policy
            events advance the epoch and derive fresh key material without
            disclosing the root secret again.</li>
        <li>Session recovery: a reconnecting peer must re-authenticate and
            establish a new epoch, preventing session-token reuse
            attacks.</li>
      </ul>
      <t>
        This document specifies the protocol in full and illustrates its
        operation with a worked example involving the full-duplex transfer
        of a sample MP3 audio file between two SGCP endpoints.
      </t>
    </section>

    <!-- ===== Section 2: Conventions ===== -->
    <section anchor="conventions" numbered="true" toc="default">
      <name>Conventions and Definitions</name>

      <section anchor="req-lang" numbered="true" toc="default">
        <name>Requirements Language</name>
        <t>
          The key words <bcp14>MUST</bcp14>, <bcp14>MUST NOT</bcp14>,
          <bcp14>REQUIRED</bcp14>, <bcp14>SHALL</bcp14>,
          <bcp14>SHALL NOT</bcp14>, <bcp14>SHOULD</bcp14>,
          <bcp14>SHOULD NOT</bcp14>, <bcp14>RECOMMENDED</bcp14>,
          <bcp14>NOT RECOMMENDED</bcp14>, <bcp14>MAY</bcp14>, and
          <bcp14>OPTIONAL</bcp14> in this document are to be interpreted as
          described in BCP&nbsp;14 <xref target="RFC2119"/>
          <xref target="RFC8174"/> when, and only when, they appear in all
          capitals, as shown here.
        </t>
      </section>

      <section anchor="terminology" numbered="true" toc="default">
        <name>Terminology</name>
        <dl newline="false" spacing="normal">
          <dt>State Graph:</dt>
          <dd>A deterministically derived directed graph in which each node
              represents a valid cryptographic communication state and each
              directed edge represents a permitted and cryptographically
              authenticated state transition.</dd>

          <dt>Node:</dt>
          <dd>A vertex in the state graph representing one valid
              cryptographic communication state. A node is identified by
              the tuple (Session_ID, Epoch, Sequence, Direction).</dd>

          <dt>Edge:</dt>
          <dd>A directed arc between two nodes representing a permitted
              transition. An edge carries an Authentication_Proof.</dd>

          <dt>Epoch:</dt>
          <dd>A cryptographic generation. Each epoch possesses a distinct
              set of derived keys. A new epoch is created upon a
              key-rotation event, a context change requiring
              reauthentication, or a session-recovery event.</dd>

          <dt>Root Secret:</dt>
          <dd>The session-level secret derived from the authenticated
              DH/ECDH exchange. The root secret is the ultimate
              key-derivation ancestor and is never transmitted.</dd>

          <dt>Epoch Key:</dt>
          <dd>A key derived from the Root Secret scoped to a particular
              epoch. Packet keys for all packets within the epoch are
              derived from the Epoch Key.</dd>

          <dt>Packet Key:</dt>
          <dd>A per-packet symmetric key derived from the Epoch Key, packet
              direction, and sequence number using a KDF.</dd>

          <dt>Context Binding:</dt>
          <dd>The cryptographic hash of the normalized Device-Port-Socket
              context tuple that binds the session to its communication
              environment.</dd>

          <dt>Transformation State:</dt>
          <dd>A deterministic, state-dependent bit-level transformation
              applied to the ciphertext prior to placing the packet on the
              wire. Derived from the Epoch Key, sequence, and direction;
              not a substitute for AEAD.</dd>

          <dt>Key_ID:</dt>
          <dd>A non-secret identifier for the expected cryptographic state
              of a packet, computed as H(Session_ID || Epoch || Direction
              || Sequence).</dd>

          <dt>Session Recovery:</dt>
          <dd>The process by which a reconnecting endpoint proves its
              identity, triggers a new epoch, and resumes communication
              without reusing old key material.</dd>

          <dt>Hash Chain:</dt>
          <dd>A monotonically advancing chain of cryptographic hash values
              linking successive state-graph nodes, providing tamper-evident
              ordering across the communication session.</dd>
        </dl>
      </section>
    </section>

    <!-- ===== Section 3: Architecture ===== -->
    <section anchor="architecture" numbered="true" toc="default">
      <name>High-Level Architecture</name>
      <t>
        The overall SGCP architecture is shown in
        <xref target="fig-arch"/>.
      </t>
      <figure anchor="fig-arch">
        <name>SGCP High-Level Architecture</name>
        <artwork align="center" alt="SGCP Architecture Diagram"><![CDATA[
                     +----------------------+
                     |       CLIENT         |
                     |  Device Identity     |
                     |  Private Key         |
                     |  Certificate         |
                     |  Context Monitor     |
                     +----------+-----------+
                                |
                                | Handshake
                                v
                     +----------+-----------+
                     |   AUTHENTICATION     |
                     |  Identity Validation |
                     |  Certificate Check   |
                     |  Challenge/Response  |
                     +----------+-----------+
                                |
                                v
                     +----------+-----------+
                     |   KEY ESTABLISHMENT  |
                     |  ECDH / DH           |
                     |  Optional ML-KEM     |
                     +----------+-----------+
                                |
                                v
                     +----------+-----------+
                     |    ROOT SECRET       |
                     |   (Session Secret)   |
                     +----------+-----------+
                                |
             +------------------+------------------+
             |                  |                  |
             v                  v                  v
    Device Context       Port Context       Socket Context
             |                  |                  |
             +------------------+------------------+
                                v
                       Context Binding
                                |
                                v
                     +----------+-----------+
                     |    STATE ENGINE      |
                     |  Epoch / Sequence    |
                     |  Direction / Key ID  |
                     |  Context / Trust     |
                     +----------+-----------+
                                |
                                v
                     +----------+-----------+
                     |    STATE GRAPH       |
                     |  Nodes + Auth Edges  |
                     |  + Hash Chain        |
                     +----------+-----------+
                                |
                                v
                     +----------+-----------+
                     |   PACKET ENGINE      |
                     |  Key Derivation      |
                     |  AEAD Encryption     |
                     |  Transformation      |
                     +----------+-----------+
                                |
                                v
                              PACKET
                                |
                                v
                     +----------+-----------+
                     |       SERVER         |
                     |  State Reconstruction|
                     |  Verification        |
                     |  Decryption          |
                     |  Trust Evaluation    |
                     +----------------------+
        ]]></artwork>
      </figure>
    </section>

    <!-- ===== Section 4: X.509 Certificate Integration ===== -->
    <section anchor="x509-integration" numbered="true" toc="default">
      <name>X.509 Certificate Integration and Protocol Stack</name>

      <section anchor="x509-role" numbered="true" toc="default">
        <name>Role of X.509 in SGCP</name>
        <t>
          SGCP uses X.509 <xref target="RFC5280"/> certificates exclusively
          to establish the authenticated identities of both endpoints during
          the handshake. X.509 defines the certificate format and the
          identity-binding mechanism; SGCP defines how those certificates are
          used and how the authentication outcome feeds into the cryptographic
          state graph.
        </t>
        <t>The separation of concerns is:</t>
        <ul spacing="normal">
          <li>X.509: "This public key belongs to this authenticated
              identity."</li>
          <li>SGCP: Uses that authenticated identity to establish a session
              Root Secret and derive a cryptographic state graph that governs
              every subsequent packet.</li>
        </ul>
        <t>
          X.509 certificates do NOT contain the SGCP state graph, epoch
          state, or packet keys. They exist only at the authentication
          boundary.
        </t>
      </section>

      <section anchor="x509-stack" numbered="true" toc="default">
        <name>Complete Protocol Stack</name>
        <t>
          The full stack, from identity layer to packet protection, is:
        </t>
        <figure anchor="fig-protocol-stack">
          <name>SGCP Complete Protocol Stack</name>
          <artwork align="center"><![CDATA[
                       SGCP
                        |
              +---------+---------+
              |                   |
       X.509 Certificate        ECDH
       (via OpenSSL)          Exchange
              |                   |
              v                   v
         Authenticate        Shared Secret
              |                   |
              +---------+---------+
                        |
                        v
                  KDF / Key Tree
                 (HKDF, Section 8)
                        |
                        v
               SGCP Root Secret
                        |
                        v
               SGCP State Graph
                        |
              +---------+---------+
              v                   v
          State Node          State Edge
              |                   |
              +---------+---------+
                        |
                        v
                Packet Protection
           (Epoch Key -> Packet Key -> AEAD)
          ]]></artwork>
        </figure>
        <t>Stated as a linear stack:</t>
        <artwork align="left"><![CDATA[
   OpenSSL
      |
      v
   X.509 Certificates  (identity and public-key binding)
      |
      v
   SGCP Authentication (challenge-response, certificate validation)
      |
      v
   ECDH / ML-KEM       (shared secret establishment)
      |
      v
   KDF                 (HKDF-Extract/Expand with domain labels)
      |
      v
   SGCP Root Secret    (session-level cryptographic anchor)
      |
      v
   SGCP State Graph    (epoch, sequence, context-bound nodes/edges)
      |
      v
   Per-Packet Key      (AEAD + state-dependent transformation)
      |
      v
   Wire Packet
        ]]></artwork>
      </section>

      <section anchor="x509-cert-reqs" numbered="true" toc="default">
        <name>Certificate Requirements</name>
        <t>Each SGCP endpoint <bcp14>MUST</bcp14> possess:</t>
        <artwork align="left"><![CDATA[
   client.crt   (X.509 end-entity certificate, DER or PEM)
   client.key   (private key corresponding to the certificate)

   server.crt
   server.key
        ]]></artwork>
        <t>Certificates <bcp14>MUST</bcp14>:</t>
        <ul spacing="normal">
          <li>Be signed by a CA trusted by the remote endpoint, or be
              mutually pre-configured as trusted.</li>
          <li>Contain a Subject Alternative Name (SAN) or Common Name (CN)
              entry matching the Device_ID used in the SGCP handshake.</li>
          <li>Not be expired or revoked at the time of handshake.</li>
          <li>Use a key algorithm consistent with the negotiated SGCP cipher
              suite (e.g., P-256 or Ed25519).</li>
        </ul>
        <t>The certificate hash used in Root Secret derivation is:</t>
        <artwork align="left"><![CDATA[
   Certificate_Hash = SHA-256(DER-encoded certificate)
        ]]></artwork>
        <t>
          This binds the Root Secret to the specific certificates exchanged
          during this handshake, preventing certificate substitution attacks.
        </t>
      </section>

      <section anchor="x509-openssl" numbered="true" toc="default">
        <name>OpenSSL Integration</name>
        <t>
          Implementations <bcp14>MAY</bcp14> use OpenSSL (or a compatible
          TLS library) to perform the X.509 certificate operations during
          the SGCP handshake. The following OpenSSL operations are involved:
        </t>
        <ul spacing="normal">
          <li>
            <t>Certificate loading:</t>
            <artwork align="left"><![CDATA[
   SSL_CTX_use_certificate_file(ctx, "server.crt", SSL_FILETYPE_PEM);
   SSL_CTX_use_PrivateKey_file(ctx, "server.key", SSL_FILETYPE_PEM);
            ]]></artwork>
          </li>
          <li>
            <t>Certificate verification:</t>
            <artwork align="left"><![CDATA[
   SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback);
   SSL_CTX_load_verify_locations(ctx, "ca-chain.crt", NULL);
            ]]></artwork>
          </li>
          <li>
            <t>Certificate inspection (Device_ID from SAN/CN):</t>
            <artwork align="left"><![CDATA[
   X509 *cert = SSL_get_peer_certificate(ssl);
   X509_NAME *subj = X509_get_subject_name(cert);
   X509_NAME_get_text_by_NID(subj, NID_commonName, buf, sizeof(buf));
            ]]></artwork>
          </li>
          <li>
            <t>ECDH key generation (for SGCP's own DH exchange):</t>
            <artwork align="left"><![CDATA[
   EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, NULL);
   EVP_PKEY_keygen_init(ctx);
   EVP_PKEY_keygen(ctx, &pkey);
            ]]></artwork>
          </li>
        </ul>
        <t>
          <strong>IMPORTANT:</strong> When OpenSSL is used as an underlying
          library, the SGCP handshake runs ON TOP OF the X.509 certificate
          exchange. SGCP does not delegate its state graph, epoch management,
          or packet key derivation to OpenSSL. OpenSSL is used only for
          certificate parsing, signature verification, and ECDH primitives.
        </t>
      </section>

      <section anchor="x509-handshake-flow" numbered="true" toc="default">
        <name>SGCP Handshake with X.509 Certificate Flow</name>
        <t>
          The complete handshake, showing certificate exchange and the
          transition from X.509-authenticated identity into SGCP state:
        </t>
        <figure anchor="fig-x509-handshake">
          <name>SGCP Handshake Certificate Flow</name>
          <artwork align="left"><![CDATA[
   CLIENT                                    SERVER
   (client.crt + client.key)         (server.crt + server.key)

   |-- ClientHello --------------------------->|
   |   + Client X.509 Certificate              |
   |   + Client DH Public Key                  |
   |   + Client KEM Public Key (if PQ)         |
   |   + Client_Nonce                          |
                              Verify client certificate chain
                              Extract Device_ID from SAN/CN
                              Lookup Device_ID in device registry
                              Verify certificate not revoked
                              Generate Server_Challenge

   |<-- ServerHello ---------------------------|  
   |   + Server X.509 Certificate              |
   |   + Server DH Public Key                  |
   |   + Server KEM Ciphertext (if PQ)         |
   |   + Server_Challenge                      |
   |   + ServerHello_Signature                 |

   Verify server certificate chain
   Verify ServerHello_Signature
   Compute DH_Secret (X25519)
   Decapsulate KEM_Secret (if PQ)
       |
       v
   Root_Secret = HKDF-Extract(
       "SGCP_ROOT_PQ_v1",
       DH_Secret || KEM_Secret
       || Client_Nonce || Server_Nonce
       || SHA-256(client.crt)
       || SHA-256(server.crt))

   |-- ClientFinish -------------------------->|
   |   + Challenge_Response                    |
   |     (signed with client.key)              |
   |   + ClientFinish_MAC                      |
                              Verify Challenge_Response
                              Compute DH_Secret, Root_Secret
                              |
                              v
                         SGCP takes over:
                              |
                              v
                     Session_ID = H("SGCP_SID" || ...)
                              |
                              v
                       Epoch_0_Key = HKDF-Expand(...)
                              |
                              v
                      Initial State N0
                              |
                              v
                    N0 -> N1 -> N2 -> N3 -> ...

   After ClientFinish: X.509 is no longer involved.
   Both sides enter the state graph at N0.
          ]]></artwork>
        </figure>
      </section>

      <section anchor="x509-vs-sgcp" numbered="true" toc="default">
        <name>What X.509 Establishes vs. What SGCP Establishes</name>
        <table anchor="tbl-x509-sgcp" align="center">
          <name>X.509 vs. SGCP Responsibility Boundary</name>
          <thead>
            <tr>
              <th>X.509 Establishes</th>
              <th>SGCP Establishes</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>Identity binding</td>
              <td>Session Root Secret</td>
            </tr>
            <tr>
              <td>Public key authenticity</td>
              <td>Epoch key hierarchy</td>
            </tr>
            <tr>
              <td>Certificate validity</td>
              <td>Per-packet unique keys</td>
            </tr>
            <tr>
              <td>Chain of trust to CA</td>
              <td>State graph (N0, N1, N2, ...)</td>
            </tr>
            <tr>
              <td>Revocation status</td>
              <td>Context binding</td>
            </tr>
            <tr>
              <td>Signature algorithms</td>
              <td>Replay protection windows</td>
            </tr>
            <tr>
              <td></td>
              <td>Epoch transitions</td>
            </tr>
            <tr>
              <td></td>
              <td>Authenticated state edges</td>
            </tr>
            <tr>
              <td></td>
              <td>Hash chain linking nodes</td>
            </tr>
          </tbody>
        </table>
        <t>
          In summary: X.509 answers "who are you?"  SGCP answers "what
          cryptographic state governs each byte of our ongoing session?"
        </t>
      </section>
    </section>

    <!-- ===== Section 5: Protocol Phases ===== -->
    <section anchor="phases" numbered="true" toc="default">
      <name>Protocol Phases</name>

      <section anchor="phase1" numbered="true" toc="default">
        <name>Phase 1 - Client Initialization</name>
        <t>
          The process begins before any network communication. The client
          possesses:
        </t>
        <ul spacing="normal">
          <li>A Device_ID (a stable unique device identifier)</li>
          <li>A Device Public Key / Private Key pair</li>
          <li>A certificate binding the public key to the Device_ID</li>
          <li>An application-level identity (AppID)</li>
          <li>A local security policy and Trust State</li>
        </ul>
        <t>
          The client's private key <bcp14>MUST</bcp14> never be transmitted
          to the server or any third party.
        </t>
        <t>The server maintains a device registry containing at minimum:</t>
        <artwork align="left"><![CDATA[
   Device_ID
   Public_Key
   Certificate_ID
   Status
   Policy_ID
   Key_Version
   Trust_State
        ]]></artwork>
        <t>
          Only Device_IDs with Status = AUTHORIZED <bcp14>MAY</bcp14>
          initiate a new session.
        </t>
      </section>

      <section anchor="phase2" numbered="true" toc="default">
        <name>Phase 2 - Initial Connection</name>
        <t>
          The client establishes a transport connection to the server. The
          communication context is the tuple:
        </t>
        <artwork align="left"><![CDATA[
   Context = (Device_ID, Protocol, Local_Port, Remote_Port,
              Socket_ID, Session_Nonce)
        ]]></artwork>
        <t>
          SGCP does not treat IP address, MAC address, port number, or
          socket identifiers as secret. These are context attributes whose
          purpose is to bind the cryptographic session to its communication
          environment.
        </t>
        <t>The client <bcp14>SHOULD</bcp14> compute:</t>
        <artwork align="left"><![CDATA[
   Prelim_Context_Hash =
       H("SGCP_CTX_v1" || Device_ID || Protocol
         || Local_Port || Remote_Port || Socket_ID)
        ]]></artwork>
      </section>

      <section anchor="phase3" numbered="true" toc="default">
        <name>Phase 3 - Authentication</name>
        <t>
          SGCP performs mutual authentication via a three-message
          challenge-response exchange.
        </t>
        <t><strong>Message 1 (Client Hello):</strong></t>
        <artwork align="left"><![CDATA[
   ClientHello {
       ProtocolVersion,
       SupportedCipherSuites,
       Device_ID,
       Certificate,
       Client_Nonce,
       Client_DH_Public_Key,
       Client_KEM_Public_Key   (if ML-KEM is negotiated)
   }
        ]]></artwork>
        <t><strong>Message 2 (Server Hello):</strong></t>
        <artwork align="left"><![CDATA[
   ServerHello {
       SelectedCipherSuite,
       Server_Certificate,
       Server_Nonce,
       Server_DH_Public_Key,
       Server_KEM_Ciphertext,  (if ML-KEM is negotiated)
       Server_Challenge,
       ServerHello_Signature
   }

   ServerHello_Signature =
       Sign(Server_Private_Key,
            H("SGCP_SHELLO" || ClientHello || ServerHello_data))
        ]]></artwork>
        <t><strong>Message 3 (Client Finish):</strong></t>
        <artwork align="left"><![CDATA[
   ClientFinish {
       Challenge_Response,
       ClientFinish_MAC
   }

   Challenge_Response =
       Sign(Client_Private_Key,
            H("SGCP_CHALLENGE" || Server_Challenge || Client_Nonce))

   ClientFinish_MAC =
       HMAC(Handshake_Key,
            H("SGCP_CFIN" || ClientHello || ServerHello))
        ]]></artwork>
        <t>
          If any validation step fails, the server <bcp14>MUST</bcp14>
          terminate the connection with an authentication-failure alert.
        </t>
      </section>

      <section anchor="phase4" numbered="true" toc="default">
        <name>Phase 4 - Shared Secret Establishment</name>
        <t>
          The recommended primitive is X25519 <xref target="RFC7748"/> or
          P-256. The raw shared secret <bcp14>MUST NOT</bcp14> be used
          directly as a traffic key. Instead:
        </t>
        <artwork align="left"><![CDATA[
   Root_Secret =
       HKDF-Extract("SGCP_ROOT_v1",
                     DH_Secret || Client_Nonce || Server_Nonce
                     || Client_Certificate_Hash
                     || Server_Certificate_Hash)
        ]]></artwork>
        <t>
          If post-quantum protection is required, a hybrid construction is
          used:
        </t>
        <artwork align="left"><![CDATA[
   Root_Secret =
       HKDF-Extract("SGCP_ROOT_PQ_v1",
                     DH_Secret || KEM_Secret
                     || Client_Nonce || Server_Nonce
                     || Client_Certificate_Hash
                     || Server_Certificate_Hash)
        ]]></artwork>
        <t>
          The post-quantum KEM <bcp14>MUST</bcp14> be a standardized
          algorithm such as ML-KEM-768 <xref target="FIPS203"/>. Custom or
          proprietary KEMs <bcp14>MUST NOT</bcp14> be used.
        </t>
      </section>

      <section anchor="phase5" numbered="true" toc="default">
        <name>Phase 5 - Session Creation</name>
        <t>
          Both endpoints independently create the initial session state:
        </t>
        <artwork align="left"><![CDATA[
   Session_ID = H("SGCP_SID" || Root_Secret || Client_Nonce
                  || Server_Nonce)
   Epoch      = 0
   Sequence   = 0
   Direction  = Client->Server (C->S channel)
                Server->Client (S->C channel)
   Node_ID    = N0
        ]]></artwork>
        <t>
          SGCP is a full-duplex protocol. Each direction maintains
          independent sequence numbering and per-direction key derivation.
        </t>
      </section>

      <section anchor="phase6" numbered="true" toc="default">
        <name>Phase 6 - Device-Port-Socket Context</name>
        <t>The Context Binding is computed as:</t>
        <artwork align="left"><![CDATA[
   Context_Binding =
       H("SGCP_CTX_BIND_v1"
         || Version || Device_ID || Protocol
         || Local_Port || Remote_Port
         || Socket_ID || Session_ID)
        ]]></artwork>
        <t>
          The Context Binding becomes an input to all epoch-key derivations,
          thereby cryptographically binding every packet key to the
          communication environment.
        </t>
      </section>

      <section anchor="phase7" numbered="true" toc="default">
        <name>Phase 7 - Creation of the State Graph</name>
        <t>The first node of the state graph is:</t>
        <artwork align="left"><![CDATA[
   N0 = {
       Node_ID        : H("SGCP_NODE" || Session_ID || 0 || 0),
       Session_ID     : <from Phase 5>,
       Epoch          : 0,
       Sequence       : 0,
       Context_Binding: <from Phase 6>,
       Key_ID         : H(Session_ID || 0 || "C->S" || 0),
       Direction      : Client->Server,
       State_Status   : ACTIVE,
       Chain_Hash     : H("SGCP_CHAIN_GENESIS" || Session_ID)
   }
        ]]></artwork>
        <t>Subsequent nodes form the hash chain:</t>
        <artwork align="left"><![CDATA[
   N(k+1).Chain_Hash =
       H("SGCP_CHAIN" || N(k).Chain_Hash || N(k).Node_ID
         || Sequence(k+1) || Epoch)
        ]]></artwork>
        <t>Normal graph growth:</t>
        <artwork align="left"><![CDATA[
   N0 --E0--> N1 --E1--> N2 --E2--> N3 --E3--> N4 ...
        ]]></artwork>
      </section>

      <section anchor="phase8" numbered="true" toc="default">
        <name>Phase 8 - Packet Creation</name>
        <t>
          For every outgoing packet, the sender performs the following
          sequence:
        </t>
        <ol spacing="normal" type="(%d)">
          <li>Read (Session_ID, Epoch, Sequence, Direction,
              Context_Binding).</li>
          <li>
            <t>Derive Epoch_Key and Packet_Key:</t>
            <artwork align="left"><![CDATA[
   Epoch_Key =
       HKDF-Expand(Root_Secret,
                   "SGCP_EPOCH" || Epoch || Context_Binding,
                   key_length)

   Packet_Key =
       HKDF-Expand(Epoch_Key,
                   "SGCP_PACKET" || Direction || Sequence,
                   key_length)
            ]]></artwork>
          </li>
          <li>Construct AAD = Session_ID || Epoch || Sequence || Direction
              || Context_Binding || Key_ID.</li>
          <li>
            <t>AEAD-Encrypt:</t>
            <artwork align="left"><![CDATA[
   (Ciphertext, Tag) =
       AEAD-Encrypt(Packet_Key, Nonce, Plaintext, AAD)

   Nonce = Epoch || Sequence || Direction
            ]]></artwork>
          </li>
          <li>
            <t>Derive Transform_State and apply wire transformation:</t>
            <artwork align="left"><![CDATA[
   Transform_State =
       HKDF-Expand(Epoch_Key,
                   "SGCP_TRANSFORM" || Sequence || Direction,
                   transform_length)

   Wire_Payload = Transform(Ciphertext || Tag, Transform_State)
            ]]></artwork>
          </li>
          <li>Transmit the wire packet and advance Sequence += 1.</li>
        </ol>
      </section>

      <section anchor="phase9" numbered="true" toc="default">
        <name>Phase 9 - Receiver Processing</name>
        <t>Upon receipt of a packet the receiver performs:</t>
        <ol spacing="normal" type="(%d)">
          <li>Parse the packet header.</li>
          <li>Look up the session by Session_ID.</li>
          <li>Read Epoch from the packet header.</li>
          <li>Validate the Sequence number against the replay window.</li>
          <li>Verify Key_ID matches H(Session_ID||Epoch||Direction||Sequence).
              If not, discard.</li>
          <li>Derive Epoch_Key, Packet_Key, and Transform_State.</li>
          <li>Reverse the wire transformation.</li>
          <li>AEAD-Decrypt and verify the authentication tag. If verification
              fails, silently discard.</li>
          <li>Accept the state transition and advance the sequence window.</li>
          <li>Evaluate Context and Trust State.</li>
        </ol>
        <t>
          The receiver <bcp14>MUST NOT</bcp14> attempt multiple candidate
          transformations or keys. Only one deterministically derived state
          is tested per packet.
        </t>
      </section>

      <section anchor="phase10" numbered="true" toc="default">
        <name>Phase 10 - State Advancement</name>
        <t>
          After successful packet verification, both sender and receiver
          independently advance their local state:
        </t>
        <artwork align="left"><![CDATA[
   Sequence += 1
   Node_ID  = H("SGCP_NODE" || Session_ID || Epoch || Sequence)
        ]]></artwork>
      </section>

      <section anchor="phase11" numbered="true" toc="default">
        <name>Phase 11 - Replay Protection</name>
        <t>
          Each endpoint maintains a replay window per (Session_ID, Epoch,
          Direction) tuple with Window_High and a Window_Bits bitmap covering
          [Window_High - W + 1, Window_High] where W is the configured
          window size (<bcp14>RECOMMENDED</bcp14>: W &gt;= 64).
        </t>
        <t>Upon receipt of a packet with Sequence S:</t>
        <ul spacing="normal">
          <li>If S &lt;= Window_High - W: DISCARD (too old).</li>
          <li>If S is within the window and the bit is set: DISCARD
              (duplicate).</li>
          <li>If S &gt; Window_High: advance window after AEAD
              verification.</li>
          <li>If S is within the window and the bit is clear: accept after
              AEAD verification.</li>
        </ul>
        <t>A new epoch resets the replay window for that direction.</t>
      </section>

      <section anchor="phase12" numbered="true" toc="default">
        <name>Phase 12 - Continuous Context Monitoring</name>
        <t>
          SGCP does not permanently trust a session once established. Both
          endpoints <bcp14>SHOULD</bcp14> continuously monitor device,
          network, port, socket, session, and behavioral context.
        </t>
        <figure anchor="fig-trust">
          <name>Trust Engine Decision</name>
          <artwork align="center"><![CDATA[
          Context Change
                |
                v
          Trust Engine
                |
    +-----------+-----------+
    v           v           v
 ACCEPT       REAUTH     REVOKE
    |           |           |
    v           v           v
 Continue    Verify     Terminate
          ]]></artwork>
        </figure>
      </section>
    </section>

    <!-- ===== Section 5: Packet Format ===== -->
    <section anchor="packet-format" numbered="true" toc="default">
      <name>Packet Format</name>

      <section anchor="common-header" numbered="true" toc="default">
        <name>Common Packet Header</name>
        <figure anchor="fig-header">
          <name>SGCP Common Packet Header</name>
          <artwork align="left"><![CDATA[
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Version (8)   | Packet_Type(8)| Flags     (8) | Reserved  (8) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Session_ID  (128 bits)                     |
|                                                               |
|                                                               |
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|        Epoch  (32 bits)       |                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |
|              Sequence Number  (64 bits)                       |
|                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                               |   Direction   |  Reserved     |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                      Key_ID   (64 bits)                       |
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|         Payload Length (32)   |       Header Checksum (16)    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
          ]]></artwork>
        </figure>

        <dl newline="false" spacing="normal">
          <dt>Version (8 bits):</dt>
          <dd>SGCP version. This document defines version 1 (0x01).</dd>

          <dt>Packet_Type (8 bits):</dt>
          <dd>
            <artwork align="left"><![CDATA[
   0x01 = CLIENT_HELLO       0x02 = SERVER_HELLO
   0x03 = CLIENT_FINISH      0x04 = DATA
   0x05 = CONTEXT_CHANGE     0x06 = KEY_ROTATION
   0x07 = REAUTH_REQUEST     0x08 = REAUTH_RESPONSE
   0x09 = RECOVERY_INIT      0x0A = RECOVERY_ACK
   0x0B = ALERT              0x0C = SESSION_CLOSE
   0x10 = MEDIA_SEGMENT      0x11 = MEDIA_ACK
            ]]></artwork>
          </dd>

          <dt>Flags (8 bits):</dt>
          <dd>
            <artwork align="left"><![CDATA[
   Bit 0 = FULL_DUPLEX
   Bit 1 = EPOCH_BOUNDARY
   Bit 2 = CONTEXT_CHANGED
   Bit 3 = KEY_ROTATION_PENDING
   Bits 4-7 = Reserved
            ]]></artwork>
          </dd>

          <dt>Direction (8 bits):</dt>
          <dd>0x01 = Client-to-Server; 0x02 = Server-to-Client.</dd>

          <dt>Session_ID (128 bits):</dt>
          <dd>Unique session identifier derived in Phase 5.</dd>

          <dt>Epoch (32 bits):</dt>
          <dd>Current epoch number.</dd>

          <dt>Sequence (64 bits):</dt>
          <dd>Per-direction monotonically increasing packet sequence number.
              Wraps to a new epoch before reaching 2^64 - 1.</dd>

          <dt>Key_ID (64 bits):</dt>
          <dd>H(Session_ID || Epoch || Direction || Sequence)[0:8].</dd>

          <dt>Payload_Length (32 bits):</dt>
          <dd>Length of wire payload (transformed ciphertext + AEAD tag)
              in bytes.</dd>

          <dt>Header_Checksum (16 bits):</dt>
          <dd>CRC-16 over all header fields except this field itself.</dd>
        </dl>
      </section>

      <section anchor="media-header" numbered="true" toc="default">
        <name>Media Segment Packet Extension</name>
        <t>
          For MEDIA_SEGMENT (0x10) packets, an additional media header
          precedes the segment data within the encrypted plaintext:
        </t>
        <figure anchor="fig-media-header">
          <name>SGCP Media Segment Inner Header</name>
          <artwork align="left"><![CDATA[
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Media_Type (8)| Codec    (8)  |  Segment_Index    (32)      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           Total_Segments      (32)                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|       Byte_Offset_in_File     (64)                          |
|                                                             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|       Segment_Byte_Length     (32)                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|       File_Hash (SHA-256, 32 bytes)                         |
|                                                             |
|                                                             |
|                                                             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|               Segment_Data (variable)                       |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
          ]]></artwork>
        </figure>
        <t>
          Media_Type: 0x01 = AUDIO. Codec: 0x01 = MP3, 0x02 = AAC,
          0x03 = OPUS, 0xFF = RAW. File_Hash is SHA-256 over the
          complete unencrypted file, enabling end-to-end integrity
          verification after reassembly.
        </t>
      </section>
    </section>

    <!-- ===== Section 6: State Graph Model ===== -->
    <section anchor="state-graph" numbered="true" toc="default">
      <name>State Graph Model</name>

      <section anchor="graph-nodes" numbered="true" toc="default">
        <name>Graph Nodes</name>
        <artwork align="left"><![CDATA[
   Node = {
       Node_ID         : H("SGCP_NODE"  || Session_ID
                           || Epoch || Sequence),
       Session_ID      : <session identifier>,
       Epoch           : <epoch number>,
       Sequence        : <sequence number>,
       Context_Binding : <from Section 4.6>,
       Key_ID          : <non-secret key identifier>,
       Direction       : <C->S | S->C>,
       State_Status    : ACTIVE | SUSPENDED | TERMINATED,
       Chain_Hash      : H("SGCP_CHAIN" || Prev_Chain_Hash
                           || Node_ID || Sequence || Epoch)
   }
        ]]></artwork>
        <t>
          Secret keys <bcp14>MUST NOT</bcp14> be stored inside the node
          record; they are derived on demand from the key hierarchy.
        </t>
      </section>

      <section anchor="graph-edges" numbered="true" toc="default">
        <name>Graph Edges</name>
        <artwork align="left"><![CDATA[
   Edge = {
       Previous_Node       : Node_ID(k),
       Next_Node           : Node_ID(k+1),
       Sequence            : k,
       Event               : <event type>,
       Context_Version     : <Context_Binding at time of edge>,
       Transition_Type     : NORMAL | EPOCH_BOUNDARY
                             | REAUTH | RECOVERY | REVOCATION,
       Authentication_Proof: AEAD_Tag(Packet(k))
   }
        ]]></artwork>
      </section>

      <section anchor="deterministic-derivation" numbered="true"
               toc="default">
        <name>Deterministic State Derivation</name>
        <t>
          The graph is reproducible from authenticated state; it does not
          need to be transmitted as a secret object.
        </t>
        <artwork align="left"><![CDATA[
   Node_Key =
       HKDF-Expand(Root_Secret,
                   "SGCP_NODEKEY" || Session_ID || Epoch || Node_ID,
                   key_length)

   Packet_Key =
       HKDF-Expand(Epoch_Key,
                   "SGCP_PACKET" || Direction || Sequence,
                   key_length)
        ]]></artwork>
      </section>
    </section>

    <!-- ===== Section 7: Key Hierarchy ===== -->
    <section anchor="key-hierarchy" numbered="true" toc="default">
      <name>Key Hierarchy</name>

      <section anchor="root-secret" numbered="true" toc="default">
        <name>Root Secret</name>
        <t>
          The Root Secret is the sole ancestor of all cryptographic keys.
          It <bcp14>MUST</bcp14> be protected in memory and erased when the
          session terminates.
        </t>
      </section>

      <section anchor="epoch-key" numbered="true" toc="default">
        <name>Epoch Key</name>
        <artwork align="left"><![CDATA[
   Epoch_Key =
       HKDF-Expand(Root_Secret,
                   "SGCP_EPOCH" || uint32(Epoch)
                   || Context_Binding,
                   key_length)
        ]]></artwork>
        <t>
          Old Epoch Keys <bcp14>SHOULD</bcp14> be erased after epoch
          transition to maintain forward secrecy within the session.
        </t>
      </section>

      <section anchor="packet-key" numbered="true" toc="default">
        <name>Packet Key</name>
        <artwork align="left"><![CDATA[
   Packet_Key =
       HKDF-Expand(Epoch_Key,
                   "SGCP_PACKET" || Direction || uint64(Sequence),
                   key_length)
        ]]></artwork>
      </section>

      <section anchor="transform-key" numbered="true" toc="default">
        <name>Transformation State Key</name>
        <artwork align="left"><![CDATA[
   Transform_State =
       HKDF-Expand(Epoch_Key,
                   "SGCP_TRANSFORM" || uint64(Sequence)
                   || Direction,
                   transform_length)
        ]]></artwork>
      </section>

      <section anchor="domain-labels" numbered="true" toc="default">
        <name>Domain Separation Labels</name>
        <t>
          The following labels <bcp14>MUST</bcp14> be used as-is (ASCII,
          no null terminator) in all HKDF-Expand info parameters:
        </t>
        <artwork align="left"><![CDATA[
   "SGCP_ROOT_v1"       "SGCP_ROOT_PQ_v1"
   "SGCP_SID"           "SGCP_HANDSHAKE"
   "SGCP_EPOCH"         "SGCP_PACKET"
   "SGCP_TRANSFORM"     "SGCP_NODEKEY"
   "SGCP_CHAIN"         "SGCP_CHAIN_GENESIS"
   "SGCP_CTX_BIND_v1"   "SGCP_RECOVERY"
        ]]></artwork>
      </section>
    </section>

    <!-- ===== Section 8: Transformation ===== -->
    <section anchor="transformation" numbered="true" toc="default">
      <name>State-Dependent Packet Transformation</name>
      <t>
        The state-dependent transformation is a deterministic, invertible
        byte-level operation applied to the AEAD ciphertext+tag before the
        packet is placed on the wire.
      </t>
      <t>The transformation <bcp14>MUST</bcp14> satisfy:</t>
      <ul spacing="normal">
        <li>Determinism: identical inputs always produce identical
            output.</li>
        <li>Invertibility: the receiver can recover Ciphertext from the
            wire payload and Transform_State.</li>
        <li>Non-ambiguity: there is exactly one inverse.</li>
        <li>Independence from the AEAD primitive.</li>
      </ul>
      <t>
        The transformation <bcp14>MUST NOT</bcp14> be used as a substitute
        for encryption. Confidentiality and integrity are guaranteed by the
        AEAD construction.
      </t>
    </section>

    <!-- ===== Section 9: Epoch Architecture ===== -->
    <section anchor="epochs" numbered="true" toc="default">
      <name>Epoch Architecture</name>
      <t>
        A session is divided into one or more epochs. Each epoch possesses
        a unique epoch number, a distinct Epoch Key, an independent
        sequence-number space starting from 0, and an independent replay
        window.
      </t>
      <figure anchor="fig-epochs">
        <name>Multi-Epoch Session Structure</name>
        <artwork align="left"><![CDATA[
   SESSION S1

   Epoch 0:  N0 -> N1 -> N2 -> N3
                              |
                              | Context Change
                              v
   Epoch 1:  N0' -> N1' -> N2' -> N3'
                              |
                              | Key Rotation
                              v
   Epoch 2:  N0'' -> N1'' -> N2''
        ]]></artwork>
      </figure>

      <section anchor="context-change" numbered="true" toc="default">
        <name>Context Change</name>
        <t>When a context-change event is detected:</t>
        <ul spacing="normal">
          <li>ACCEPT: Context changed within policy bounds. Continue
              current epoch and update Context_Binding.</li>
          <li>REAUTH: Context changed beyond policy bounds. Initiate
              reauthentication, derive new Epoch Key, reset sequence
              space.</li>
          <li>REVOKE: Context indicates potential compromise. Immediately
              terminate the session.</li>
        </ul>
      </section>

      <section anchor="key-rotation" numbered="true" toc="default">
        <name>Key Rotation</name>
        <t>
          Proactive key rotation <bcp14>SHOULD</bcp14> occur after a
          configurable number of packets (e.g., every 2^32 packets) within
          one epoch, after a configurable time interval, or upon receipt of
          a KEY_ROTATION packet from the peer.
        </t>
      </section>
    </section>

    <!-- ===== Section 10: State Transition Engine ===== -->
    <section anchor="transition-engine" numbered="true" toc="default">
      <name>State Transition Engine</name>

      <section anchor="transition-events" numbered="true" toc="default">
        <name>Transition Events</name>
        <artwork align="left"><![CDATA[
   PACKET_ACCEPTED    KEY_ROTATION    CONTEXT_CHANGED
   REAUTHENTICATED    SESSION_RECOVERY  TIMEOUT
   POLICY_CHANGE      REVOCATION
        ]]></artwork>
      </section>

      <section anchor="transition-examples" numbered="true" toc="default">
        <name>Transition Examples</name>
        <artwork align="left"><![CDATA[
   Normal:
     N100 -- PACKET_ACCEPTED --> N101

   Key Rotation:
     N101 -- KEY_ROTATION --> N0(Epoch+1)

   Context Change + Reauth:
     N200 -- CONTEXT_CHANGED --> T0
     T0   -- REAUTHENTICATED --> N0(Epoch+1)

   Revocation:
     N300 -- REVOCATION --> TERMINATED
        ]]></artwork>
      </section>
    </section>

    <!-- ===== Section 11: Session Recovery ===== -->
    <section anchor="recovery" numbered="true" toc="default">
      <name>Session Recovery</name>
      <t>
        The server <bcp14>MUST NOT</bcp14> accept a claimed Session_ID
        without completing the challenge-response. Old traffic keys
        <bcp14>MUST NOT</bcp14> be reused after a recovery event.
      </t>
      <figure anchor="fig-recovery">
        <name>Session Recovery Message Flow</name>
        <artwork align="left"><![CDATA[
   CLIENT                              SERVER
     |                                    |
     |--- RECOVERY_INIT ----------------->|
     |    (Session_ID_Hint, Device_ID,    |
     |     Client_Nonce_R)                |
     |                                    |
     |<-- Recovery_Challenge -------------|
     |                                    |
     |--- RECOVERY_ACK ------------------>|
     |    (Challenge_Response_R,          |
     |     Client_DH_Public_Key_R)        |
     |                                    |
     |<-- Server_DH_Public_Key_R ---------|
     |                                    |
     |  Recovery_Secret derived           |
     |  New Epoch(N), Sequence = 0        |
        ]]></artwork>
      </figure>
    </section>

    <!-- ===== Section 12: Synchronization ===== -->
    <section anchor="synchronization" numbered="true" toc="default">
      <name>Sender-Receiver Synchronization</name>
      <t>
        Both endpoints derive the same state without transmitting any
        secret. Because state is derived from the sequence number (not from
        the previous packet's decryption result), the receiver CAN
        reconstruct the expected state for any received sequence number
        within the current epoch, supporting out-of-order delivery:
      </t>
      <artwork align="left"><![CDATA[
   State(N) = F(Epoch_Key, N, Direction)
      ]]></artwork>
      <t>
        When the receiver detects irrecoverable state divergence, it
        <bcp14>MUST</bcp14> initiate session recovery or terminate the
        session.
      </t>
    </section>

    <!-- ===== Section 13: MP3 Example ===== -->
    <section anchor="mp3-example" numbered="true" toc="default">
      <name>Full-Duplex MP3 Media Transfer Example</name>

      <section anchor="scenario" numbered="true" toc="default">
        <name>Scenario Description</name>
        <dl newline="false" spacing="normal">
          <dt>Client:</dt>
          <dd>Device_ID = "DEV-AUDIO-CLIENT-42", IP = 203.0.113.10,
              Port = 51234</dd>
          <dt>Server:</dt>
          <dd>Device_ID = "SRV-MEDIA-PROCESSOR-07", IP = 198.51.100.20,
              Port = 8443</dd>
          <dt>Transport:</dt>
          <dd>TCP (Protocol = 6)</dd>
        </dl>
        <t>
          The Client-to-Server direction transfers the MP3 file in
          segments. The Server-to-Client direction sends per-segment
          acknowledgements and real-time processing status. Both channels
          are active simultaneously (full-duplex operation).
        </t>
      </section>

      <section anchor="mp3-params" numbered="true" toc="default">
        <name>MP3 File Parameters</name>
        <artwork align="left"><![CDATA[
   File:            podcast_episode_42.mp3
   Size:            7,340,032 bytes  (7 MB exactly)
   SHA-256 Hash:    A3F182B0C44179D35E6F2A9104BC8D7E
                    F2034A5687CD19E023B456A789F01C2D
                    4E7890ABCD1234EF567890BC12DE9C7D
   Bit Rate:        128 kbps
   Duration:        ~7 min 41 sec
   Sample Rate:     44100 Hz
   Channels:        Stereo (2)
   MPEG Version:    MPEG-1 Layer III
   ID3 Tag Length:  10,240 bytes (prepended)

   Segment Size:    8,192 bytes
   Total Segments:  896   (= 7,340,032 / 8,192)
        ]]></artwork>
      </section>

      <section anchor="handshake-ex" numbered="true" toc="default">
        <name>Handshake Phase</name>
        <t>
          The following message sequence uses illustrative
          (non-real) cryptographic values. All multi-octet fields are
          in network byte order (big-endian).
        </t>

        <section anchor="hs-msg1" numbered="true" toc="default">
          <name>Message 1: CLIENT_HELLO (T+0.000s)</name>
          <artwork align="left"><![CDATA[
   Header:
     Version       = 0x01
     Packet_Type   = 0x01  (CLIENT_HELLO)
     Flags         = 0x01  (FULL_DUPLEX)
     Session_ID    = 0x00..00  (zero, pre-session)
     Epoch         = 0x00000000
     Sequence      = 0x0000000000000000
     Key_ID        = 0x0000000000000000

   Payload (cleartext TLV):
     ProtocolVersion    = 0x0001
     SupportedSuites    = [
         SGCP_X25519_AESGCM256_SHA256,
         SGCP_X25519_MLKEM768_AESGCM256_SHA256
     ]
     Device_ID          = "DEV-AUDIO-CLIENT-42"
     Certificate        = <DER-encoded X.509>
     Client_Nonce       = 0x8A3F...1B2C  (32 bytes)
     Client_DH_Pub      = 0x5C2D...7F4A  (32 bytes, X25519)
     Client_KEM_Pub     = 0x3A1B...E9D2  (1184 bytes, ML-KEM-768)
          ]]></artwork>
        </section>

        <section anchor="hs-msg2" numbered="true" toc="default">
          <name>Message 2: SERVER_HELLO (T+0.018s)</name>
          <artwork align="left"><![CDATA[
   Payload (cleartext TLV):
     SelectedSuite      = SGCP_X25519_MLKEM768_AESGCM256_SHA256
     Server_Certificate = <DER-encoded X.509>
     Server_Nonce       = 0x2F7C...4E8D  (32 bytes)
     Server_DH_Pub      = 0xA1B2...CD3E  (32 bytes, X25519)
     Server_KEM_CT      = 0xB2C3...EF40  (1088 bytes, ML-KEM-768 CT)
     Server_Challenge   = 0xD4E5...1F60  (32 bytes)
     Signature          = 0x3045...8A21  (ECDSA-P256)

   Client computes:
     DH_Secret  = X25519(Client_DH_Priv, Server_DH_Pub)
                = 0x9F2A...7C3B

     KEM_Secret = ML-KEM-768.Decapsulate(Client_KEM_Priv,
                                          Server_KEM_CT)
                = 0xE1D2...4C5B

     Root_Secret = HKDF-Extract("SGCP_ROOT_PQ_v1",
                     DH_Secret || KEM_Secret
                     || Client_Nonce || Server_Nonce
                     || H(Client_Cert) || H(Server_Cert))
                 = 0x7B4A...F9CE
          ]]></artwork>
        </section>

        <section anchor="hs-msg3" numbered="true" toc="default">
          <name>Message 3: CLIENT_FINISH (T+0.020s)</name>
          <artwork align="left"><![CDATA[
   Session_ID =
       H("SGCP_SID" || Root_Secret || Client_Nonce || Server_Nonce)
       = 0xC3D4...A5B6  (16 bytes)

   Payload (Handshake_Key-AEAD encrypted):
     Challenge_Response =
         ECDSA-P256-Sign(Client_Private_Key,
             H("SGCP_CHALLENGE" || Server_Challenge
               || Client_Nonce))
         = 0x3046...9B72

     ClientFinish_MAC =
         HMAC-SHA256(Handshake_Key,
             H("SGCP_CFIN" || ClientHello || ServerHello))
         = 0xA2B3...7C8D

   Context_Binding =
       H("SGCP_CTX_BIND_v1"
         || 0x0001                   (Version)
         || "DEV-AUDIO-CLIENT-42"
         || 0x06                     (TCP)
         || 0xC822                   (Port 51234)
         || 0x20FB                   (Port 8443)
         || Socket_ID
         || Session_ID)
       = 0xF1A2...B3C4

   Epoch_0_Key =
       HKDF-Expand(Root_Secret,
           "SGCP_EPOCH" || 0x00000000 || Context_Binding,
           32)
       = 0x4D5E...6F70

   Handshake complete at T+0.022s.
   Both sides: Epoch = 0, Sequence = 0, State = ACTIVE.
          ]]></artwork>
        </section>
      </section>

      <section anchor="mp3-transfer" numbered="true" toc="default">
        <name>MP3 Segment Transfer - Client to Server</name>

        <section anchor="seg0" numbered="true" toc="default">
          <name>Segment 0 (Sequence 0, C->S, T+0.025s)</name>
          <artwork align="left"><![CDATA[
   Plaintext media header + data:
     Media_Type       = 0x01  (AUDIO)
     Codec            = 0x01  (MP3)
     Segment_Index    = 0x00000000
     Total_Segments   = 0x00000380  (896)
     Byte_Offset      = 0x0000000000000000
     Segment_Byte_Len = 0x00002000  (8192)
     File_Hash        = A3F182B0...9C7D  (32 bytes)
     Segment_Data     = [bytes 0..8191 of podcast_episode_42.mp3]

   Packet_Key_0 =
       HKDF-Expand(Epoch_0_Key,
           "SGCP_PACKET" || 0x01 || 0x0000000000000000,
           32)
       = 0x1A2B...3C4D

   Nonce_0 = Epoch(0) || Seq(0) || Dir(0x01)

   AAD_0 = Session_ID || 0x00000000 || 0x0000000000000000
           || 0x01 || Context_Binding || Key_ID_0

   (Ciphertext_0, Tag_0) =
       AES-256-GCM-Encrypt(Packet_Key_0, Nonce_0,
                           Plaintext_0, AAD_0)

   Transform_State_0 =
       HKDF-Expand(Epoch_0_Key,
           "SGCP_TRANSFORM" || 0x0000000000000000 || 0x01,
           8208)  // 8192 + 16 (AEAD tag)

   Wire_Payload_0 =
       XOR(Ciphertext_0 || Tag_0, Transform_State_0)

   Wire Header (illustrative hex):
     01 10 01 00           ; Ver=1 Type=MEDIA_SEGMENT Flags=FD
     C3D4A5B6C7D8E9F0      ; Session_ID [0..7]
     A1B2C3D4E5F6A7B8      ; Session_ID [8..15]
     00000000              ; Epoch = 0
     0000000000000000      ; Sequence = 0
     01                    ; Direction = C->S
     00                    ; Reserved
     [Key_ID_0: 8 bytes]
     00002010              ; Payload Length = 8208
     [CRC-16]
     [Wire_Payload_0: 8208 bytes]

   State after Seg 0:  Sequence_C2S = 1
          ]]></artwork>
        </section>

        <section anchor="segs1to3" numbered="true" toc="default">
          <name>Segments 1-3 (Sequences 1-3)</name>
          <artwork align="left"><![CDATA[
   Seg 1 (T+0.030s):  Byte_Offset = 8192   Packet_Key differs
   Seg 2 (T+0.035s):  Byte_Offset = 16384  Packet_Key differs
   Seg 3 (T+0.040s):  Byte_Offset = 24576  Packet_Key differs

   State Graph (C->S) after 4 segments:
   N0 --[Pkt0]--> N1 --[Pkt1]--> N2 --[Pkt2]--> N3 --[Pkt3]--> N4
          ]]></artwork>
        </section>
      </section>

      <section anchor="full-duplex-ex" numbered="true" toc="default">
        <name>Full-Duplex Operation - Simultaneous Exchange</name>
        <figure anchor="fig-duplex-timeline">
          <name>Full-Duplex Timeline (T+0.025s to T+0.060s)</name>
          <artwork align="left"><![CDATA[
   Time     Client->Server              Server->Client
   -------  --------------------------  ---------------------------
   T+0.025  MEDIA_SEGMENT Seq=0 (8KB)
   T+0.030  MEDIA_SEGMENT Seq=1 (8KB)
   T+0.033                              MEDIA_ACK Seq=0
   T+0.035  MEDIA_SEGMENT Seq=2 (8KB)
   T+0.038                              MEDIA_ACK Seq=1
   T+0.040  MEDIA_SEGMENT Seq=3 (8KB)
   T+0.043                              MEDIA_ACK Seq=2
   T+0.045  MEDIA_SEGMENT Seq=4 (8KB)
   T+0.048                              MEDIA_ACK Seq=3
   T+0.050  MEDIA_SEGMENT Seq=5 (8KB)
   T+0.055                              STATUS    Seq=4 (decode OK)
   ...
   T+0.880  MEDIA_SEGMENT Seq=895(8KB)  (final segment)
   T+0.883                              MEDIA_ACK Seq=895
   T+0.885                              STATUS (complete, PASS)
          ]]></artwork>
        </figure>
        <t>
          The S->C Packet Key is derived independently from the C->S key:
        </t>
        <artwork align="left"><![CDATA[
   Packet_Key_S2C_0 =
       HKDF-Expand(Epoch_0_Key,
           "SGCP_PACKET" || 0x02 || 0x0000000000000000,
           32)
       = 0x7E8F...9A0B  (entirely different from any C->S key)
        ]]></artwork>
      </section>

      <section anchor="epoch-transition-ex" numbered="true" toc="default">
        <name>Epoch Transition During Transfer</name>
        <t>
          After 512 segments (Sequence = 512 on C->S), the client
          initiates proactive key rotation at T+0.453s.
        </t>
        <artwork align="left"><![CDATA[
   KEY_ROTATION packet (C->S, Seq=512, Epoch=0):
     Packet_Type = 0x06  (KEY_ROTATION)
     Flags       = 0x09  (FULL_DUPLEX | KEY_ROTATION_PENDING)
     Payload (encrypted):
       New_Epoch = 1
       Reason    = PROACTIVE_ROTATION
       MAC       = HMAC-SHA256(Epoch_0_Key,
                               "SGCP_KEYROT" || Session_ID || 1)

   Server verifies, sends KEY_ROTATION_ACK (S->C, Seq=256, Epoch=0).

   Both sides derive Epoch 1:
     Epoch_1_Key =
         HKDF-Expand(Root_Secret,
             "SGCP_EPOCH" || 0x00000001 || Context_Binding,
             32)
         = 0x5F6A...7B8C

   Epoch_0_Key erased from memory.
   C->S: Sequence reset to 0, Epoch = 1
   S->C: Sequence reset to 0, Epoch = 1

   State Graph at boundary:

   Epoch 0 (C->S): N0 -> N1 -> ... -> N512
                                         |
                                         | KEY_ROTATION (E512)
                                         v
   Epoch 1 (C->S): N0' -> N1' -> ...  (Seg 512 onwards)

   First packet in Epoch 1 (T+0.457s):
     Epoch  = 0x00000001
     Seq    = 0x0000000000000000
     Flags  = 0x03  (FULL_DUPLEX | EPOCH_BOUNDARY)
     Packet_Key_E1_C2S_0 =
         HKDF-Expand(Epoch_1_Key,
             "SGCP_PACKET" || 0x01 || 0x0000000000000000,
             32)
         = 0x2C3D...4E5F
        ]]></artwork>
      </section>

      <section anchor="transfer-summary" numbered="true" toc="default">
        <name>Transfer Completion and Session Summary</name>
        <t>
          Server reassembles all 896 segments and verifies integrity:
        </t>
        <artwork align="left"><![CDATA[
   Received_File_Hash = SHA-256(reassembled 7,340,032 bytes)
   Verify: Received_File_Hash == A3F1...9C7D   -> PASS

   Transfer Summary:
     C->S Packets:  896 MEDIA_SEGMENT + 1 KEY_ROTATION
                    + 1 SESSION_CLOSE = 898 packets
     S->C Packets:  896 MEDIA_ACK + ~179 STATUS
                    + 1 KEY_ROTATION_ACK = ~1077 packets
     Epochs used:   2 (Epoch 0: segs 0-511; Epoch 1: segs 512-895)
     Total data:    7,340,032 bytes
     Integrity:     PASS (end-to-end SHA-256 match)
     Key uniqueness: Every packet used a unique derived key.
        ]]></artwork>
      </section>
    </section>

    <!-- ===== Section 14: Complete State Model ===== -->
    <section anchor="state-model" numbered="true" toc="default">
      <name>Complete State Model</name>
      <artwork align="left"><![CDATA[
   STATE = {
       Session_ID,         // 128-bit session identifier
       Epoch,              // 32-bit epoch counter
       Sequence,           // 64-bit per-direction sequence counter
       Direction,          // C->S or S->C
       Node_ID,            // current graph node identifier
       Key_ID,             // current non-secret key identifier
       Context_Binding,    // 256-bit context hash
       Device_State,       // device trust/posture
       Port_State,         // port binding
       Socket_State,       // socket binding
       Trust_State,        // session trust level
       Replay_State,       // (Window_High, Window_Bits[W])
       Policy_Version,     // applicable policy revision
       State_Version,      // monotonic state-version counter
       Chain_Hash          // hash-chain pointer to current node
   }
      ]]></artwork>
      <t>
        Secret keys are NOT stored in the state record; they are derived
        from the Root Secret on demand from a separate protected memory
        region.
      </t>
    </section>

    <!-- ===== Section 15: Security Considerations ===== -->
    <section anchor="security" numbered="true" toc="default">
      <name>Security Considerations</name>

      <section anchor="attack-surface" numbered="true" toc="default">
        <name>Attack Surface Analysis</name>
        <table anchor="tbl-security" align="center">
          <name>SGCP Security Properties vs. Threats</name>
          <thead>
            <tr>
              <th>Property</th>
              <th>Threat Mitigated</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>Mutual authentication</td>
              <td>Impersonation, MITM</td>
            </tr>
            <tr>
              <td>ECDH key establishment</td>
              <td>Passive eavesdropping</td>
            </tr>
            <tr>
              <td>Per-packet unique keys</td>
              <td>Key compromise propagation</td>
            </tr>
            <tr>
              <td>Context binding</td>
              <td>Session transplantation</td>
            </tr>
            <tr>
              <td>Authenticated state edges</td>
              <td>Fake state injection</td>
            </tr>
            <tr>
              <td>Replay window</td>
              <td>Replay attacks</td>
            </tr>
            <tr>
              <td>Epoch rotation</td>
              <td>Long-term key exposure</td>
            </tr>
            <tr>
              <td>Session recovery auth</td>
              <td>Session token replay</td>
            </tr>
            <tr>
              <td>Hash chain</td>
              <td>State history tampering</td>
            </tr>
            <tr>
              <td>Deterministic state rule</td>
              <td>Oracle attacks on transformation</td>
            </tr>
            <tr>
              <td>ML-KEM hybridization</td>
              <td>Quantum-computer attacks</td>
            </tr>
          </tbody>
        </table>
      </section>

      <section anchor="replay-sec" numbered="true" toc="default">
        <name>Replay Attacks</name>
        <t>
          The replay window rejects packets with a sequence number that has
          already been accepted within the current epoch. The AEAD
          construction ensures that a replayed packet cannot be modified to
          appear as a new packet (the AAD includes the sequence number and
          epoch). An epoch boundary resets the sequence space; old-epoch
          packets <bcp14>MUST NOT</bcp14> be accepted in a new epoch.
        </t>
      </section>

      <section anchor="divergence-sec" numbered="true" toc="default">
        <name>State Divergence</name>
        <t>
          Implementations <bcp14>MUST NOT</bcp14> attempt to brute-force
          candidate transform states or packet keys. When the receiver
          detects irrecoverable state divergence, it <bcp14>MUST</bcp14>
          initiate session recovery or terminate the session.
        </t>
      </section>

      <section anchor="det-state-rule" numbered="true" toc="default">
        <name>Deterministic State Security Rule</name>
        <t>
          The receiver <bcp14>MUST</bcp14> derive exactly ONE expected state
          for a received packet and test it. If the single test fails, the
          packet is discarded. The receiver <bcp14>MUST NOT</bcp14> iterate
          over multiple candidate states or transformations. Violating this
          rule creates an oracle that could allow an adversary to learn
          information about the key hierarchy.
        </t>
      </section>
    </section>

    <!-- ===== Section 16: IANA ===== -->
    <section anchor="iana" numbered="true" toc="default">
      <name>IANA Considerations</name>
      <t>
        This document requests the following IANA registrations. Values
        not listed in a registry are unassigned; new values
        <bcp14>MUST</bcp14> be registered via the Specification Required
        policy <xref target="RFC8126"/>.
      </t>

      <section anchor="iana-suites" numbered="true" toc="default">
        <name>SGCP Cipher Suites Registry</name>
        <table align="center">
          <name>SGCP Cipher Suites</name>
          <thead>
            <tr><th>Value</th><th>Name</th></tr>
          </thead>
          <tbody>
            <tr><td>0x0001</td>
                <td>SGCP_X25519_AESGCM256_SHA256</td></tr>
            <tr><td>0x0002</td>
                <td>SGCP_P256_AESGCM256_SHA256</td></tr>
            <tr><td>0x0003</td>
                <td>SGCP_X25519_MLKEM768_AESGCM256_SHA256</td></tr>
            <tr><td>0x0004</td>
                <td>SGCP_P256_MLKEM1024_AESGCM256_SHA384</td></tr>
          </tbody>
        </table>
      </section>

      <section anchor="iana-types" numbered="true" toc="default">
        <name>SGCP Packet Types Registry</name>
        <table align="center">
          <name>SGCP Packet Types</name>
          <thead>
            <tr><th>Value</th><th>Name</th></tr>
          </thead>
          <tbody>
            <tr><td>0x01</td><td>CLIENT_HELLO</td></tr>
            <tr><td>0x02</td><td>SERVER_HELLO</td></tr>
            <tr><td>0x03</td><td>CLIENT_FINISH</td></tr>
            <tr><td>0x04</td><td>DATA</td></tr>
            <tr><td>0x05</td><td>CONTEXT_CHANGE</td></tr>
            <tr><td>0x06</td><td>KEY_ROTATION</td></tr>
            <tr><td>0x07</td><td>REAUTH_REQUEST</td></tr>
            <tr><td>0x08</td><td>REAUTH_RESPONSE</td></tr>
            <tr><td>0x09</td><td>RECOVERY_INIT</td></tr>
            <tr><td>0x0A</td><td>RECOVERY_ACK</td></tr>
            <tr><td>0x0B</td><td>ALERT</td></tr>
            <tr><td>0x0C</td><td>SESSION_CLOSE</td></tr>
            <tr><td>0x10</td><td>MEDIA_SEGMENT</td></tr>
            <tr><td>0x11</td><td>MEDIA_ACK</td></tr>
          </tbody>
        </table>
      </section>

      <section anchor="iana-alerts" numbered="true" toc="default">
        <name>SGCP Alert Codes Registry</name>
        <table align="center">
          <name>SGCP Alert Codes</name>
          <thead>
            <tr><th>Value</th><th>Name</th></tr>
          </thead>
          <tbody>
            <tr><td>0x01</td><td>AUTH_FAILURE</td></tr>
            <tr><td>0x02</td><td>DECRYPTION_FAILURE</td></tr>
            <tr><td>0x03</td><td>REPLAY_DETECTED</td></tr>
            <tr><td>0x04</td><td>STATE_MISMATCH</td></tr>
            <tr><td>0x05</td><td>CONTEXT_VIOLATION</td></tr>
            <tr><td>0x06</td><td>POLICY_VIOLATION</td></tr>
            <tr><td>0x07</td><td>SESSION_EXPIRED</td></tr>
            <tr><td>0x08</td><td>REVOCATION</td></tr>
            <tr><td>0x09</td><td>INTERNAL_ERROR</td></tr>
            <tr><td>0xFF</td><td>CLOSE_NOTIFY</td></tr>
          </tbody>
        </table>
      </section>
    </section>

  </middle>

  <!-- ============================================================ -->
  <!--  BACK                                                          -->
  <!-- ============================================================ -->
  <back>

    <!-- ===== References ===== -->
    <references>
      <name>References</name>

      <references anchor="normative-refs">
        <name>Normative References</name>

        <reference anchor="RFC2119"
                   target="https://www.rfc-editor.org/rfc/rfc2119">
          <front>
            <title>Key words for use in RFCs to Indicate Requirement
                   Levels</title>
            <author initials="S." surname="Bradner" fullname="S. Bradner"/>
            <date month="March" year="1997"/>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="2119"/>
          <seriesInfo name="DOI" value="10.17487/RFC2119"/>
        </reference>

        <reference anchor="RFC8174"
                   target="https://www.rfc-editor.org/rfc/rfc8174">
          <front>
            <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key
                   Words</title>
            <author initials="B." surname="Leiba" fullname="B. Leiba"/>
            <date month="May" year="2017"/>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="8174"/>
          <seriesInfo name="DOI" value="10.17487/RFC8174"/>
        </reference>

        <reference anchor="RFC5869"
                   target="https://www.rfc-editor.org/rfc/rfc5869">
          <front>
            <title>HMAC-based Extract-and-Expand Key Derivation Function
                   (HKDF)</title>
            <author initials="H." surname="Krawczyk"
                    fullname="H. Krawczyk"/>
            <author initials="P." surname="Eronen" fullname="P. Eronen"/>
            <date month="May" year="2010"/>
          </front>
          <seriesInfo name="RFC" value="5869"/>
          <seriesInfo name="DOI" value="10.17487/RFC5869"/>
        </reference>

        <reference anchor="RFC7748"
                   target="https://www.rfc-editor.org/rfc/rfc7748">
          <front>
            <title>Elliptic Curves for Security</title>
            <author initials="A." surname="Langley"
                    fullname="A. Langley"/>
            <author initials="M." surname="Hamburg"
                    fullname="M. Hamburg"/>
            <author initials="S." surname="Turner" fullname="S. Turner"/>
            <date month="January" year="2016"/>
          </front>
          <seriesInfo name="RFC" value="7748"/>
          <seriesInfo name="DOI" value="10.17487/RFC7748"/>
        </reference>

        <reference anchor="RFC8032"
                   target="https://www.rfc-editor.org/rfc/rfc8032">
          <front>
            <title>Edwards-Curve Digital Signature Algorithm
                   (EdDSA)</title>
            <author initials="S." surname="Josefsson"
                    fullname="S. Josefsson"/>
            <author initials="I." surname="Liusvaara"
                    fullname="I. Liusvaara"/>
            <date month="January" year="2017"/>
          </front>
          <seriesInfo name="RFC" value="8032"/>
          <seriesInfo name="DOI" value="10.17487/RFC8032"/>
        </reference>

        <reference anchor="RFC8446"
                   target="https://www.rfc-editor.org/rfc/rfc8446">
          <front>
            <title>The Transport Layer Security (TLS) Protocol Version
                   1.3</title>
            <author initials="E." surname="Rescorla"
                    fullname="E. Rescorla"/>
            <date month="August" year="2018"/>
          </front>
          <seriesInfo name="RFC" value="8446"/>
          <seriesInfo name="DOI" value="10.17487/RFC8446"/>
        </reference>

        <reference anchor="RFC8126"
                   target="https://www.rfc-editor.org/rfc/rfc8126">
          <front>
            <title>Guidelines for Writing an IANA Considerations Section
                   in RFCs</title>
            <author initials="M." surname="Cotton" fullname="M. Cotton"/>
            <author initials="B." surname="Leiba" fullname="B. Leiba"/>
            <author initials="T." surname="Narten" fullname="T. Narten"/>
            <date month="June" year="2017"/>
          </front>
          <seriesInfo name="BCP" value="26"/>
          <seriesInfo name="RFC" value="8126"/>
          <seriesInfo name="DOI" value="10.17487/RFC8126"/>
        </reference>

        <reference anchor="FIPS203"
                   target="https://doi.org/10.6028/NIST.FIPS.203">
          <front>
            <title>Module-Lattice-Based Key-Encapsulation Mechanism
                   Standard</title>
            <author>
              <organization>National Institute of Standards and
                            Technology</organization>
            </author>
            <date month="August" year="2024"/>
          </front>
          <seriesInfo name="NIST FIPS" value="203"/>
          <seriesInfo name="DOI" value="10.6028/NIST.FIPS.203"/>
        </reference>

        <reference anchor="RFC5280"
                   target="https://www.rfc-editor.org/rfc/rfc5280">
          <front>
            <title>Internet X.509 Public Key Infrastructure Certificate
                   and Certificate Revocation List (CRL) Profile</title>
            <author initials="D." surname="Cooper" fullname="D. Cooper"/>
            <author initials="S." surname="Santesson"
                    fullname="S. Santesson"/>
            <author initials="S." surname="Farrell" fullname="S. Farrell"/>
            <author initials="S." surname="Boeyen" fullname="S. Boeyen"/>
            <author initials="R." surname="Housley" fullname="R. Housley"/>
            <author initials="W." surname="Polk" fullname="W. Polk"/>
            <date month="May" year="2008"/>
          </front>
          <seriesInfo name="RFC" value="5280"/>
          <seriesInfo name="DOI" value="10.17487/RFC5280"/>
        </reference>

        <reference anchor="FIPS197"
                   target="https://doi.org/10.6028/NIST.FIPS.197">
          <front>
            <title>Advanced Encryption Standard (AES)</title>
            <author>
              <organization>National Institute of Standards and
                            Technology</organization>
            </author>
            <date month="November" year="2001"/>
          </front>
          <seriesInfo name="NIST FIPS" value="197"/>
          <seriesInfo name="DOI" value="10.6028/NIST.FIPS.197"/>
        </reference>
      </references>

      <references anchor="informative-refs">
        <name>Informative References</name>

        <reference anchor="RFC9147"
                   target="https://www.rfc-editor.org/rfc/rfc9147">
          <front>
            <title>The Datagram Transport Layer Security (DTLS) Protocol
                   Version 1.3</title>
            <author initials="E." surname="Rescorla"
                    fullname="E. Rescorla"/>
            <author initials="H." surname="Tschofenig"
                    fullname="H. Tschofenig"/>
            <author initials="N." surname="Modadugu"
                    fullname="N. Modadugu"/>
            <date month="April" year="2022"/>
          </front>
          <seriesInfo name="RFC" value="9147"/>
          <seriesInfo name="DOI" value="10.17487/RFC9147"/>
        </reference>

        <reference anchor="RFC5905"
                   target="https://www.rfc-editor.org/rfc/rfc5905">
          <front>
            <title>Network Time Protocol Version 4: Protocol and
                   Algorithms Specification</title>
            <author initials="D." surname="Mills" fullname="D. Mills"/>
            <author initials="J." surname="Martin" fullname="J. Martin"/>
            <author initials="J." surname="Burbank"
                    fullname="J. Burbank"/>
            <author initials="W." surname="Kasch" fullname="W. Kasch"/>
            <date month="June" year="2010"/>
          </front>
          <seriesInfo name="RFC" value="5905"/>
          <seriesInfo name="DOI" value="10.17487/RFC5905"/>
        </reference>
      </references>
    </references>

    <!-- ===== Appendix A ===== -->
    <section anchor="appendix-a" numbered="true" toc="default">
      <name>Graph Interaction Diagrams</name>

      <section anchor="app-a1" numbered="true" toc="default">
        <name>Normal Full-Duplex Operation</name>
        <artwork align="left"><![CDATA[
   CLIENT (C->S)                        SERVER
   ====================================  ============================
   Epoch=0, Seq=0, Node=N0_C2S           Epoch=0, Seq=0, Node=N0_C2S
   |                                     |
   |--- MEDIA_SEGMENT(Seq=0) ----------->|
   |                                     | verify -> N1_C2S
   |                                     |--- MEDIA_ACK(S2C,Seq=0) ->|
   |--- MEDIA_SEGMENT(Seq=1) ----------->|
   |  -> N2_C2S                          | verify -> N2_C2S
   ...
        ]]></artwork>
      </section>

      <section anchor="app-a2" numbered="true" toc="default">
        <name>Epoch Boundary</name>
        <artwork align="left"><![CDATA[
   Epoch=0, Seq=512, Node=N512_C2S
   |
   |--- KEY_ROTATION(Seq=512) ---------->|
   |                                     |--- KEY_ROTATION_ACK ------>|
   Epoch=1, Seq=0, Node=N0'_C2S
   (Epoch_0_Key erased)
   |--- MEDIA_SEGMENT(Epoch=1,Seq=0) --->|
        ]]></artwork>
      </section>

      <section anchor="app-a3" numbered="true" toc="default">
        <name>Session Recovery</name>
        <artwork align="left"><![CDATA[
   CONNECTION LOST
   |
   |--- RECOVERY_INIT ------------------>|
   |<-- Recovery_Challenge --------------|
   |--- RECOVERY_ACK ------------------->|
   |<-- Server_DH_Public_Key_R ----------|
   |
   Epoch=N+1, Seq=0  (fresh keys)
   |--- MEDIA_SEGMENT(Epoch=N+1) ------->|
        ]]></artwork>
      </section>
    </section>

    <!-- ===== Appendix B ===== -->
    <section anchor="appendix-b" numbered="true" toc="default">
      <name>Test Vectors (Illustrative)</name>
      <t>
        The following values are illustrative only and do not constitute
        real cryptographic test vectors. Implementors
        <bcp14>MUST</bcp14> generate test vectors using real
        implementations of the specified primitives.
      </t>
      <artwork align="left"><![CDATA[
   Session parameters:
     Device_ID     = "DEV-TEST-01"
     Client_Nonce  = 32 bytes of 0xAA
     Server_Nonce  = 32 bytes of 0xBB
     DH_Secret     = 32 bytes of 0xCC  (hypothetical)
     KEM_Secret    = 32 bytes of 0xDD  (hypothetical)

   Root_Secret (illustrative):
     HKDF-Extract("SGCP_ROOT_PQ_v1",
                   0xCC...CC || 0xDD...DD
                   || 0xAA...AA || 0xBB...BB
                   || H("DEV-TEST-01-CERT")
                   || H("SRV-TEST-01-CERT"))
     = <32 bytes>

   Session_ID (illustrative):
     HKDF-Expand(Root_Secret, "SGCP_SID" || ..., 16)
     = <16 bytes>

   Real test vectors will be provided in a future revision of this
   document following independent implementation and verification.
      ]]></artwork>
    </section>
    <!-- ===== Section 17: Reference Implementation ===== -->
    <section anchor="sec-reference-impl" numbered="true" toc="default">
      <name>Reference Implementation</name>
      <t>
        A reference implementation of SGCP is available as an open-source
        Python package on the Python Package Index (PyPI) under the package
        name <tt>sgcp</tt>.
      </t>
      <t>
        PyPI: <eref target="https://pypi.org/project/sgcp/"/>
      </t>
      <t>
        Installation:
      </t>
      <artwork align="left"><![CDATA[
   pip install sgcp
      ]]></artwork>
      <t>
        The reference implementation covers all normative sections of this
        document, including:
      </t>
      <ul>
        <li>Section 4 (X.509 Certificate Integration)</li>
        <li>Section 5 (All 12 Phases)</li>
        <li>Section 6 (Wire Format — header, handshake, data, media packets)</li>
        <li>Section 7 (State Graph — nodes, edges, hash chain)</li>
        <li>Section 8 (Key Derivation — Root Secret, Epoch Key, Packet Key)</li>
        <li>Section 9 (State-Dependent Transformation)</li>
        <li>Section 10 (Epoch Management and key erasure)</li>
        <li>Section 11 (State Transition Engine)</li>
        <li>Section 12 (Session Recovery)</li>
        <li>Section 13 (Sender-Receiver Synchronization)</li>
        <li>Section 14 (Full-Duplex MP3 Media Transfer)</li>
        <li>Section 15 (State Persistence)</li>
        <li>Section 16 (Security Requirements)</li>
      </ul>
      <t>
        The implementation provides two high-level endpoint classes:
        <tt>SGCPClient</tt> and <tt>SGCPServer</tt>, both exposing a
        unified <tt>receive()</tt> method that automatically dispatches on
        packet type (DATA 0x04 vs MEDIA_SEGMENT 0x10), returning an
        <tt>SGCPMessage</tt> envelope containing the decrypted payload.
      </t>
      <t>
        Source repository:
        <eref target="https://github.com/sgcp-wg/sgcp-protocol"/>
      </t>
      <t>
        IETF Datatracker:
        <eref target="https://datatracker.ietf.org/doc/draft-sgcp-state-graph-cryptographic-protocol/"/>
      </t>
    </section>

  </back>
</rfc>
