default:
break;
- case TLS_ST_SW_HELLO_RETRY_REQUEST:
- if (mt == SSL3_MT_CLIENT_HELLO) {
- st->hand_state = TLS_ST_SR_CLNT_HELLO;
- return 1;
- }
- break;
-
case TLS_ST_EARLY_DATA:
- if (s->ext.early_data == SSL_EARLY_DATA_ACCEPTED) {
+ if (s->hello_retry_request) {
+ if (mt == SSL3_MT_CLIENT_HELLO) {
+ st->hand_state = TLS_ST_SR_CLNT_HELLO;
+ return 1;
+ }
+ break;
+ } else if (s->ext.early_data == SSL_EARLY_DATA_ACCEPTED) {
if (mt == SSL3_MT_END_OF_EARLY_DATA) {
st->hand_state = TLS_ST_SR_END_OF_EARLY_DATA;
return 1;
return WRITE_TRAN_CONTINUE;
case TLS_ST_SW_HELLO_RETRY_REQUEST:
- return WRITE_TRAN_FINISHED;
+ st->hand_state = TLS_ST_EARLY_DATA;
+ return WRITE_TRAN_CONTINUE;
case TLS_ST_SW_SRVR_HELLO:
st->hand_state = TLS_ST_SW_ENCRYPTED_EXTENSIONS;
*/
if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) {
if (clienthello->dtls_cookie_len == 0)
- return 1;
+ return MSG_PROCESS_FINISHED_READING;
}
}
DOWNGRADE dgrd = DOWNGRADE_NONE;
/* Finished parsing the ClientHello, now we can start processing it */
- /* Give the early callback a crack at things */
- if (s->ctx->early_cb != NULL) {
- int code;
- /* A failure in the early callback terminates the connection. */
- code = s->ctx->early_cb(s, &al, s->ctx->early_cb_arg);
- if (code == 0)
+ /* Give the ClientHello callback a crack at things */
+ if (s->ctx->client_hello_cb != NULL) {
+ /* A failure in the ClientHello callback terminates the connection. */
+ switch (s->ctx->client_hello_cb(s, &al, s->ctx->client_hello_cb_arg)) {
+ case SSL_CLIENT_HELLO_SUCCESS:
+ break;
+ case SSL_CLIENT_HELLO_RETRY:
+ s->rwstate = SSL_CLIENT_HELLO_CB;
+ return -1;
+ case SSL_CLIENT_HELLO_ERROR:
+ default:
goto err;
- if (code < 0) {
- s->rwstate = SSL_EARLY_WORK;
- return code;
}
}
return 1;
}
+/*
+ * Call the alpn_select callback if needed. Upon success, returns 1.
+ * Upon failure, returns 0 and sets |*al| to the appropriate fatal alert.
+ */
+int tls_handle_alpn(SSL *s, int *al)
+{
+ const unsigned char *selected = NULL;
+ unsigned char selected_len = 0;
+
+ if (s->ctx->ext.alpn_select_cb != NULL && s->s3->alpn_proposed != NULL) {
+ int r = s->ctx->ext.alpn_select_cb(s, &selected, &selected_len,
+ s->s3->alpn_proposed,
+ (unsigned int)s->s3->alpn_proposed_len,
+ s->ctx->ext.alpn_select_cb_arg);
+
+ if (r == SSL_TLSEXT_ERR_OK) {
+ OPENSSL_free(s->s3->alpn_selected);
+ s->s3->alpn_selected = OPENSSL_memdup(selected, selected_len);
+ if (s->s3->alpn_selected == NULL) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ s->s3->alpn_selected_len = selected_len;
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ /* ALPN takes precedence over NPN. */
+ s->s3->npn_seen = 0;
+#endif
+
+ /* Check ALPN is consistent with session */
+ if (s->session->ext.alpn_selected == NULL
+ || selected_len != s->session->ext.alpn_selected_len
+ || memcmp(selected, s->session->ext.alpn_selected,
+ selected_len) != 0) {
+ /* Not consistent so can't be used for early_data */
+ s->ext.early_data_ok = 0;
+
+ if (!s->hit) {
+ /* If a new session update it with the new ALPN value */
+ s->session->ext.alpn_selected = OPENSSL_memdup(selected,
+ selected_len);
+ if (s->session->ext.alpn_selected == NULL) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ s->session->ext.alpn_selected_len = selected_len;
+ }
+ }
+
+ return 1;
+ } else if (r != SSL_TLSEXT_ERR_NOACK) {
+ *al = SSL_AD_NO_APPLICATION_PROTOCOL;
+ return 0;
+ }
+ /*
+ * If r == SSL_TLSEXT_ERR_NOACK then behave as if no callback was
+ * present.
+ */
+ }
+
+ /* Check ALPN is consistent with session */
+ if (s->session->ext.alpn_selected != NULL) {
+ /* Not consistent so can't be used for early_data */
+ s->ext.early_data_ok = 0;
+ }
+
+ return 1;
+}
+
WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst)
{
int al = SSL_AD_HANDSHAKE_FAILURE;
SSL_R_CLIENTHELLO_TLSEXT);
goto f_err;
}
+ /*
+ * Call alpn_select callback if needed. Has to be done after SNI and
+ * cipher negotiation (HTTP/2 restricts permitted ciphers). In TLSv1.3
+ * we already did this because cipher negotiation happens earlier, and
+ * we must handle ALPN before we decide whether to accept early_data.
+ */
+ if (!SSL_IS_TLS13(s) && !tls_handle_alpn(s, &al)) {
+ SSLerr(SSL_F_TLS_POST_PROCESS_CLIENT_HELLO,
+ SSL_R_CLIENTHELLO_TLSEXT);
+ goto f_err;
+ }
wst = WORK_MORE_C;
}
* fails. See https://tools.ietf.org/html/rfc5246#section-7.4.7.1
*/
- if (RAND_bytes(rand_premaster_secret, sizeof(rand_premaster_secret)) <= 0)
+ if (ssl_randbytes(s, rand_premaster_secret, sizeof(rand_premaster_secret)) <= 0)
goto err;
/*
MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
{
- int i, al = SSL_AD_INTERNAL_ERROR, ret = MSG_PROCESS_ERROR;
+ int i, al = SSL_AD_INTERNAL_ERROR;
+ MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR;
X509 *x = NULL;
unsigned long l, llen;
const unsigned char *certstart, *certbytes;
} age_add_u;
if (SSL_IS_TLS13(s)) {
- if (RAND_bytes(age_add_u.age_add_c, sizeof(age_add_u)) <= 0)
+ if (ssl_randbytes(s, age_add_u.age_add_c, sizeof(age_add_u)) <= 0)
goto err;
s->session->ext.tick_age_add = age_add_u.age_add;
/*
const EVP_CIPHER *cipher = EVP_aes_256_cbc();
iv_len = EVP_CIPHER_iv_length(cipher);
- if (RAND_bytes(iv, iv_len) <= 0)
+ if (ssl_randbytes(s, iv, iv_len) <= 0)
goto err;
if (!EVP_EncryptInit_ex(ctx, cipher, NULL,
tctx->ext.tick_aes_key, iv))
? 0 : s->session->timeout)
|| (SSL_IS_TLS13(s)
&& (!WPACKET_put_bytes_u32(pkt, age_add_u.age_add)
- /* ticket_nonce */
- || !WPACKET_start_sub_packet_u8(pkt)
- || !WPACKET_put_bytes_u8(pkt, 0)
- || !WPACKET_close(pkt)))
+ || !WPACKET_sub_memcpy_u8(pkt, s->session->ext.tick_nonce,
+ s->session->ext.tick_nonce_len)))
/* Now the actual ticket data */
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_get_total_written(pkt, &macoffset)