/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
+ * Copyright 2005 Nokia. 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
* https://www.openssl.org/source/license.html
*/
-/* ====================================================================
- * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
- *
- * Portions of the attached software ("Contribution") are developed by
- * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
- *
- * The Contribution is licensed pursuant to the OpenSSL open source
- * license provided above.
- *
- * ECC cipher suite support in OpenSSL originally written by
- * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
- *
- */
-/* ====================================================================
- * Copyright 2005 Nokia. All rights reserved.
- *
- * The portions of the attached software ("Contribution") is developed by
- * Nokia Corporation and is licensed pursuant to the OpenSSL open source
- * license.
- *
- * The Contribution, originally written by Mika Kousa and Pasi Eronen of
- * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
- * support (see RFC 4279) to OpenSSL.
- *
- * No patent licenses or other rights except those expressly stated in
- * the OpenSSL open source license shall be deemed granted or received
- * expressly, by implication, estoppel, or otherwise.
- *
- * No assurances are provided by Nokia that the Contribution does not
- * infringe the patent or other intellectual property rights of any third
- * party or that the license provides you with all the necessary rights
- * to make use of the Contribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
- * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
- * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
- * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
- * OTHERWISE.
- */
-
#include <stdio.h>
#include "../ssl_locl.h"
#include "statem_locl.h"
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;
al = SSL_AD_HANDSHAKE_FAILURE;
goto err;
}
- if (s->hello_retry_request && s->s3->tmp.new_cipher != NULL
- && s->s3->tmp.new_cipher->id != cipher->id) {
+ if (s->hello_retry_request
+ && (s->s3->tmp.new_cipher == NULL
+ || s->s3->tmp.new_cipher->id != cipher->id)) {
/*
* A previous HRR picked a different ciphersuite to the one we
* just selected. Something must have changed.
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 early_data */
+ if (s->ext.early_data_ok
+ && (s->session->ext.alpn_selected == NULL
+ || selected_len != s->session->ext.alpn_selected_len
+ || memcmp(selected, s->session->ext.alpn_selected,
+ selected_len) != 0))
+ s->ext.early_data_ok = 0;
+
+ 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 early_data */
+ if (s->ext.early_data_ok && s->session->ext.alpn_selected != NULL)
+ 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;
}
/* not anonymous */
if (lu != NULL) {
EVP_PKEY *pkey = s->s3->tmp.cert->privatekey;
- const EVP_MD *md = ssl_md(lu->hash_idx);
- unsigned char *sigbytes1, *sigbytes2;
- size_t siglen;
+ const EVP_MD *md;
+ unsigned char *sigbytes1, *sigbytes2, *tbs;
+ size_t siglen, tbslen;
+ int rv;
- if (pkey == NULL || md == NULL) {
+ if (pkey == NULL || !tls1_lookup_md(lu, &md)) {
/* Should never happen */
al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
goto f_err;
}
}
- if (EVP_DigestSignUpdate(md_ctx, &(s->s3->client_random[0]),
- SSL3_RANDOM_SIZE) <= 0
- || EVP_DigestSignUpdate(md_ctx, &(s->s3->server_random[0]),
- SSL3_RANDOM_SIZE) <= 0
- || EVP_DigestSignUpdate(md_ctx,
- s->init_buf->data + paramoffset,
- paramlen) <= 0
- || EVP_DigestSignFinal(md_ctx, sigbytes1, &siglen) <= 0
- || !WPACKET_sub_allocate_bytes_u16(pkt, siglen, &sigbytes2)
+ tbslen = construct_key_exchange_tbs(s, &tbs,
+ s->init_buf->data + paramoffset,
+ paramlen);
+ if (tbslen == 0) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ ERR_R_MALLOC_FAILURE);
+ goto f_err;
+ }
+ rv = EVP_DigestSign(md_ctx, sigbytes1, &siglen, tbs, tbslen);
+ OPENSSL_free(tbs);
+ if (rv <= 0 || !WPACKET_sub_allocate_bytes_u16(pkt, siglen, &sigbytes2)
|| sigbytes1 != sigbytes2) {
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
* 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;
/*
} 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;
+ /*
+ * ticket_nonce is set to a single 0 byte because we only ever send a
+ * single ticket per connection. IMPORTANT: If we ever support multiple
+ * tickets per connection then this will need to be changed.
+ */
+ OPENSSL_free(s->session->ext.tick_nonce);
+ s->session->ext.tick_nonce = OPENSSL_zalloc(sizeof(char));
+ if (s->session->ext.tick_nonce == NULL) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ s->session->ext.tick_nonce_len = 1;
s->session->time = (long)time(NULL);
if (s->s3->alpn_selected != NULL) {
OPENSSL_free(s->session->ext.alpn_selected);
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))
(s->hit && !SSL_IS_TLS13(s))
? 0 : s->session->timeout)
|| (SSL_IS_TLS13(s)
- && !WPACKET_put_bytes_u32(pkt, age_add_u.age_add))
+ && (!WPACKET_put_bytes_u32(pkt, age_add_u.age_add)
+ || !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)