Newer
Older
* Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/ocsp.h>
#include "../ssl_locl.h"
#include "statem_locl.h"
#include "internal/cryptlib.h"
#define COOKIE_STATE_FORMAT_VERSION 0
/*
* 2 bytes for packet length, 2 bytes for format version, 2 bytes for
* protocol version, 2 bytes for group id, 2 bytes for cipher id, 1 byte for
* key_share present flag, 4 bytes for timestamp, 2 bytes for the hashlen,
* EVP_MAX_MD_SIZE for transcript hash, 1 byte for app cookie length, app cookie
* length bytes, SHA256_DIGEST_LENGTH bytes for the HMAC of the whole thing.
#define MAX_COOKIE_SIZE (2 + 2 + 2 + 2 + 2 + 1 + 4 + 2 + EVP_MAX_MD_SIZE + 1 \
+ SSL_COOKIE_LENGTH + SHA256_DIGEST_LENGTH)
/*
* Message header + 2 bytes for protocol version + number of random bytes +
* + 1 byte for legacy session id length + number of bytes in legacy session id
* + 2 bytes for ciphersuite + 1 byte for legacy compression
* + 2 bytes for extension block length + 6 bytes for key_share extension
* + 4 bytes for cookie extension header + the number of bytes in the cookie
#define MAX_HRR_SIZE (SSL3_HM_HEADER_LENGTH + 2 + SSL3_RANDOM_SIZE + 1 \
+ SSL_MAX_SSL_SESSION_ID_LENGTH + 2 + 1 + 2 + 6 + 4 \
+ MAX_COOKIE_SIZE)
/*
* Parse the client's renegotiation binding and abort if it's not right
*/
int tls_parse_ctos_renegotiate(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
unsigned int ilen;
const unsigned char *data;
/* Parse the length byte */
if (!PACKET_get_1(pkt, &ilen)
|| !PACKET_get_bytes(pkt, &data, ilen)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE,
SSL_R_RENEGOTIATION_ENCODING_ERR);
return 0;
}
/* Check that the extension matches */
if (ilen != s->s3->previous_client_finished_len) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE,
SSL_R_RENEGOTIATION_MISMATCH);
return 0;
}
if (memcmp(data, s->s3->previous_client_finished,
s->s3->previous_client_finished_len)) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE,
SSL_R_RENEGOTIATION_MISMATCH);
return 0;
}
s->s3->send_connection_binding = 1;
return 1;
}
/*-
* The servername extension is treated as follows:
*
* - Only the hostname type is supported with a maximum length of 255.
* - The servername is rejected if too long or if it contains zeros,
* in which case an fatal alert is generated.
* - The servername field is maintained together with the session cache.
* - When a session is resumed, the servername call back invoked in order
* to allow the application to position itself to the right context.
* - The servername is acknowledged if it is new for a session or when
* it is identical to a previously used for the same session.
* Applications can control the behaviour. They can at any time
* set a 'desirable' servername for a new SSL object. This can be the
* case for example with HTTPS when a Host: header field is received and
* a renegotiation is requested. In this case, a possible servername
* presented in the new client hello is only acknowledged if it matches
* the value of the Host: field.
* - Applications must use SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
* if they provide for changing an explicit servername context for the
* session, i.e. when the session has been established with a servername
* extension.
* - On session reconnect, the servername extension may be absent.
*/
int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
unsigned int servname_type;
PACKET sni, hostname;
if (!PACKET_as_length_prefixed_2(pkt, &sni)
/* ServerNameList must be at least 1 byte long. */
|| PACKET_remaining(&sni) == 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
SSL_R_BAD_EXTENSION);
return 0;
}
/*
* Although the intent was for server_name to be extensible, RFC 4366
* was not clear about it; and so OpenSSL among other implementations,
* always and only allows a 'host_name' name types.
* RFC 6066 corrected the mistake but adding new name types
* is nevertheless no longer feasible, so act as if no other
* SNI types can exist, to simplify parsing.
*
* Also note that the RFC permits only one SNI value per type,
* i.e., we can only have a single hostname.
*/
if (!PACKET_get_1(&sni, &servname_type)
|| servname_type != TLSEXT_NAMETYPE_host_name
|| !PACKET_as_length_prefixed_2(&sni, &hostname)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
SSL_R_BAD_EXTENSION);
return 0;
}
if (!s->hit) {
if (PACKET_remaining(&hostname) > TLSEXT_MAXLEN_host_name) {
SSLfatal(s, SSL_AD_UNRECOGNIZED_NAME,
SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
SSL_R_BAD_EXTENSION);
return 0;
}
if (PACKET_contains_zero_byte(&hostname)) {
SSLfatal(s, SSL_AD_UNRECOGNIZED_NAME,
SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
SSL_R_BAD_EXTENSION);
return 0;
}
OPENSSL_free(s->session->ext.hostname);
s->session->ext.hostname = NULL;
if (!PACKET_strndup(&hostname, &s->session->ext.hostname)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
ERR_R_INTERNAL_ERROR);
return 0;
}
s->servername_done = 1;
} else {
/*
* TODO(openssl-team): if the SNI doesn't match, we MUST
* fall back to a full handshake.
*/
s->servername_done = s->session->ext.hostname
&& PACKET_equal(&hostname, s->session->ext.hostname,
strlen(s->session->ext.hostname));
if (!s->servername_done && s->session->ext.hostname != NULL)
s->ext.early_data_ok = 0;
}
return 1;
}
int tls_parse_ctos_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
unsigned int value;
if (PACKET_remaining(pkt) != 1 || !PACKET_get_1(pkt, &value)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN,
SSL_R_BAD_EXTENSION);
return 0;
}
/* Received |value| should be a valid max-fragment-length code. */
if (!IS_MAX_FRAGMENT_LENGTH_EXT_VALID(value)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN,
SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
return 0;
}
/*
* RFC 6066: The negotiated length applies for the duration of the session
* including session resumptions.
* We should receive the same code as in resumed session !
*/
if (s->hit && s->session->ext.max_fragment_len_mode != value) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN,
SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
Loading
Loading full blame…