Commit 06217867 authored by Emilia Kasper's avatar Emilia Kasper
Browse files

Refactor ClientHello extension parsing



1) Simplify code with better PACKET methods.

2) Make broken SNI parsing explicit. SNI was intended to be extensible
to new name types but RFC 4366 defined the syntax inextensibly, and
OpenSSL has never parsed SNI in a way that would allow adding a new name
type. RFC 6066 fixed the definition but due to broken implementations
being widespread, it appears impossible to ever extend SNI.

3) Annotate resumption behaviour. OpenSSL doesn't currently handle all
extensions correctly upon resumption. Annotate for further clean-up.

4) Send an alert on ALPN protocol mismatch.

Reviewed-by: default avatarKurt Roeckx <kurt@openssl.org>
parent d6c25879
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -4,6 +4,12 @@

 Changes between 1.0.2g and 1.1.0  [xx XXX xxxx]

  *) If the server has ALPN configured, but supports no protocols that the
     client advertises, send a fatal "no_application_protocol" alert.
     This behaviour is SHALL in RFC 7301, though it isn't universally
     implemented by other servers.
     [Emilia Käsper]

  *) Add X25519 support.
     Integrate support for X25519 into EC library. This includes support
     for public and private key encoding using the format documented in
+1 −0
Original line number Diff line number Diff line
@@ -1109,6 +1109,7 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
# define SSL_AD_UNKNOWN_PSK_IDENTITY     TLS1_AD_UNKNOWN_PSK_IDENTITY
/* fatal */
# define SSL_AD_INAPPROPRIATE_FALLBACK   TLS1_AD_INAPPROPRIATE_FALLBACK
# define SSL_AD_NO_APPLICATION_PROTOCOL  TLS1_AD_NO_APPLICATION_PROTOCOL
# define SSL_ERROR_NONE                  0
# define SSL_ERROR_SSL                   1
# define SSL_ERROR_WANT_READ             2
+1 −0
Original line number Diff line number Diff line
@@ -204,6 +204,7 @@ extern "C" {
# define TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE 113
# define TLS1_AD_BAD_CERTIFICATE_HASH_VALUE 114
# define TLS1_AD_UNKNOWN_PSK_IDENTITY    115/* fatal */
# define TLS1_AD_NO_APPLICATION_PROTOCOL 120 /* fatal */

/* ExtensionType values from RFC3546 / RFC4366 / RFC6066 */
# define TLSEXT_TYPE_server_name                 0
+63 −0
Original line number Diff line number Diff line
@@ -92,6 +92,16 @@ static ossl_inline size_t PACKET_remaining(const PACKET *pkt)
    return pkt->remaining;
}

/*
 * Returns a pointer to the first byte after the packet data.
 * Useful for integrating with non-PACKET parsing code.
 * Specifically, we use PACKET_end() to verify that a d2i_... call
 * has consumed the entire packet contents.
 */
static ossl_inline const unsigned char *PACKET_end(const PACKET *pkt)
{
    return pkt->curr + pkt->remaining;
}
/*
 * Returns a pointer to the PACKET's current position.
 * For use in non-PACKETized APIs.
@@ -452,6 +462,12 @@ __owur static ossl_inline int PACKET_strndup(const PACKET *pkt, char **data)
    return (*data != NULL);
}

/* Returns 1 if |pkt| contains at least one 0-byte, 0 otherwise. */
static ossl_inline int PACKET_contains_zero_byte(const PACKET *pkt)
{
  return memchr(pkt->curr, 0, pkt->remaining) != NULL;
}

/* Move the current reading position forward |len| bytes */
__owur static ossl_inline int PACKET_forward(PACKET *pkt, size_t len)
{
@@ -488,6 +504,28 @@ __owur static ossl_inline int PACKET_get_length_prefixed_1(PACKET *pkt,
    return 1;
}

/*
 * Like PACKET_get_length_prefixed_1, but additionally, fails when there are
 * leftover bytes in |pkt|.
 */
__owur static ossl_inline int PACKET_as_length_prefixed_1(PACKET *pkt, PACKET *subpkt)
{
  unsigned int length;
  const unsigned char *data;
  PACKET tmp = *pkt;
  if (!PACKET_get_1(&tmp, &length) ||
      !PACKET_get_bytes(&tmp, &data, (size_t)length) ||
      PACKET_remaining(&tmp) != 0) {
      return 0;
  }

  *pkt = tmp;
  subpkt->curr = data;
  subpkt->remaining = length;

  return 1;
}

/*
 * Reads a variable-length vector prefixed with a two-byte length, and stores
 * the contents in |subpkt|. |pkt| can equal |subpkt|.
@@ -501,6 +539,7 @@ __owur static ossl_inline int PACKET_get_length_prefixed_2(PACKET *pkt,
    unsigned int length;
    const unsigned char *data;
    PACKET tmp = *pkt;

    if (!PACKET_get_net_2(&tmp, &length) ||
        !PACKET_get_bytes(&tmp, &data, (size_t)length)) {
        return 0;
@@ -513,6 +552,30 @@ __owur static ossl_inline int PACKET_get_length_prefixed_2(PACKET *pkt,
    return 1;
}

/*
 * Like PACKET_get_length_prefixed_2, but additionally, fails when there are
 * leftover bytes in |pkt|.
 */
__owur static ossl_inline int PACKET_as_length_prefixed_2(PACKET *pkt,
                                                          PACKET *subpkt)
{
  unsigned int length;
  const unsigned char *data;
  PACKET tmp = *pkt;

  if (!PACKET_get_net_2(&tmp, &length) ||
      !PACKET_get_bytes(&tmp, &data, (size_t)length) ||
      PACKET_remaining(&tmp) != 0) {
      return 0;
  }

  *pkt = tmp;
  subpkt->curr = data;
  subpkt->remaining = length;

  return 1;
}

/*
 * Reads a variable-length vector prefixed with a three-byte length, and stores
 * the contents in |subpkt|. |pkt| can equal |subpkt|.
+2 −0
Original line number Diff line number Diff line
@@ -667,6 +667,8 @@ int ssl3_alert_code(int code)
        return (TLS1_AD_UNKNOWN_PSK_IDENTITY);
    case SSL_AD_INAPPROPRIATE_FALLBACK:
        return (TLS1_AD_INAPPROPRIATE_FALLBACK);
    case SSL_AD_NO_APPLICATION_PROTOCOL:
        return (TLS1_AD_NO_APPLICATION_PROTOCOL);
    default:
        return (-1);
    }
Loading