#include <openssl/evp.h>
#include <openssl/x509.h>
+/* Fixed value used in the ServerHello random field to identify an HRR */
+const unsigned char hrrrandom[] = {
+ 0xcf, 0x21, 0xad, 0x74, 0xe5, 0x9a, 0x61, 0x11, 0xbe, 0x1d, 0x8c, 0x02,
+ 0x1e, 0x65, 0xb8, 0x91, 0xc2, 0xa2, 0x11, 0x16, 0x7a, 0xbb, 0x8c, 0x5e,
+ 0x07, 0x9e, 0x09, 0xe2, 0xc8, 0xa8, 0x33, 0x9c
+};
+
/*
* send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or
* SSL3_RT_CHANGE_CIPHER_SPEC)
* in NBIO events. If |clearbufs| is set then init_buf and the wbio buffer is
* freed up as well.
*/
-WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs)
+WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs, int stop)
{
int discard;
void (*cb) (const SSL *ssl, int type, int val) = NULL;
}
}
- /*
- * If we've not cleared the buffers its because we've got more work to do,
- * so continue.
- */
- if (!clearbufs)
+ if (!stop)
return WORK_FINISHED_CONTINUE;
ossl_statem_set_in_init(s, 0);
SSL_R_BAD_CHANGE_CIPHER_SPEC);
return 0;
}
+ if (s->statem.hand_state == TLS_ST_BEFORE
+ && (s->s3->flags & TLS1_FLAGS_STATELESS) != 0) {
+ /*
+ * We are stateless and we received a CCS. Probably this is
+ * from a client between the first and second ClientHellos.
+ * We should ignore this, but return an error because we do
+ * not return success until we see the second ClientHello
+ * with a valid cookie.
+ */
+ return 0;
+ }
s->s3->tmp.message_type = *mt = SSL3_MT_CHANGE_CIPHER_SPEC;
s->init_num = readbytes - 1;
s->init_msg = s->init_buf->data;
* We defer feeding in the HRR until later. We'll do it as part of
* processing the message
*/
- if (s->s3->tmp.message_type != SSL3_MT_HELLO_RETRY_REQUEST
- && !ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
- s->init_num + SSL3_HM_HEADER_LENGTH)) {
- /* SSLfatal() already called */
- *len = 0;
- return 0;
+#define SERVER_HELLO_RANDOM_OFFSET (SSL3_HM_HEADER_LENGTH + 2)
+ if (s->s3->tmp.message_type != SSL3_MT_SERVER_HELLO
+ || s->init_num < SERVER_HELLO_RANDOM_OFFSET + SSL3_RANDOM_SIZE
+ || memcmp(hrrrandom,
+ s->init_buf->data + SERVER_HELLO_RANDOM_OFFSET,
+ SSL3_RANDOM_SIZE) != 0) {
+ if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
+ s->init_num + SSL3_HM_HEADER_LENGTH)) {
+ /* SSLfatal() already called */
+ *len = 0;
+ return 0;
+ }
}
if (s->msg_callback)
s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data,
suppversions = &hello->pre_proc_exts[TLSEXT_IDX_supported_versions];
+ /* If we did an HRR then supported versions is mandatory */
+ if (!suppversions->present && s->hello_retry_request != SSL_HRR_NONE)
+ return SSL_R_UNSUPPORTED_PROTOCOL;
+
if (suppversions->present && !SSL_IS_DTLS(s)) {
unsigned int candidate_vers = 0;
unsigned int best_vers = 0;
}
if (best_vers > 0) {
- if (SSL_IS_TLS13(s)) {
+ if (s->hello_retry_request != SSL_HRR_NONE) {
/*
- * We get here if this is after a HelloRetryRequest. In this
- * case we just check that we still negotiated TLSv1.3
+ * This is after a HelloRetryRequest so we better check that we
+ * negotiated TLSv1.3
*/
if (best_vers != TLS1_3_VERSION)
return SSL_R_UNSUPPORTED_PROTOCOL;
return 0;
}
- if (s->hello_retry_request && s->version != TLS1_3_VERSION) {
+ if (s->hello_retry_request != SSL_HRR_NONE
+ && s->version != TLS1_3_VERSION) {
s->version = origv;
SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_SSL_CHOOSE_CLIENT_VERSION,
SSL_R_WRONG_SSL_VERSION);
#endif
/* Replace ClientHello1 in the transcript hash with a synthetic message */
-int create_synthetic_message_hash(SSL *s)
+int create_synthetic_message_hash(SSL *s, const unsigned char *hashval,
+ size_t hashlen, const unsigned char *hrr,
+ size_t hrrlen)
{
- unsigned char hashval[EVP_MAX_MD_SIZE];
- size_t hashlen = 0;
+ unsigned char hashvaltmp[EVP_MAX_MD_SIZE];
unsigned char msghdr[SSL3_HM_HEADER_LENGTH];
memset(msghdr, 0, sizeof(msghdr));
- /* Get the hash of the initial ClientHello */
- if (!ssl3_digest_cached_records(s, 0)
- || !ssl_handshake_hash(s, hashval, sizeof(hashval), &hashlen)) {
- /* SSLfatal() already called */
- return 0;
+ if (hashval == NULL) {
+ hashval = hashvaltmp;
+ hashlen = 0;
+ /* Get the hash of the initial ClientHello */
+ if (!ssl3_digest_cached_records(s, 0)
+ || !ssl_handshake_hash(s, hashvaltmp, sizeof(hashvaltmp),
+ &hashlen)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
}
/* Reinitialise the transcript hash */
return 0;
}
+ /*
+ * Now re-inject the HRR and current message if appropriate (we just deleted
+ * it when we reinitialised the transcript hash above). Only necessary after
+ * receiving a ClientHello2 with a cookie.
+ */
+ if (hrr != NULL
+ && (!ssl3_finish_mac(s, hrr, hrrlen)
+ || !ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
+ s->s3->tmp.message_size
+ + SSL3_HM_HEADER_LENGTH))) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+
return 1;
}