MSG_PROCESS_RETURN tls_process_finished(SSL *s, PACKET *pkt)
{
- int al;
+ int al = SSL_AD_INTERNAL_ERROR;
size_t md_len;
/* If this occurs, we have missed a message */
- if (!s->s3->change_cipher_spec) {
+ if (!SSL_IS_TLS13(s) && !s->s3->change_cipher_spec) {
al = SSL_AD_UNEXPECTED_MESSAGE;
SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_GOT_A_FIN_BEFORE_A_CCS);
goto f_err;
s->s3->previous_server_finished_len = md_len;
}
+ /*
+ * In TLS1.3 we also have to change cipher state and do any final processing
+ * of the initial server flight (if we are a client)
+ */
+ if (SSL_IS_TLS13(s)) {
+ if (s->server) {
+ if (!s->method->ssl3_enc->change_cipher_state(s,
+ SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_SERVER_READ)) {
+ SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_CANNOT_CHANGE_CIPHER);
+ goto f_err;
+ }
+ } else {
+ if (!s->method->ssl3_enc->generate_master_secret(s,
+ s->session->master_key, s->handshake_secret, 0,
+ &s->session->master_key_length)) {
+ SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_CANNOT_CHANGE_CIPHER);
+ goto f_err;
+ }
+ if (!s->method->ssl3_enc->change_cipher_state(s,
+ SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_CLIENT_READ)) {
+ SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_CANNOT_CHANGE_CIPHER);
+ goto f_err;
+ }
+ if (!tls_process_initial_server_flight(s, &al))
+ goto f_err;
+ }
+ }
+
return MSG_PROCESS_FINISHED_READING;
f_err:
ssl3_send_alert(s, SSL3_AL_FATAL, al);
return 1;
}
-unsigned long ssl3_output_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk)
+/* Add a certificate to the WPACKET */
+static int ssl_add_cert_to_wpacket(SSL *s, WPACKET *pkt, X509 *x, int chain,
+ int *al)
+{
+ int len;
+ unsigned char *outbytes;
+
+ len = i2d_X509(x, NULL);
+ if (len < 0) {
+ SSLerr(SSL_F_SSL_ADD_CERT_TO_WPACKET, ERR_R_BUF_LIB);
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ if (!WPACKET_sub_allocate_bytes_u24(pkt, len, &outbytes)
+ || i2d_X509(x, &outbytes) != len) {
+ SSLerr(SSL_F_SSL_ADD_CERT_TO_WPACKET, ERR_R_INTERNAL_ERROR);
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+
+ if (SSL_IS_TLS13(s)
+ && !tls_construct_extensions(s, pkt, EXT_TLS1_3_CERTIFICATE, x,
+ chain, al))
+ return 0;
+
+ return 1;
+}
+
+/* Add certificate chain to provided WPACKET */
+static int ssl_add_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk, int *al)
{
+ int i, chain_count;
+ X509 *x;
+ STACK_OF(X509) *extra_certs;
+ STACK_OF(X509) *chain = NULL;
+ X509_STORE *chain_store;
+ int tmpal = SSL_AD_INTERNAL_ERROR;
+
+ if (cpk == NULL || cpk->x509 == NULL)
+ return 1;
+
+ x = cpk->x509;
+
+ /*
+ * If we have a certificate specific chain use it, else use parent ctx.
+ */
+ if (cpk->chain != NULL)
+ extra_certs = cpk->chain;
+ else
+ extra_certs = s->ctx->extra_certs;
+
+ if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || extra_certs)
+ chain_store = NULL;
+ else if (s->cert->chain_store)
+ chain_store = s->cert->chain_store;
+ else
+ chain_store = s->ctx->cert_store;
+
+ if (chain_store != NULL) {
+ X509_STORE_CTX *xs_ctx = X509_STORE_CTX_new();
+
+ if (xs_ctx == NULL) {
+ SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (!X509_STORE_CTX_init(xs_ctx, chain_store, x, NULL)) {
+ X509_STORE_CTX_free(xs_ctx);
+ SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, ERR_R_X509_LIB);
+ goto err;
+ }
+ /*
+ * It is valid for the chain not to be complete (because normally we
+ * don't include the root cert in the chain). Therefore we deliberately
+ * ignore the error return from this call. We're not actually verifying
+ * the cert - we're just building as much of the chain as we can
+ */
+ (void)X509_verify_cert(xs_ctx);
+ /* Don't leave errors in the queue */
+ ERR_clear_error();
+ chain = X509_STORE_CTX_get0_chain(xs_ctx);
+ i = ssl_security_cert_chain(s, chain, NULL, 0);
+ if (i != 1) {
+#if 0
+ /* Dummy error calls so mkerr generates them */
+ SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, SSL_R_EE_KEY_TOO_SMALL);
+ SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, SSL_R_CA_KEY_TOO_SMALL);
+ SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, SSL_R_CA_MD_TOO_WEAK);
+#endif
+ X509_STORE_CTX_free(xs_ctx);
+ SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, i);
+ goto err;
+ }
+ chain_count = sk_X509_num(chain);
+ for (i = 0; i < chain_count; i++) {
+ x = sk_X509_value(chain, i);
+
+ if (!ssl_add_cert_to_wpacket(s, pkt, x, i, &tmpal)) {
+ X509_STORE_CTX_free(xs_ctx);
+ goto err;
+ }
+ }
+ X509_STORE_CTX_free(xs_ctx);
+ } else {
+ i = ssl_security_cert_chain(s, extra_certs, x, 0);
+ if (i != 1) {
+ SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, i);
+ goto err;
+ }
+ if (!ssl_add_cert_to_wpacket(s, pkt, x, 0, &tmpal))
+ goto err;
+ for (i = 0; i < sk_X509_num(extra_certs); i++) {
+ x = sk_X509_value(extra_certs, i);
+ if (!ssl_add_cert_to_wpacket(s, pkt, x, i + 1, &tmpal))
+ goto err;
+ }
+ }
+ return 1;
+
+ err:
+ *al = tmpal;
+ return 0;
+}
+
+unsigned long ssl3_output_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk,
+ int *al)
+{
+ int tmpal = SSL_AD_INTERNAL_ERROR;
+
if (!WPACKET_start_sub_packet_u24(pkt)
- || !ssl_add_cert_chain(s, pkt, cpk)
+ || !ssl_add_cert_chain(s, pkt, cpk, &tmpal)
|| !WPACKET_close(pkt)) {
SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN, ERR_R_INTERNAL_ERROR);
+ *al = tmpal;
return 0;
}
return 1;
/* s->init_num < SSL3_HM_HEADER_LENGTH */
int skip_message, i, recvd_type, al;
unsigned char *p;
- size_t l, read;
+ size_t l, readbytes;
p = (unsigned char *)s->init_buf->data;
i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, &recvd_type,
&p[s->init_num],
SSL3_HM_HEADER_LENGTH - s->init_num,
- 0, &read);
+ 0, &readbytes);
if (i <= 0) {
s->rwstate = SSL_READING;
return 0;
* A ChangeCipherSpec must be a single byte and may not occur
* in the middle of a handshake message.
*/
- if (s->init_num != 0 || read != 1 || p[0] != SSL3_MT_CCS) {
+ if (s->init_num != 0 || readbytes != 1 || p[0] != SSL3_MT_CCS) {
al = SSL_AD_UNEXPECTED_MESSAGE;
SSLerr(SSL_F_TLS_GET_MESSAGE_HEADER,
SSL_R_BAD_CHANGE_CIPHER_SPEC);
goto f_err;
}
s->s3->tmp.message_type = *mt = SSL3_MT_CHANGE_CIPHER_SPEC;
- s->init_num = read - 1;
- s->s3->tmp.message_size = read;
+ s->init_num = readbytes - 1;
+ s->init_msg = s->init_buf->data;
+ s->s3->tmp.message_size = readbytes;
return 1;
} else if (recvd_type != SSL3_RT_HANDSHAKE) {
al = SSL_AD_UNEXPECTED_MESSAGE;
SSLerr(SSL_F_TLS_GET_MESSAGE_HEADER, SSL_R_CCS_RECEIVED_EARLY);
goto f_err;
}
- s->init_num += read;
+ s->init_num += readbytes;
}
skip_message = 0;
int tls_get_message_body(SSL *s, size_t *len)
{
- size_t n, read;
+ size_t n, readbytes;
unsigned char *p;
int i;
n = s->s3->tmp.message_size - s->init_num;
while (n > 0) {
i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL,
- &p[s->init_num], n, 0, &read);
+ &p[s->init_num], n, 0, &readbytes);
if (i <= 0) {
s->rwstate = SSL_READING;
*len = 0;
return 0;
}
- s->init_num += read;
- n -= read;
+ s->init_num += readbytes;
+ n -= readbytes;
}
#ifndef OPENSSL_NO_NEXTPROTONEG
*
* Returns 0 on success or an SSL error reason number on failure.
*/
-int ssl_choose_server_version(SSL *s)
+int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello)
{
/*-
* With version-flexible methods we have an initial state with:
* handle version.
*/
int server_version = s->method->version;
- int client_version = s->client_version;
+ int client_version = hello->legacy_version;
const version_info *vent;
const version_info *table;
int disabled = 0;
+ RAW_EXTENSION *suppversions;
+
+ s->client_version = client_version;
switch (server_version) {
default:
+ /*
+ * TODO(TLS1.3): This check will fail if someone attempts to do
+ * renegotiation in TLS1.3 at the moment. We need to ensure we disable
+ * renegotiation for TLS1.3
+ */
if (version_cmp(s, client_version, s->version) < 0)
return SSL_R_WRONG_SSL_VERSION;
/*
break;
}
+ suppversions = &hello->pre_proc_exts[TLSEXT_IDX_supported_versions];
+
+ if (suppversions->present && !SSL_IS_DTLS(s)) {
+ unsigned int candidate_vers = 0;
+ unsigned int best_vers = 0;
+ const SSL_METHOD *best_method = NULL;
+ PACKET versionslist;
+
+ suppversions->parsed = 1;
+
+ if (!PACKET_as_length_prefixed_1(&suppversions->data, &versionslist)) {
+ /* Trailing or invalid data? */
+ return SSL_R_LENGTH_MISMATCH;
+ }
+
+ while (PACKET_get_net_2(&versionslist, &candidate_vers)) {
+ /* TODO(TLS1.3): Remove this before release */
+ if (candidate_vers == TLS1_3_VERSION_DRAFT)
+ candidate_vers = TLS1_3_VERSION;
+ /*
+ * TODO(TLS1.3): There is some discussion on the TLS list about
+ * wheter to ignore versions <TLS1.2 in supported_versions. At the
+ * moment we honour them if present. To be reviewed later
+ */
+ if (version_cmp(s, candidate_vers, best_vers) <= 0)
+ continue;
+ for (vent = table;
+ vent->version != 0 && vent->version != (int)candidate_vers;
+ ++vent)
+ continue;
+ if (vent->version != 0 && vent->smeth != NULL) {
+ const SSL_METHOD *method;
+
+ method = vent->smeth();
+ if (ssl_method_error(s, method) == 0) {
+ best_vers = candidate_vers;
+ best_method = method;
+ }
+ }
+ }
+ if (PACKET_remaining(&versionslist) != 0) {
+ /* Trailing data? */
+ return SSL_R_LENGTH_MISMATCH;
+ }
+
+ if (best_vers > 0) {
+ s->version = best_vers;
+ s->method = best_method;
+ return 0;
+ }
+ return SSL_R_UNSUPPORTED_PROTOCOL;
+ }
+
+ /*
+ * If the supported versions extension isn't present, then the highest
+ * version we can negotiate is TLSv1.2
+ */
+ if (version_cmp(s, client_version, TLS1_3_VERSION) >= 0)
+ client_version = TLS1_2_VERSION;
+
+ /*
+ * No supported versions extension, so we just use the version supplied in
+ * the ClientHello.
+ */
for (vent = table; vent->version != 0; ++vent) {
const SSL_METHOD *method;
const version_info *vent;
const version_info *table;
+ /* TODO(TLS1.3): Remove this before release */
+ if (version == TLS1_3_VERSION_DRAFT)
+ version = TLS1_3_VERSION;
+
switch (s->method->version) {
default:
if (version != s->version)
/*
* ssl_set_client_hello_version - Work out what version we should be using for
- * the initial ClientHello.
+ * the initial ClientHello.legacy_version field.
*
* @s: client SSL handle.
*
if (ret != 0)
return ret;
- s->client_version = s->version = ver_max;
+ s->version = ver_max;
+
+ /* TLS1.3 always uses TLS1.2 in the legacy_version field */
+ if (!SSL_IS_DTLS(s) && ver_max > TLS1_2_VERSION)
+ ver_max = TLS1_2_VERSION;
+
+ s->client_version = ver_max;
return 0;
}