Subject: h2 padding

From: "Roy T. Fielding" <[email-masked]>
Date: Sat, 30 Aug 2014 12:14:17 -0700

This comment is in reference to sections 6.1, 6.2, 6.6 of

 http://tools.ietf.org/id/draft-ietf-httpbis-http2-14.txt

> 6.1.  DATA
> 
>    DATA frames (type=0x0) convey arbitrary, variable-length sequences of
>    octets associated with a stream.  One or more DATA frames are used,
>    for instance, to carry HTTP request or response payloads.
> 
>    DATA frames MAY also contain arbitrary padding.  Padding can be added
>    to DATA frames to obscure the size of messages.
> 
>      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
>     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>     |Pad Length? (8)|
>     +---------------+-----------------------------------------------+
>     |                            Data (*)                         ...
>     +---------------------------------------------------------------+
>     |                           Padding (*)                       ...
>     +---------------------------------------------------------------+
> 
>                             DATA Frame Payload
> 
>    The DATA frame contains the following fields:
> 
>    Pad Length:  An 8-bit field containing the length of the frame
>       padding in units of octets.  This field is optional and is only
>       present if the PADDED flag is set.
> 
>    Data:  Application data.  The amount of data is the remainder of the
>       frame payload after subtracting the length of the other fields
>       that are present.
> 
>    Padding:  Padding octets that contain no application semantic value.
>       Padding octets MUST be set to zero when sending and ignored when
>       receiving.

I think that is a mistake.  Forcing padding to zero makes it less random
and causes it to be compressed to nothing if a higher layer compresses
the stream.  A requirement on senders cannot prevent bad actors from
sending non-zeros (assuming this is to prevent smuggling of data).

>    The DATA frame defines the following flags:
> 
>    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 enter one of the "half
>       closed" states or the "closed" state (Section 5.1).
> 
>    PADDED (0x8):  Bit 4 being set indicates that the Pad Length field is
>       present.
> 
>    DATA frames MUST be associated with a stream.  If a DATA frame is
>    received whose stream identifier field is 0x0, the recipient MUST
>    respond with a connection error (Section 5.4.1) of type
>    PROTOCOL_ERROR.
> 
>    DATA frames are subject to flow control and can only be sent when a
>    stream is in the "open" or "half closed (remote)" states.  The entire
>    DATA frame payload is included in flow control, including Pad Length
>    and Padding fields if present.  If a DATA frame is received whose
>    stream is not in "open" or "half closed (local)" state, the recipient
>    MUST respond with a stream error (Section 5.4.2) of type
>    STREAM_CLOSED.
> 
>    The total number of padding octets is determined by the value of the
>    Pad Length field.  If the length of the padding is greater than the
>    length of the remainder of the frame payload, the recipient MUST
>    treat this as a connection error (Section 5.4.1) of type
>    PROTOCOL_ERROR.
> 
>    Note:  A frame can be increased in size by one octet by including a
>       Pad Length field with a value of zero.
> 
>    Use of padding is a security feature; as such, its use demands some
>    care, see Section 10.7.

I think there is a misunderstanding here.  Padding is used to allow an
opaque stream to not reveal its size.  Frames are not opaque.  There is no
need for padding within a frame.  The security need is for padding to be
allowed after a frame when both are enveloped within an opaque stream.

Naturally, this is best accomplished with a padding frame type.

As you can see, almost half of the description of this frame is devoted
to the optional padding.  The same is true of 6.2 and 6.6.
By moving padding to a frame type, we can then remove the optional
pad length and half the complexity for each of the types that currently
allow padding within their frames.

Cheers,

Roy T. Fielding                     <http://roy.gbiv.com/>
Senior Principal Scientist, Adobe   <http://www.adobe.com/>

---

From: Greg Wilkins <[email-masked]>
Date: Mon, 1 Sep 2014 08:43:22 +1000

> Naturally, this is best accomplished with a padding frame type.

I agree that having padding within the frame itself is not called for (and
pretty much unusable), but I would go further and ask why does the framing
layer need to know about security padding at all?

Telling the framing layer is inviting it to handle it differently and the
moment there is any different handling, then there are increased chances
that you will leak the information you are trying to hide (eg by timing or
other handling artefacts).   The spec makes it very clear that the
application of security padding is something that should be done with care
and knowledge of the application data:

   - *“Redundant padding could even be counterproductive.”*
   - *“Correct application can depend on having specific knowledge of the
   data that is being padded.”*
   - *“To mitigate attacks that rely on compression, disabling or limiting
   compression might be preferable to padding as a countermeasure.”*
   - *“Use of padding can result in less protection than might seem
   immediately obvious.”*
   - *“At best, padding only makes it more difficult for an attacker to
   infer length information by increasing the number of frames an attacker has
   to observe.”*
   - *“Incorrectly implemented padding schemes can be easily defeated.”*

Thus security padding cannot be applied at the framing layer and typically
there are no channels for applications to tunnel security knowledge about
payloads down to the framing layer. If security padding is desired by
knowledgeable application layers, then there are already places for padding
to be added without informing the framing layer that it is padding:  extra
headers, trailers, within the content-type itself, pong frames, etc.

Unless there are clear directives of how the framing layer should generate
security padding, then I don't think there should be any explicit handling
of padding by the framing layer.

On the other hand,  if h2 had padding for frame header alignment reasons,
then I see no problems in some smart implementations using that also for
security padding.

However, if padding is to be used for frame header alignment, then a
padding frame with normal frame header does not work because it can't do
minimal octet alignment.    Instead we could use padding octets that are
indicated by having the high bit set and the remaining bits used to
indicate how many padding octets follow:

   0
   0 1 2 3 4 5 6 7
  +-+-+-+-+-+-+-+-+
  |1| Pad count   |
  +-+-------------+

I guess conceptually this is a padding frame with a special 1 byte header.
This allows arbitrarily small padding and the mechanism can be used for
both alignment and security padding.

regards

-- 
Greg Wilkins <[email-masked]>
http://eclipse.org/jetty HTTP, SPDY, Websocket server and client that scales
http://www.webtide.com  advice and support for jetty and cometd.