#include <openssl/bn.h>
#include <openssl/engine.h>
+static MSG_PROCESS_RETURN tls_process_hello_retry_request(SSL *s, PACKET *pkt);
static MSG_PROCESS_RETURN tls_process_encrypted_extensions(SSL *s, PACKET *pkt);
static ossl_inline int cert_req_allowed(SSL *s);
default:
break;
+ case TLS_ST_CW_CLNT_HELLO:
+ /*
+ * This must a ClientHello following a HelloRetryRequest, so the only
+ * thing we can get now is a ServerHello.
+ */
+ if (mt == SSL3_MT_SERVER_HELLO) {
+ st->hand_state = TLS_ST_CR_SRVR_HELLO;
+ return 1;
+ }
+ break;
+
case TLS_ST_CR_SRVR_HELLO:
if (mt == SSL3_MT_ENCRYPTED_EXTENSIONS) {
st->hand_state = TLS_ST_CR_ENCRYPTED_EXTENSIONS;
st->hand_state = TLS_ST_CR_SESSION_TICKET;
return 1;
}
+ if (mt == SSL3_MT_KEY_UPDATE) {
+ st->hand_state = TLS_ST_CR_KEY_UPDATE;
+ return 1;
+ }
break;
}
int ske_expected;
/*
- * Note that after a ClientHello we don't know what version we are going
- * to negotiate yet, so we don't take this branch until later
+ * Note that after writing the first ClientHello we don't know what version
+ * we are going to negotiate yet, so we don't take this branch until later.
*/
if (SSL_IS_TLS13(s)) {
if (!ossl_statem_client13_read_transition(s, mt))
st->hand_state = DTLS_ST_CR_HELLO_VERIFY_REQUEST;
return 1;
}
+ } else {
+ if (mt == SSL3_MT_HELLO_RETRY_REQUEST) {
+ st->hand_state = TLS_ST_CR_HELLO_RETRY_REQUEST;
+ return 1;
+ }
}
break;
OSSL_STATEM *st = &s->statem;
/*
- * TODO(TLS1.3): This is still based on the TLSv1.2 state machine. Over time
- * we will update this to look more like real TLSv1.3
- */
-
- /*
- * Note: There are no cases for TLS_ST_BEFORE or TLS_ST_CW_CLNT_HELLO,
- * because we haven't negotiated TLSv1.3 yet at that point. They are
- * handled by ossl_statem_client_write_transition().
+ * Note: There are no cases for TLS_ST_BEFORE because we haven't negotiated
+ * TLSv1.3 yet at that point. They are handled by
+ * ossl_statem_client_write_transition().
*/
switch (st->hand_state) {
default:
/* Shouldn't happen */
return WRITE_TRAN_ERROR;
+ case TLS_ST_CW_CLNT_HELLO:
+ /* We only hit this in the case of HelloRetryRequest */
+ return WRITE_TRAN_FINISHED;
+
+ case TLS_ST_CR_HELLO_RETRY_REQUEST:
+ st->hand_state = TLS_ST_CW_CLNT_HELLO;
+ return WRITE_TRAN_CONTINUE;
+
case TLS_ST_CR_FINISHED:
st->hand_state = (s->s3->tmp.cert_req != 0) ? TLS_ST_CW_CERT
: TLS_ST_CW_FINISHED;
st->hand_state = TLS_ST_CW_FINISHED;
return WRITE_TRAN_CONTINUE;
+ case TLS_ST_CR_KEY_UPDATE:
+ if (s->key_update != SSL_KEY_UPDATE_NONE) {
+ st->hand_state = TLS_ST_CW_KEY_UPDATE;
+ return WRITE_TRAN_CONTINUE;
+ }
+ /* Fall through */
+
+ case TLS_ST_CW_KEY_UPDATE:
case TLS_ST_CR_SESSION_TICKET:
case TLS_ST_CW_FINISHED:
st->hand_state = TLS_ST_OK;
return WRITE_TRAN_CONTINUE;
case TLS_ST_OK:
- /* Just go straight to trying to read from the server */
+ if (s->key_update != SSL_KEY_UPDATE_NONE) {
+ st->hand_state = TLS_ST_CW_KEY_UPDATE;
+ return WRITE_TRAN_CONTINUE;
+ }
+
+ /* Try to read from the server instead */
return WRITE_TRAN_FINISHED;
}
}
return WORK_ERROR;
}
break;
+
+ case TLS_ST_CW_KEY_UPDATE:
+ if (statem_flush(s) != 1)
+ return WORK_MORE_A;
+ if (!tls13_update_key(s, 1))
+ return WORK_ERROR;
+ break;
}
return WORK_FINISHED_CONTINUE;
*confunc = tls_construct_finished;
*mt = SSL3_MT_FINISHED;
break;
+
+ case TLS_ST_CW_KEY_UPDATE:
+ *confunc = tls_construct_key_update;
+ *mt = SSL3_MT_KEY_UPDATE;
+ break;
}
return 1;
case DTLS_ST_CR_HELLO_VERIFY_REQUEST:
return HELLO_VERIFY_REQUEST_MAX_LENGTH;
+ case TLS_ST_CR_HELLO_RETRY_REQUEST:
+ return HELLO_RETRY_REQUEST_MAX_LENGTH;
+
case TLS_ST_CR_CERT:
return s->max_cert_list;
case TLS_ST_CR_ENCRYPTED_EXTENSIONS:
return ENCRYPTED_EXTENSIONS_MAX_LENGTH;
+
+ case TLS_ST_CR_KEY_UPDATE:
+ return KEY_UPDATE_MAX_LENGTH;
}
}
case DTLS_ST_CR_HELLO_VERIFY_REQUEST:
return dtls_process_hello_verify(s, pkt);
+ case TLS_ST_CR_HELLO_RETRY_REQUEST:
+ return tls_process_hello_retry_request(s, pkt);
+
case TLS_ST_CR_CERT:
return tls_process_server_certificate(s, pkt);
case TLS_ST_CR_ENCRYPTED_EXTENSIONS:
return tls_process_encrypted_extensions(s, pkt);
+
+ case TLS_ST_CR_KEY_UPDATE:
+ return tls_process_key_update(s, pkt);
}
}
context = SSL_IS_TLS13(s) ? EXT_TLS1_3_SERVER_HELLO
: EXT_TLS1_2_SERVER_HELLO;
- if (!tls_collect_extensions(s, &extpkt, context, &extensions, &al))
+ if (!tls_collect_extensions(s, &extpkt, context, &extensions, &al, NULL))
goto f_err;
s->hit = 0;
&& master_key_length > 0) {
s->session->master_key_length = master_key_length;
s->session->cipher = pref_cipher ?
- pref_cipher : ssl_get_cipher_by_char(s, cipherchars);
+ pref_cipher : ssl_get_cipher_by_char(s, cipherchars, 0);
} else {
SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
al = SSL_AD_INTERNAL_ERROR;
goto f_err;
}
- c = ssl_get_cipher_by_char(s, cipherchars);
+ c = ssl_get_cipher_by_char(s, cipherchars, 0);
if (c == NULL) {
/* unknown cipher */
al = SSL_AD_ILLEGAL_PARAMETER;
return MSG_PROCESS_ERROR;
}
+static MSG_PROCESS_RETURN tls_process_hello_retry_request(SSL *s, PACKET *pkt)
+{
+ unsigned int sversion;
+ int errorcode;
+ RAW_EXTENSION *extensions = NULL;
+ int al;
+ PACKET extpkt;
+
+ if (!PACKET_get_net_2(pkt, &sversion)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+
+ s->hello_retry_request = 1;
+
+ /* This will fail if it doesn't choose TLSv1.3+ */
+ errorcode = ssl_choose_client_version(s, sversion);
+ if (errorcode != 0) {
+ al = SSL_AD_PROTOCOL_VERSION;
+ SSLerr(SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST, errorcode);
+ goto f_err;
+ }
+
+ if (!PACKET_as_length_prefixed_2(pkt, &extpkt)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST, SSL_R_BAD_LENGTH);
+ goto f_err;
+ }
+
+ if (!tls_collect_extensions(s, &extpkt, EXT_TLS1_3_HELLO_RETRY_REQUEST,
+ &extensions, &al, NULL)
+ || !tls_parse_all_extensions(s, EXT_TLS1_3_HELLO_RETRY_REQUEST,
+ extensions, NULL, 0, &al))
+ goto f_err;
+
+ OPENSSL_free(extensions);
+
+ return MSG_PROCESS_FINISHED_READING;
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ ossl_statem_set_error(s);
+ OPENSSL_free(extensions);
+ return MSG_PROCESS_ERROR;
+}
+
MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
{
int al, i, ret = MSG_PROCESS_ERROR, exp_idx;
goto f_err;
}
if (!tls_collect_extensions(s, &extensions, EXT_TLS1_3_CERTIFICATE,
- &rawexts, &al)
+ &rawexts, &al, NULL)
|| !tls_parse_all_extensions(s, EXT_TLS1_3_CERTIFICATE,
rawexts, x, chainidx, &al)) {
OPENSSL_free(rawexts);
al = SSL_AD_DECODE_ERROR;
goto err;
}
- md = ssl_md(s->s3->tmp.peer_sigalg->hash_idx);
#ifdef SSL_DEBUG
fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));
#endif
- } else if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) {
- md = EVP_md5_sha1();
- } else {
- md = EVP_sha1();
+ } else if (!tls1_set_peer_legacy_sigalg(s, pkey)) {
+ al = SSL_AD_INTERNAL_ERROR;
+ goto err;
}
+ md = ssl_md(s->s3->tmp.peer_sigalg->hash_idx);
+
if (!PACKET_get_length_prefixed_2(pkt, &signature)
|| PACKET_remaining(pkt) != 0) {
al = SSL_AD_DECODE_ERROR;
goto err;
}
- /* Clear certificate digests and validity flags */
- for (i = 0; i < SSL_PKEY_NUM; i++) {
- s->s3->tmp.md[i] = NULL;
+ /* Clear certificate validity flags */
+ for (i = 0; i < SSL_PKEY_NUM; i++)
s->s3->tmp.valid_flags[i] = 0;
- }
if (!tls1_save_sigalgs(s, &sigalgs)) {
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, ERR_R_MALLOC_FAILURE);
goto err;
}
- } else {
- ssl_set_default_md(s);
}
/* get the CA RDNs */
if (!PACKET_as_length_prefixed_2(pkt, &extpkt)
|| !tls_collect_extensions(s, &extpkt,
EXT_TLS1_3_NEW_SESSION_TICKET,
- &exts, &al)
+ &exts, &al, NULL)
|| !tls_parse_all_extensions(s, EXT_TLS1_3_NEW_SESSION_TICKET,
exts, NULL, 0, &al)) {
SSLerr(SSL_F_TLS_PROCESS_NEW_SESSION_TICKET, SSL_R_BAD_EXTENSION);
*/
static int ssl3_check_client_certificate(SSL *s)
{
- if (!s->cert || !s->cert->key->x509 || !s->cert->key->privatekey)
- return 0;
/* If no suitable signature algorithm can't use certificate */
- if (SSL_USE_SIGALGS(s) && !s->s3->tmp.md[s->cert->key - s->cert->pkeys])
+ if (!tls_choose_sigalg(s, NULL) || s->s3->tmp.sigalg == NULL)
return 0;
/*
* If strict mode check suitability of chain before using it. This also
}
if (!tls_collect_extensions(s, &extensions, EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
- &rawexts, &al)
+ &rawexts, &al, NULL)
|| !tls_parse_all_extensions(s, EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
rawexts, NULL, 0, &al))
goto err;