X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fstatem%2Fstatem_srvr.c;h=dfeba173a7ee32c1b5566a1d6b8d1c550e0fde21;hp=5651f6476d2dff9740827ea24e69af11f500ad48;hb=9d0a8bb71e3e411e9183e635122f17c1429c4116;hpb=c36001c3a89691e21dc4940425fc880c89c57ffc diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index 5651f6476d..dfeba173a7 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved * Copyright 2005 Nokia. All rights reserved. * @@ -13,6 +13,7 @@ #include "../ssl_locl.h" #include "statem_locl.h" #include "internal/constant_time_locl.h" +#include "internal/cryptlib.h" #include #include #include @@ -106,6 +107,13 @@ static int ossl_statem_server13_read_transition(SSL *s, int mt) */ if (s->early_data_state == SSL_EARLY_DATA_READING) break; + + if (mt == SSL3_MT_CERTIFICATE + && s->post_handshake_auth == SSL_PHA_REQUESTED) { + st->hand_state = TLS_ST_SR_CERT; + return 1; + } + if (mt == SSL3_MT_KEY_UPDATE) { st->hand_state = TLS_ST_SR_KEY_UPDATE; return 1; @@ -269,6 +277,20 @@ int ossl_statem_server_read_transition(SSL *s, int mt) err: /* No valid transition found */ + if (SSL_IS_DTLS(s) && mt == SSL3_MT_CHANGE_CIPHER_SPEC) { + BIO *rbio; + + /* + * CCS messages don't have a message sequence number so this is probably + * because of an out-of-order CCS. We'll just drop it. + */ + s->init_num = 0; + s->rwstate = SSL_READING; + rbio = SSL_get_rbio(s); + BIO_clear_retry_flags(rbio); + BIO_set_retry_read(rbio); + return 0; + } SSLfatal(s, SSL3_AD_UNEXPECTED_MESSAGE, SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION, SSL_R_UNEXPECTED_MESSAGE); @@ -324,16 +346,22 @@ static int send_server_key_exchange(SSL *s) * 1: Yes * 0: No */ -static int send_certificate_request(SSL *s) +int send_certificate_request(SSL *s) { if ( /* don't request cert unless asked for it: */ s->verify_mode & SSL_VERIFY_PEER + /* + * don't request if post-handshake-only unless doing + * post-handshake in TLSv1.3: + */ + && (!SSL_IS_TLS13(s) || !(s->verify_mode & SSL_VERIFY_POST_HANDSHAKE) + || s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) /* * if SSL_VERIFY_CLIENT_ONCE is set, don't request cert - * during re-negotiation: + * a second time: */ - && (s->s3->tmp.finish_md_len == 0 || + && (s->certreqs_sent < 1 || !(s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) /* * never request cert in anonymous ciphersuites (see @@ -387,6 +415,10 @@ static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s) st->hand_state = TLS_ST_SW_KEY_UPDATE; return WRITE_TRAN_CONTINUE; } + if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) { + st->hand_state = TLS_ST_SW_CERT_REQ; + return WRITE_TRAN_CONTINUE; + } /* Try to read from the client instead */ return WRITE_TRAN_FINISHED; @@ -422,7 +454,12 @@ static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s) return WRITE_TRAN_CONTINUE; case TLS_ST_SW_CERT_REQ: - st->hand_state = TLS_ST_SW_CERT; + if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) { + s->post_handshake_auth = SSL_PHA_REQUESTED; + st->hand_state = TLS_ST_OK; + } else { + st->hand_state = TLS_ST_SW_CERT; + } return WRITE_TRAN_CONTINUE; case TLS_ST_SW_CERT: @@ -443,13 +480,23 @@ static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s) case TLS_ST_SR_FINISHED: /* * Technically we have finished the handshake at this point, but we're - * going to remain "in_init" for now and write out the session ticket + * going to remain "in_init" for now and write out any session tickets * immediately. - * TODO(TLS1.3): Perhaps we need to be able to control this behaviour - * and give the application the opportunity to delay sending the - * session ticket? */ - st->hand_state = TLS_ST_SW_SESSION_TICKET; + if (s->post_handshake_auth == SSL_PHA_REQUESTED) { + s->post_handshake_auth = SSL_PHA_EXT_RECEIVED; + } else if (!s->ext.ticket_expected) { + /* + * If we're not going to renew the ticket then we just finish the + * handshake at this point. + */ + st->hand_state = TLS_ST_OK; + return WRITE_TRAN_CONTINUE; + } + if (s->num_tickets > s->sent_tickets) + st->hand_state = TLS_ST_SW_SESSION_TICKET; + else + st->hand_state = TLS_ST_OK; return WRITE_TRAN_CONTINUE; case TLS_ST_SR_KEY_UPDATE: @@ -461,7 +508,14 @@ static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s) case TLS_ST_SW_KEY_UPDATE: case TLS_ST_SW_SESSION_TICKET: - st->hand_state = TLS_ST_OK; + /* In a resumption we only ever send a maximum of one new ticket. + * Following an initial handshake we send the number of tickets we have + * been configured for. + */ + if (s->hit || s->num_tickets <= s->sent_tickets) { + /* We've written enough tickets out. */ + st->hand_state = TLS_ST_OK; + } return WRITE_TRAN_CONTINUE; } } @@ -514,10 +568,15 @@ WRITE_TRAN ossl_statem_server_write_transition(SSL *s) case TLS_ST_SR_CLNT_HELLO: if (SSL_IS_DTLS(s) && !s->d1->cookie_verified - && (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)) + && (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)) { st->hand_state = DTLS_ST_SW_HELLO_VERIFY_REQUEST; - else + } else if (s->renegotiate == 0 && !SSL_IS_FIRST_HANDSHAKE(s)) { + /* We must have rejected the renegotiation */ + st->hand_state = TLS_ST_OK; + return WRITE_TRAN_CONTINUE; + } else { st->hand_state = TLS_ST_SW_SRVR_HELLO; + } return WRITE_TRAN_CONTINUE; case DTLS_ST_SW_HELLO_VERIFY_REQUEST: @@ -857,6 +916,13 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst) } break; + case TLS_ST_SW_CERT_REQ: + if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) { + if (statem_flush(s) != 1) + return WORK_MORE_A; + } + break; + case TLS_ST_SW_KEY_UPDATE: if (statem_flush(s) != 1) return WORK_MORE_A; @@ -1113,7 +1179,6 @@ WORK_STATE ossl_statem_server_post_process_message(SSL *s, WORK_STATE wst) case TLS_ST_SR_KEY_EXCH: return tls_post_process_client_key_exchange(s, wst); } - return WORK_FINISHED_CONTINUE; } #ifndef OPENSSL_NO_SRP @@ -1254,24 +1319,33 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt) /* |cookie| will only be initialized for DTLS. */ PACKET session_id, compression, extensions, cookie; static const unsigned char null_compression = 0; - CLIENTHELLO_MSG *clienthello; + CLIENTHELLO_MSG *clienthello = NULL; - clienthello = OPENSSL_zalloc(sizeof(*clienthello)); - if (clienthello == NULL) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO, - ERR_R_INTERNAL_ERROR); - goto err; - } /* Check if this is actually an unexpected renegotiation ClientHello */ if (s->renegotiate == 0 && !SSL_IS_FIRST_HANDSHAKE(s)) { - if ((s->options & SSL_OP_NO_RENEGOTIATION)) { - ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION); + if (!ossl_assert(!SSL_IS_TLS13(s))) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO, + ERR_R_INTERNAL_ERROR); goto err; } + if ((s->options & SSL_OP_NO_RENEGOTIATION) != 0 + || (!s->s3->send_connection_binding + && (s->options + & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) == 0)) { + ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION); + return MSG_PROCESS_FINISHED_READING; + } s->renegotiate = 1; s->new_session = 1; } + clienthello = OPENSSL_zalloc(sizeof(*clienthello)); + if (clienthello == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO, + ERR_R_INTERNAL_ERROR); + goto err; + } + /* * First, parse the raw ClientHello data into the CLIENTHELLO_MSG structure. */ @@ -2055,7 +2129,17 @@ int tls_handle_alpn(SSL *s) s->ext.early_data_ok = 0; if (!s->hit) { - /* If a new session update it with the new ALPN value */ + /* + * This is a new session and so alpn_selected should have + * been initialised to NULL. We should update it with the + * selected ALPN. + */ + if (!ossl_assert(s->session->ext.alpn_selected == NULL)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_HANDLE_ALPN, + ERR_R_INTERNAL_ERROR); + return 0; + } s->session->ext.alpn_selected = OPENSSL_memdup(selected, selected_len); if (s->session->ext.alpn_selected == NULL) { @@ -2426,6 +2510,12 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt) } dh = EVP_PKEY_get0_DH(s->s3->tmp.pkey); + if (dh == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto err; + } EVP_PKEY_free(pkdh); pkdh = NULL; @@ -2687,12 +2777,30 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt) int tls_construct_certificate_request(SSL *s, WPACKET *pkt) { if (SSL_IS_TLS13(s)) { - /* TODO(TLS1.3) for now send empty request context */ - if (!WPACKET_put_bytes_u8(pkt, 0)) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, - SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, - ERR_R_INTERNAL_ERROR); - return 0; + /* Send random context when doing post-handshake auth */ + if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) { + OPENSSL_free(s->pha_context); + s->pha_context_len = 32; + if ((s->pha_context = OPENSSL_malloc(s->pha_context_len)) == NULL + || RAND_bytes(s->pha_context, s->pha_context_len) <= 0 + || !WPACKET_sub_memcpy_u8(pkt, s->pha_context, s->pha_context_len)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, + ERR_R_INTERNAL_ERROR); + return 0; + } + /* reset the handshake hash back to just after the ClientFinished */ + if (!tls13_restore_handshake_digest_for_pha(s)) { + /* SSLfatal() already called */ + return 0; + } + } else { + if (!WPACKET_put_bytes_u8(pkt, 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, + ERR_R_INTERNAL_ERROR); + return 0; + } } if (!tls_construct_extensions(s, pkt, @@ -2733,6 +2841,7 @@ int tls_construct_certificate_request(SSL *s, WPACKET *pkt) } done: + s->certreqs_sent++; s->s3->tmp.cert_request = 1; return 1; } @@ -2862,7 +2971,7 @@ static int tls_process_cke_rsa(SSL *s, PACKET *pkt) * fails. See https://tools.ietf.org/html/rfc5246#section-7.4.7.1 */ - if (ssl_randbytes(s, rand_premaster_secret, + if (RAND_priv_bytes(rand_premaster_secret, sizeof(rand_premaster_secret)) <= 0) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA, ERR_R_INTERNAL_ERROR); @@ -3159,11 +3268,9 @@ static int tls_process_cke_gost(SSL *s, PACKET *pkt) const unsigned char *start; size_t outlen = 32, inlen; unsigned long alg_a; - int Ttag, Tclass; - long Tlen; - size_t sess_key_len; - const unsigned char *data; + unsigned int asn1id, asn1len; int ret = 0; + PACKET encdata; /* Get our certificate private key */ alg_a = s->s3->tmp.new_cipher->algorithm_auth; @@ -3205,22 +3312,42 @@ static int tls_process_cke_gost(SSL *s, PACKET *pkt) ERR_clear_error(); } /* Decrypt session key */ - sess_key_len = PACKET_remaining(pkt); - if (!PACKET_get_bytes(pkt, &data, sess_key_len)) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST, - ERR_R_INTERNAL_ERROR); + if (!PACKET_get_1(pkt, &asn1id) + || asn1id != (V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED) + || !PACKET_peek_1(pkt, &asn1len)) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST, + SSL_R_DECRYPTION_FAILED); goto err; } - /* TODO(size_t): Convert this function */ - if (ASN1_get_object((const unsigned char **)&data, &Tlen, &Ttag, - &Tclass, (long)sess_key_len) != V_ASN1_CONSTRUCTED - || Ttag != V_ASN1_SEQUENCE || Tclass != V_ASN1_UNIVERSAL) { + if (asn1len == 0x81) { + /* + * Long form length. Should only be one byte of length. Anything else + * isn't supported. + * We did a successful peek before so this shouldn't fail + */ + if (!PACKET_forward(pkt, 1)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST, + SSL_R_DECRYPTION_FAILED); + goto err; + } + } else if (asn1len >= 0x80) { + /* + * Indefinite length, or more than one long form length bytes. We don't + * support it + */ + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST, + SSL_R_DECRYPTION_FAILED); + goto err; + } /* else short form length */ + + if (!PACKET_as_length_prefixed_1(pkt, &encdata)) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST, SSL_R_DECRYPTION_FAILED); goto err; } - start = data; - inlen = Tlen; + inlen = PACKET_remaining(&encdata); + start = PACKET_data(&encdata); + if (EVP_PKEY_decrypt(pkey_ctx, premaster_secret, &outlen, start, inlen) <= 0) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST, @@ -3381,11 +3508,12 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt) int i; MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR; X509 *x = NULL; - unsigned long l, llen; + unsigned long l; const unsigned char *certstart, *certbytes; STACK_OF(X509) *sk = NULL; PACKET spkt, context; size_t chainidx; + SSL_SESSION *new_sess = NULL; if ((sk = sk_X509_new_null()) == NULL) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, @@ -3393,10 +3521,16 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt) goto err; } - /* TODO(TLS1.3): For now we ignore the context. We need to verify this */ - if ((SSL_IS_TLS13(s) && !PACKET_get_length_prefixed_1(pkt, &context)) - || !PACKET_get_net_3(pkt, &llen) - || !PACKET_get_sub_packet(pkt, &spkt, llen) + if (SSL_IS_TLS13(s) && (!PACKET_get_length_prefixed_1(pkt, &context) + || (s->pha_context == NULL && PACKET_remaining(&context) != 0) + || (s->pha_context != NULL && + !PACKET_equal(&context, s->pha_context, s->pha_context_len)))) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, + SSL_R_INVALID_CONTEXT); + goto err; + } + + if (!PACKET_get_length_prefixed_3(pkt, &spkt) || PACKET_remaining(pkt) != 0) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, SSL_R_LENGTH_MISMATCH); @@ -3482,7 +3616,7 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt) EVP_PKEY *pkey; i = ssl_verify_cert_chain(s, sk); if (i <= 0) { - SSLfatal(s, ssl_verify_alarm_type(s->verify_result), + SSLfatal(s, ssl_x509err2alert(s->verify_result), SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, SSL_R_CERTIFICATE_VERIFY_FAILED); goto err; @@ -3501,6 +3635,35 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt) } } + /* + * Sessions must be immutable once they go into the session cache. Otherwise + * we can get multi-thread problems. Therefore we don't "update" sessions, + * we replace them with a duplicate. Here, we need to do this every time + * a new certificate is received via post-handshake authentication, as the + * session may have already gone into the session cache. + */ + + if (s->post_handshake_auth == SSL_PHA_REQUESTED) { + int m = s->session_ctx->session_cache_mode; + + if ((new_sess = ssl_session_dup(s->session, 0)) == 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, + ERR_R_MALLOC_FAILURE); + goto err; + } + + if (m & SSL_SESS_CACHE_SERVER) { + /* + * Remove the old session from the cache. We carry on if this fails + */ + SSL_CTX_remove_session(s->session_ctx, s->session); + } + + SSL_SESSION_free(s->session); + s->session = new_sess; + } + X509_free(s->session->peer); s->session->peer = sk_X509_shift(sk); s->session->verify_result = s->verify_result; @@ -3588,7 +3751,48 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt) } age_add_u; if (SSL_IS_TLS13(s)) { - if (ssl_randbytes(s, age_add_u.age_add_c, sizeof(age_add_u)) <= 0) { + void (*cb) (const SSL *ssl, int type, int val) = NULL; + + if (s->info_callback != NULL) + cb = s->info_callback; + else if (s->ctx->info_callback != NULL) + cb = s->ctx->info_callback; + + + if (cb != NULL) { + /* + * We don't start and stop the handshake in between each ticket when + * sending more than one - but it should appear that way to the info + * callback. + */ + if (s->sent_tickets != 0) { + ossl_statem_set_in_init(s, 0); + cb(s, SSL_CB_HANDSHAKE_DONE, 1); + ossl_statem_set_in_init(s, 1); + } + cb(s, SSL_CB_HANDSHAKE_START, 1); + } + /* + * If we already sent one NewSessionTicket then we need to take a copy + * of it and create a new session from it. + */ + if (s->sent_tickets != 0) { + SSL_SESSION *new_sess = ssl_session_dup(s->session, 0); + + if (new_sess == NULL) { + /* SSLfatal already called */ + goto err; + } + + SSL_SESSION_free(s->session); + s->session = new_sess; + } + + if (!ssl_generate_session_id(s, s->session)) { + /* SSLfatal() already called */ + goto err; + } + if (RAND_bytes(age_add_u.age_add_c, sizeof(age_add_u)) <= 0) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR); @@ -3625,6 +3829,10 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt) s->session->ext.max_early_data = s->max_early_data; } + if (tctx->generate_ticket_cb != NULL && + tctx->generate_ticket_cb(s, tctx->ticket_cb_data) == 0) + goto err; + /* get session encoding length */ slen_full = i2d_SSL_SESSION(s->session, NULL); /* @@ -3668,7 +3876,6 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt) SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR); goto err; } - sess->session_id_length = 0; /* ID is irrelevant for the ticket */ slen = i2d_SSL_SESSION(sess, NULL); if (slen == 0 || slen > slen_full) { @@ -3722,11 +3929,11 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt) const EVP_CIPHER *cipher = EVP_aes_256_cbc(); iv_len = EVP_CIPHER_iv_length(cipher); - if (ssl_randbytes(s, iv, iv_len) <= 0 + if (RAND_bytes(iv, iv_len) <= 0 || !EVP_EncryptInit_ex(ctx, cipher, NULL, - tctx->ext.tick_aes_key, iv) - || !HMAC_Init_ex(hctx, tctx->ext.tick_hmac_key, - sizeof(tctx->ext.tick_hmac_key), + tctx->ext.secure->tick_aes_key, iv) + || !HMAC_Init_ex(hctx, tctx->ext.secure->tick_hmac_key, + sizeof(tctx->ext.secure->tick_hmac_key), EVP_sha256(), NULL)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, @@ -3781,12 +3988,15 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt) SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR); goto err; } - if (SSL_IS_TLS13(s) - && !tls_construct_extensions(s, pkt, - SSL_EXT_TLS1_3_NEW_SESSION_TICKET, - NULL, 0)) { - /* SSLfatal() already called */ - goto err; + if (SSL_IS_TLS13(s)) { + ssl_update_cache(s, SSL_SESS_CACHE_SERVER); + if (!tls_construct_extensions(s, pkt, + SSL_EXT_TLS1_3_NEW_SESSION_TICKET, + NULL, 0)) { + /* SSLfatal() already called */ + goto err; + } + s->sent_tickets++; } EVP_CIPHER_CTX_free(ctx); HMAC_CTX_free(hctx);