+
+ case SSL_TLSEXT_ERR_ALERT_WARNING:
+ *al = altmp;
+ return 1;
+
+ case SSL_TLSEXT_ERR_NOACK:
+ s->servername_done = 0;
+ return 1;
+
+ default:
+ return 1;
+ }
+}
+
+#ifndef OPENSSL_NO_EC
+static int final_ec_pt_formats(SSL *s, unsigned int context, int sent,
+ int *al)
+{
+ unsigned long alg_k, alg_a;
+
+ if (s->server)
+ return 1;
+
+ alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+ alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+
+ /*
+ * If we are client and using an elliptic curve cryptography cipher
+ * suite, then if server returns an EC point formats lists extension it
+ * must contain uncompressed.
+ */
+ if (s->ext.ecpointformats != NULL
+ && s->ext.ecpointformats_len > 0
+ && s->session->ext.ecpointformats != NULL
+ && s->session->ext.ecpointformats_len > 0
+ && ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA))) {
+ /* we are using an ECC cipher */
+ size_t i;
+ unsigned char *list = s->session->ext.ecpointformats;
+
+ for (i = 0; i < s->session->ext.ecpointformats_len; i++) {
+ if (*list++ == TLSEXT_ECPOINTFORMAT_uncompressed)
+ break;
+ }
+ if (i == s->session->ext.ecpointformats_len) {
+ SSLerr(SSL_F_FINAL_EC_PT_FORMATS,
+ SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+#endif
+
+static int init_session_ticket(SSL *s, unsigned int context)
+{
+ if (!s->server)
+ s->ext.ticket_expected = 0;
+
+ return 1;
+}
+
+#ifndef OPENSSL_NO_OCSP
+static int init_status_request(SSL *s, unsigned int context)
+{
+ if (s->server) {
+ s->ext.status_type = TLSEXT_STATUSTYPE_nothing;
+ } else {
+ /*
+ * Ensure we get sensible values passed to tlsext_status_cb in the event
+ * that we don't receive a status message
+ */
+ OPENSSL_free(s->ext.ocsp.resp);
+ s->ext.ocsp.resp = NULL;
+ s->ext.ocsp.resp_len = 0;
+ }
+
+ return 1;
+}
+#endif
+
+#ifndef OPENSSL_NO_NEXTPROTONEG
+static int init_npn(SSL *s, unsigned int context)
+{
+ s->s3->npn_seen = 0;
+
+ return 1;
+}
+#endif
+
+static int init_alpn(SSL *s, unsigned int context)
+{
+ OPENSSL_free(s->s3->alpn_selected);
+ s->s3->alpn_selected = NULL;
+ s->s3->alpn_selected_len = 0;
+ if (s->server) {
+ OPENSSL_free(s->s3->alpn_proposed);
+ s->s3->alpn_proposed = NULL;
+ s->s3->alpn_proposed_len = 0;
+ }
+ return 1;
+}
+
+static int final_alpn(SSL *s, unsigned int context, int sent, int *al)
+{
+ const unsigned char *selected = NULL;
+ unsigned char selected_len = 0;
+
+ if (!s->server)
+ return 1;
+
+ 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
+ } else {
+ *al = SSL_AD_NO_APPLICATION_PROTOCOL;
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int init_sig_algs(SSL *s, unsigned int context)
+{
+ /* Clear any signature algorithms extension received */
+ OPENSSL_free(s->s3->tmp.peer_sigalgs);
+ s->s3->tmp.peer_sigalgs = NULL;
+
+ return 1;
+}
+
+#ifndef OPENSSL_NO_SRP
+static int init_srp(SSL *s, unsigned int context)
+{
+ OPENSSL_free(s->srp_ctx.login);
+ s->srp_ctx.login = NULL;
+
+ return 1;
+}
+#endif
+
+static int init_etm(SSL *s, unsigned int context)
+{
+ s->ext.use_etm = 0;
+
+ return 1;
+}
+
+static int init_ems(SSL *s, unsigned int context)
+{
+ if (!s->server)
+ s->s3->flags &= ~TLS1_FLAGS_RECEIVED_EXTMS;
+
+ return 1;
+}
+
+static int final_ems(SSL *s, unsigned int context, int sent, int *al)
+{
+ if (!s->server && s->hit) {
+ /*
+ * Check extended master secret extension is consistent with
+ * original session.
+ */
+ if (!(s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) !=
+ !(s->session->flags & SSL_SESS_FLAG_EXTMS)) {
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_FINAL_EMS, SSL_R_INCONSISTENT_EXTMS);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int init_certificate_authorities(SSL *s, unsigned int context)
+{
+ sk_X509_NAME_pop_free(s->s3->tmp.peer_ca_names, X509_NAME_free);
+ s->s3->tmp.peer_ca_names = NULL;
+ return 1;
+}
+
+static int tls_construct_certificate_authorities(SSL *s, WPACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx, int *al)
+{
+ const STACK_OF(X509_NAME) *ca_sk = SSL_get0_CA_list(s);
+
+ if (ca_sk == NULL || sk_X509_NAME_num(ca_sk) == 0)
+ return 1;
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_certificate_authorities)
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !construct_ca_names(s, pkt)
+ || !WPACKET_close(pkt)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CERTIFICATE_AUTHORITIES,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+
+static int tls_parse_certificate_authorities(SSL *s, PACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx, int *al)
+{
+ if (!parse_ca_names(s, pkt, al))
+ return 0;
+ if (PACKET_remaining(pkt) != 0) {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+ return 1;
+}
+
+#ifndef OPENSSL_NO_SRTP
+static int init_srtp(SSL *s, unsigned int context)
+{
+ if (s->server)
+ s->srtp_profile = NULL;
+
+ return 1;
+}
+#endif
+
+static int final_sig_algs(SSL *s, unsigned int context, int sent, int *al)
+{
+ if (!sent && SSL_IS_TLS13(s)) {
+ *al = TLS13_AD_MISSING_EXTENSION;
+ SSLerr(SSL_F_FINAL_SIG_ALGS, SSL_R_MISSING_SIGALGS_EXTENSION);
+ return 0;
+ }
+
+ return 1;
+}
+
+#ifndef OPENSSL_NO_EC
+static int final_key_share(SSL *s, unsigned int context, int sent, int *al)
+{
+ if (!SSL_IS_TLS13(s))
+ return 1;
+
+ /*
+ * If
+ * we are a client
+ * AND
+ * we have no key_share
+ * AND
+ * (we are not resuming
+ * OR the kex_mode doesn't allow non key_share resumes)
+ * THEN
+ * fail;
+ */
+ if (!s->server
+ && !sent
+ && (!s->hit
+ || (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE) == 0)) {
+ /* Nothing left we can do - just fail */
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_FINAL_KEY_SHARE, SSL_R_NO_SUITABLE_KEY_SHARE);
+ return 0;
+ }
+ /*
+ * If
+ * we are a server
+ * AND
+ * we have no key_share
+ * THEN
+ * If
+ * we didn't already send a HelloRetryRequest
+ * AND
+ * the client sent a key_share extension
+ * AND
+ * (we are not resuming
+ * OR the kex_mode allows key_share resumes)
+ * AND
+ * a shared group exists
+ * THEN
+ * send a HelloRetryRequest
+ * ELSE If
+ * we are not resuming
+ * OR
+ * the kex_mode doesn't allow non key_share resumes
+ * THEN
+ * fail;
+ */
+ if (s->server && s->s3->peer_tmp == NULL) {
+ /* No suitable share */
+ if (s->hello_retry_request == 0 && sent
+ && (!s->hit
+ || (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE_DHE)
+ != 0)) {
+ const unsigned char *pcurves, *pcurvestmp, *clntcurves;
+ size_t num_curves, clnt_num_curves, i;
+ unsigned int group_id = 0;
+
+ /* Check if a shared group exists */
+
+ /* Get the clients list of supported groups. */
+ if (!tls1_get_curvelist(s, 1, &clntcurves, &clnt_num_curves)) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_FINAL_KEY_SHARE, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ /* Get our list of available groups */
+ if (!tls1_get_curvelist(s, 0, &pcurves, &num_curves)) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_FINAL_KEY_SHARE, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ /* Find the first group we allow that is also in client's list */
+ for (i = 0, pcurvestmp = pcurves; i < num_curves;
+ i++, pcurvestmp += 2) {
+ group_id = bytestogroup(pcurvestmp);
+
+ if (check_in_list(s, group_id, clntcurves, clnt_num_curves, 1))
+ break;
+ }
+
+ if (i < num_curves) {
+ /* A shared group exists so send a HelloRetryRequest */
+ s->s3->group_id = group_id;
+ s->hello_retry_request = 1;
+ return 1;
+ }
+ }
+ if (!s->hit
+ || (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE) == 0) {
+ /* Nothing left we can do - just fail */
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_FINAL_KEY_SHARE, SSL_R_NO_SUITABLE_KEY_SHARE);
+ return 0;
+ }
+ }
+
+ /* We have a key_share so don't send any more HelloRetryRequest messages */
+ if (s->server)
+ s->hello_retry_request = 0;
+
+ /*
+ * For a client side resumption with no key_share we need to generate
+ * the handshake secret (otherwise this is done during key_share
+ * processing).
+ */
+ if (!sent && !s->server && !tls13_generate_handshake_secret(s, NULL, 0)) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_FINAL_KEY_SHARE, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
+#endif
+
+static int init_psk_kex_modes(SSL *s, unsigned int context)
+{
+ s->ext.psk_kex_mode = TLSEXT_KEX_MODE_FLAG_NONE;
+ return 1;
+}
+
+int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
+ size_t binderoffset, const unsigned char *binderin,
+ unsigned char *binderout,
+ SSL_SESSION *sess, int sign)
+{
+ EVP_PKEY *mackey = NULL;
+ EVP_MD_CTX *mctx = NULL;
+ unsigned char hash[EVP_MAX_MD_SIZE], binderkey[EVP_MAX_MD_SIZE];
+ unsigned char finishedkey[EVP_MAX_MD_SIZE], tmpbinder[EVP_MAX_MD_SIZE];
+ const char resumption_label[] = "resumption psk binder key";
+ size_t bindersize, hashsize = EVP_MD_size(md);
+ int ret = -1;
+
+ /* Generate the early_secret */
+ if (!tls13_generate_secret(s, md, NULL, sess->master_key,
+ sess->master_key_length,
+ (unsigned char *)&s->early_secret)) {
+ SSLerr(SSL_F_TLS_PSK_DO_BINDER, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /*
+ * Create the handshake hash for the binder key...the messages so far are
+ * empty!
+ */
+ mctx = EVP_MD_CTX_new();
+ if (mctx == NULL
+ || EVP_DigestInit_ex(mctx, md, NULL) <= 0
+ || EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) {
+ SSLerr(SSL_F_TLS_PSK_DO_BINDER, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* Generate the binder key */
+ if (!tls13_hkdf_expand(s, md, s->early_secret,
+ (unsigned char *)resumption_label,
+ sizeof(resumption_label) - 1, hash, binderkey,
+ hashsize)) {
+ SSLerr(SSL_F_TLS_PSK_DO_BINDER, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* Generate the finished key */
+ if (!tls13_derive_finishedkey(s, md, binderkey, finishedkey, hashsize)) {
+ SSLerr(SSL_F_TLS_PSK_DO_BINDER, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (EVP_DigestInit_ex(mctx, md, NULL) <= 0) {
+ SSLerr(SSL_F_TLS_PSK_DO_BINDER, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /*
+ * Get a hash of the ClientHello up to the start of the binders. If we are
+ * following a HelloRetryRequest then this includes the hash of the first
+ * ClientHello and the HelloRetryRequest itself.
+ */
+ if (s->hello_retry_request) {
+ size_t hdatalen;
+ void *hdata;
+
+ hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
+ if (hdatalen <= 0) {
+ SSLerr(SSL_F_TLS_PSK_DO_BINDER, SSL_R_BAD_HANDSHAKE_LENGTH);
+ goto err;
+ }
+
+ /*
+ * For servers the handshake buffer data will include the second
+ * ClientHello - which we don't want - so we need to take that bit off.
+ */
+ if (s->server) {
+ PACKET hashprefix, msg;
+
+ /* Find how many bytes are left after the first two messages */
+ if (!PACKET_buf_init(&hashprefix, hdata, hdatalen)
+ || !PACKET_forward(&hashprefix, 1)
+ || !PACKET_get_length_prefixed_3(&hashprefix, &msg)
+ || !PACKET_forward(&hashprefix, 1)
+ || !PACKET_get_length_prefixed_3(&hashprefix, &msg)) {
+ SSLerr(SSL_F_TLS_PSK_DO_BINDER, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ hdatalen -= PACKET_remaining(&hashprefix);
+ }
+
+ if (EVP_DigestUpdate(mctx, hdata, hdatalen) <= 0) {
+ SSLerr(SSL_F_TLS_PSK_DO_BINDER, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ }
+
+ if (EVP_DigestUpdate(mctx, msgstart, binderoffset) <= 0
+ || EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) {
+ SSLerr(SSL_F_TLS_PSK_DO_BINDER, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ mackey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, finishedkey, hashsize);
+ if (mackey == NULL) {
+ SSLerr(SSL_F_TLS_PSK_DO_BINDER, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (!sign)
+ binderout = tmpbinder;
+
+ bindersize = hashsize;
+ if (EVP_DigestSignInit(mctx, NULL, md, NULL, mackey) <= 0
+ || EVP_DigestSignUpdate(mctx, hash, hashsize) <= 0
+ || EVP_DigestSignFinal(mctx, binderout, &bindersize) <= 0
+ || bindersize != hashsize) {
+ SSLerr(SSL_F_TLS_PSK_DO_BINDER, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (sign) {
+ ret = 1;
+ } else {
+ /* HMAC keys can't do EVP_DigestVerify* - use CRYPTO_memcmp instead */
+ ret = (CRYPTO_memcmp(binderin, binderout, hashsize) == 0);
+ }
+
+ err:
+ OPENSSL_cleanse(binderkey, sizeof(binderkey));
+ OPENSSL_cleanse(finishedkey, sizeof(finishedkey));
+ EVP_PKEY_free(mackey);
+ EVP_MD_CTX_free(mctx);
+
+ return ret;
+}
+
+static int final_early_data(SSL *s, unsigned int context, int sent, int *al)
+{
+ if (!s->server || !sent)
+ return 1;
+
+ if (s->max_early_data == 0
+ || !s->hit
+ || s->session->ext.tick_identity != 0
+ || s->early_data_state != SSL_EARLY_DATA_ACCEPTING
+ || !s->ext.early_data_ok
+ || s->hello_retry_request
+ || s->s3->alpn_selected_len != s->session->ext.alpn_selected_len
+ || (s->s3->alpn_selected_len > 0
+ && memcmp(s->s3->alpn_selected, s->session->ext.alpn_selected,
+ s->s3->alpn_selected_len) != 0)) {
+ s->ext.early_data = SSL_EARLY_DATA_REJECTED;
+ } else {
+ s->ext.early_data = SSL_EARLY_DATA_ACCEPTED;
+
+ if (!tls13_change_cipher_state(s,
+ SSL3_CC_EARLY | SSL3_CHANGE_CIPHER_SERVER_READ)) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }