[gnutls-devel] Incorrect SSL heartbeat bounds checking (not exploitable)

Peter Dettman peter.dettman at bouncycastle.org
Fri Apr 11 11:02:38 CEST 2014

Hi All,

I concur with Frank, in that this code is not enforcing a minimum length 
for the padding of 16 bytes as specified in RFC 6520.

       if (len < 4)
         return  gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);

The minimum packet length is 19, so that should be "len < 19".

       if (hb_len > len - 3)
         return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);

The payload is bounded by the minimum 19 bytes for non-payload data, so 
this should be "hb_len > len - 19". I would wonder also whether that is 
the most appropriate error code for a malformed message, but I don't 
know enough about the available error codes to judge.

A further comment on the message format:

    struct {
       HeartbeatMessageType type;
       uint16 payload_length;
       opaque payload[HeartbeatMessage.payload_length];
       opaque padding[padding_length];
    } HeartbeatMessage;

The "padding_length" is defined implicitly here i.e. "whatever is left 
in the record following the previous fields" (subject to being at least 
16 bytes). That's quite a strange choice; the only other example of such 
a thing I can think of is ClientHello.extensions, where there is a more 
apparent justification. Why not explicitly include the padding_length?

Perhaps more seriously, requiring that it be filled with "random padding 
of at least 16 bytes" is 1) semantically pretty meaningless (later it 
says that the receiver MUST ignore the contents anyway!), and 2) 
suspicious in the light of DUAL_EC_DRBG and other RNG-related 
revelations. I would advise to review what randomness is used by GnuTLS 
here, and I suggest a deterministic construction of the TLS PRF keyed on 
a hash of the payload  (by analogy to RFC 6979) should be considered 
instead of actual random data (especially if the same source is used for 
key material).

Pete Dettman

On 11/04/2014 8:34 AM, Frank Li wrote:
> This may have already been discovered due to Heartbleed. gnutls's TLS 
> heartbeat implementation is not vulnerable to heartbleed but also does 
> not check the heartbeat length field matches the payload length. A 
> heartbeat response may be larger than the heartbeat request. I bring 
> this up for correctness and RFC6520-adherence sake.

More information about the Gnutls-devel mailing list