One document matched: draft-snell-httpbis-keynego-02.xml


<?xml version="1.0"?> 
<!DOCTYPE rfc SYSTEM "rfc2629.dtd" [ 
  <!ENTITY rfc2119 PUBLIC '' 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.2119.xml'>
  <!ENTITY rfc6454 PUBLIC '' 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.6454.xml'>
]>
<?rfc toc="yes"?> 
<?rfc strict="yes"?> 
<?rfc symrefs="yes" ?> 
<?rfc sortrefs="yes"?> 
<?rfc compact="yes"?> 
<rfc category="info" ipr="trust200811" docName="draft-snell-httpbis-keynego-02"> 
  <front> 
    <title abbrev="HTTP/2.0 Intra-Connection Negotiation"> 
      HTTP/2.0 Intra-Connection Negotiation
    </title> 
 
    <author initials="J.M." surname="Snell" fullname="James M Snell"> 
      <address> 
        <email>jasnell@gmail.com</email> 
      </address> 
    </author> 
    
    <date month="November" year="2013" /> 
 
    <keyword>I-D</keyword> 
    <keyword>http</keyword>
    <keyword>spdy</keyword>
 
    <abstract> 
      <t>
        This memo describes a proposed modification to HTTP/2.0 that 
        introduces the concepts of Intra-Connection Negotiation 
        and Secure Framing.</t> 
    </abstract> 
 
  </front> 
  
  <middle> 

    <section title="Introduction">
      <t>
        HTTP/2.0 Intra-Connection Negotiation allows peers to
        dynamically negotiate agreements (e.g. for cryptographic keys) with 
        an origin (as defined by <xref target="RFC6454" />) from within an 
        established HTTP/2.0 connection.
      </t>

      <t>
        This mechanism would provide a number of important benefits, 
        including:
        <list style="numbers">
          <t>
            The ability to negotiate multiple agreements for one or more 
            origins within a single HTTP/2.0 connection;
          </t>
          <t>
            The ability to revoke and renegotiate agreements on the fly 
            without tearing down and reestablishing the HTTP/2.0 
            connection;
          </t>
          <t>
            Support for multiple negotiation mechanisms, 
            including pre-shared key, etc;
          </t>
        </list>
      </t>
      
    </section>
    
    <section title="Agreement Negotiation">
      
      <t>
        Intra-Connection Negotiation is facilitated through the 
        use of a new "NEGOTIATE" HTTP pseudo-method. The HTTP header 
        field mapping for the NEGOTIATE method works similarly to 
        that of CONNECT methods, with a few notable exceptions:   
        <list style="symbols">
          <t>The ":method" header field is set to "NEGOTIATE".</t>
          <t>The ":scheme" and ":path" header fields MUST be omitted.</t>
          <t>
            The ":authority" header field contains the host and port 
            of the origin for which an agreement is being negotiated.
          </t>
          <t>
            An ":id" header field MUST be given specifying the 
            31-bit numeric identifier of the agreement being negotiated.
          </t>
          <t>
            An ":algorithm" header field MUST be given specifying the
            IRI identifier of the negotiation / agreement algorithm
            being utilized. 
          </t>
        </list>   
      </t>
      
      <t>
        A complete negotiation consumes a single stream within a connection
        and may consist of one or more distinct "messages" exchanged within 
        that stream. The number of messages required for a negotiation depends
        on the specific algorithm being used. On HEADERS and DATA frames, the 
        currently reserved 0x2 flag is used to signal the end of individual 
        messages. The negotiation is considered complete when the stream is
        closed. A negotiated agreement cannot be used until the negotiation for 
        is completed.
      </t>

      <section title="Example: Pre-Shared Key">
        
        <t>
          To illustrate the basic flow of the negotiation protocol, 
          consider the simple case where both peers share a common
          pre-shared secret. To simplify the example, we assume that
          there is need to prove possession of the shared secret.
        </t>
        
        <t>
          The initiating peer would send:
        </t>
        
<figure><artwork>
  HEADERS
    END_STREAM  (0x1)
    END_MESSAGE (0x2)
    END_HEADERS (0x4)
    :method = NEGOTIATE
    :authority = example.org
    :id = 1
    :algorithm = urn:example:algorithm:psk
    name = Our Shared Key Name
</artwork></figure>

        <t>
          The flags END_STREAM and END_MESSAGE indicate to the receiving 
          peer that no additional messages will be sent for this negotiation.
          Assuming the negotiation is accepted, a simplified response would be:
        </t>
        
<figure><artwork>
  HEADERS
    END_STREAM  (0x1)
    END_MESSAGE (0x2)
    END_HEADERS (0x4)
    :status = 200
</artwork></figure>
        
      </section>
            
      <section title="Example: Multi-step Negotiation">
        
        <t>
          Some negotiation algorithms require multiple steps.
          This is accomplished by exchanging multiple messages within
          a single stream.
        </t>
        
        <t>
          A "message" consists of a combination of a HEADERS frame
          followed by zero or more DATA frames. The last frame in the 
          message MUST have the END_MESSAGE flag set.
        </t>
        
<figure><preamble>Initializing a multi-step negotiation (note that the END_STREAM flag is not set)</preamble><artwork>
  HEADERS
    END_MESSAGE (0x2)
    END_HEADERS (0x4)
    :method = NEGOTIATE
    :authority = example.org
    :id = 1
    :algorithm = urn:example:algorithm:multistep
    init-param-1 = foo
</artwork></figure>

<figure><preamble>The initializing reponse (again, note that the END_STREAM flag is not set)</preamble><artwork>
  HEADERS
    END_MESSAGE (0x2)
    END_HEADERS (0x4)
    :status = 200
    init-param-A = bar
</artwork></figure>

        <t>
          Once the initial HEADERS frames are sent, the peers are free to 
          exchange as many messages on the stream as necessary to complete
          the negotiation process. When a peer is done with it's part of 
          the negotiation, it will include the END_STREAM flag on the last
          frame it sends. If the negotiation process fails after the initial
          HEADERS frames are sent, an RST_STREAM frame is used to terminate
          the negotiation process.
        </t>
        
      </section>
            
    </section>
    
    <section title="Secure Framing (Option 1)">
      
      <t>
        Obviously, negotiating an agreement is pointless if it cannot
        be subsequently used. To that end, I propose a modification to the 
        existing DATA frame definition.
      </t>
      
      <t>
        Specifically, I propose the introduction of a new AGREEMENT
        flag (0x4). When set, the flag indicates that the first 
        four bytes of the DATA frame payload specify a numeric 
        agreement identifier, and that the remaining DATA frame payload
        has been constructed in accordance with the referenced agreement.
        They specific structure of that data depends entirely on
        the properties of the agreement identified.
      </t>
      
<figure><artwork>
  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
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |X|                    Agreement ID (31)                        |
  +-+-------------------------------------------------------------+
  |                    Protected Payload Data                   ...
  +---------------------------------------------------------------+
</artwork></figure>

    </section>

    <section title="Secure Framing (Option 2)">
      
      <t>
        A potential alternative (and likely better) option for use
        of a negotiated agreement is to move agreement identification
        out of the DATA frame and into a request header field. For 
        instance:
      </t>
      
<figure><artwork>
  HEADERS
    :method = POST
    :authority = example.org
    :agreement = 1
</artwork></figure>
      
      <t>
        The presence of the ":agreement" header field in the initial HEADERS
        block indicates that all frames transmitted on the stream (in the same 
        direction) are constructed in accordance to the specified agreement.
      </t>
      
    </section>
    
    <section title="Renegotiation of Agreements">
      
      <t>
        Depending on the nature of the agreement, it might be possible
        for the requesting peer to renegotiate an agreement with the 
        origin. Significant care should be taken here, however, to 
        prevent the possibility of downgrade attacks.
      </t>
      
      <t>
        Renegotiation occurs by initiating a new NEGOTIATE request
        specifying an already established agreement identifier. This
        new interaction could establish new properties, expectations, 
        etc for the agreement. The renegotiation is not complete
        until after both peers successfully close the stream, meaning any
        new negotiated properties do not become effective until after 
        renegotiation is complete.
      </t>
      
    </section>
    
    <section title="Explicit Termination of Agreements">
      
      <t>
        It is possible that a mechanism for explicitly revoking or 
        terminating an agreement will be needed in some scenarios.
        Termination of an agreement is essentially a form of 
        renegotiation and would happen following a similar approach.
        One possible method for terminating an agreement would be 
        to send something like the following:
      </t>
      
<figure><artwork>
  HEADERS
    :method = NEGOTIATE
    :id = 1
    :algorithm: urn:example:algorithm:revoke-agreement
</artwork></figure>

      <t>
        A downside of this, however, termination would require
        action on the part of the requesting peer and could 
        not be initiated by the origin unless we allow the 
        origin to PUSH_PROMISE NEGOTIATE methods (which has it's
        own distinct problems since a client cannot send on a 
        pushed stream).
      </t>

    </section>
    
    <section title="The INTEGRITY frame type">
      
      <t>
        The INTEGRITY frame (type=0xB) allows a sending peer to insert
        periodic message authentication codes (MACs) into a stream to
        provide integrity and authenticity of a streams content.
      </t>
      
      <figure><artwork>
  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
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |                           MAC (*)                           ...
  +---------------------------------------------------------------+
      </artwork></figure>
      
      <t>
        The INTEGRITY frame defines the following flags:
        <list style="hanging">
          <t hangText="END_STREAM (0x1):">
            Bit 1 being set indicates that this frame is the last that
            the endpoint will send for the identified stream. Setting 
            this flag causes the stream to entire one of "half closed"
            states or "closed" state.
          </t>
        </list>
      </t>
      
      <t>
        The payload of the INTEGRITY frame consists of a MAC calculated
        over the payloads of all other frames sent on a stream since either
        the stream was opened or a previous INTEGRITY frame was sent.
      </t>

      <t>
        INTEGRITY frames MUST be associated with a stream that is, in turn,
        associated with a negotiated agreement. The algorithm used to
        gernerate the MAC is determined entirely through use of the 
        NEGOTIATE pseudo-method.
      </t>
      
    </section>
    
    <section title="Secure Tunneling with CONNECT">
      
      <t>
        Obviously, the approach described thus far only secures 
        the content of DATA frames. With HTTP, however, there is
        a significant amount of sensitive content carried within 
        HEADERS frames. To provide a more complete solution, 
        the mechanisms described herein can be combined with the 
        CONNECT method to create a secure tunnel. Specifically:
        <list style="symbols">
          <t>
            First, use the NEGOTIATE method to negotiate an 
            agreement with an origin,
          </t>
          <t>
            Second, use the CONNECT method to establish a 
            tunnel through that origin,
          </t>
          <t>
            Third, use SECURED DATA frames over the connected 
            tunnel.
          </t>
        </list>
      </t>
      
<figure><artwork>
  HEADERS 
    END_STREAM
    :method = NEGOTIATE
    :authority = example.org
    :id = 1
  ...
  
  HEADERS
    :method = CONNECT
    :authority = example.org
    :agreement = 1
  
  DATA 
    {Protected Data}
    
  INTEGRITY
    {Mac}
    
  DATA
    {Protected Data}
    
  ...
</artwork></figure>
  
    </section>
        
    <section title="Security Considerations">

      <t>TBD. TODO: Need to expand this...</t>

    </section>
        
  </middle> 

  <back>
    <references title="Normative References"> 
  &rfc2119;
  &rfc6454;
    </references>    
        
  </back>
</rfc> 
 

PAFTECH AB 2003-20262026-04-24 05:38:57