[openssl-commits] [openssl] master update

Matt Caswell matt at openssl.org
Mon Dec 4 13:44:31 UTC 2017


The branch master has been updated
       via  dd5a4279f9be3988023a72c7f840aa2690c264f3 (commit)
       via  e7d961e994620dd5dee6d80794a07fb9de1bab66 (commit)
       via  8e7677aeacea0657846df444553680fdd3391f8c (commit)
       via  8e02e73d80d44d31fbfbb757c8cbd5dad7cd311e (commit)
       via  29bfd5b79a1ec2be8bea307ffb50810fce11915c (commit)
       via  f9f674eb76a7c00e3f158f673a7ec01286b02907 (commit)
       via  47e2ee072290db534720565318f0a8110a2e7d92 (commit)
       via  635c8f771574fbf48281b2372a2f7aba0c673544 (commit)
       via  d273b60b41d88cad8d2fcf66e3e85057bbb67706 (commit)
       via  d4d2f3a4c14113c20eaa9350cbbf32cfb3e4f10c (commit)
       via  3ec8d113a59162a8ae9020d4f8a501ac2f33d744 (commit)
       via  a2c2e000509131b629b5cde0ce121ea6436bc23e (commit)
       via  f63a17d66dec01c123630682e0b20450b34c086a (commit)
       via  4752c5deb20cae92a7146c4b89ad41045a041970 (commit)
       via  1f359471f9eebab29fe2b0e8bf0e0f7b93f3bc26 (commit)
      from  1e2804f25c80136c33f3508adb54b24106b6b6f6 (commit)


- Log -----------------------------------------------------------------
commit dd5a4279f9be3988023a72c7f840aa2690c264f3
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Dec 4 13:37:01 2017 +0000

    Fix some formatting nits
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/4778)

commit e7d961e994620dd5dee6d80794a07fb9de1bab66
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Nov 27 11:41:26 2017 +0000

    Remove spurious whitespace
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/4778)

commit 8e7677aeacea0657846df444553680fdd3391f8c
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Nov 27 11:34:05 2017 +0000

    Update an error reason code to be ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
    
    The most likely explanation for us ending up at this point in the code
    is that we were called by the user application incorrectly - so use an
    appropriate error code.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/4778)

commit 8e02e73d80d44d31fbfbb757c8cbd5dad7cd311e
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Nov 23 14:35:19 2017 +0000

    Fix the Boring tests following the SSLfatal() changes
    
    An error reason code has changed for one of the boring tests, so
    ossl_config.json needed an update to take account of it.
    
    [extended tests]
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/4778)

commit 29bfd5b79a1ec2be8bea307ffb50810fce11915c
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Nov 23 13:11:42 2017 +0000

    Add some more cleanups
    
    Follow up from the conversion to use SSLfatal() in the state machine to
    clean things up a bit more.
    
    [extended tests]
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/4778)

commit f9f674eb76a7c00e3f158f673a7ec01286b02907
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Nov 23 12:33:11 2017 +0000

    Assert that SSLfatal() only gets called once
    
    We shouldn't call SSLfatal() multiple times for the same error condition.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/4778)

commit 47e2ee072290db534720565318f0a8110a2e7d92
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Nov 23 12:10:54 2017 +0000

    Add some sanity checks for the fatal error condition
    
    Sometimes at the top level of the state machine code we know we are
    supposed to be in a fatal error condition. This commit adds some sanity
    checks to ensure that SSLfatal() has been called.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/4778)

commit 635c8f771574fbf48281b2372a2f7aba0c673544
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Nov 23 11:41:40 2017 +0000

    Fix up a few places in the state machine that got missed with SSLfatal()
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/4778)

commit d273b60b41d88cad8d2fcf66e3e85057bbb67706
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Nov 23 11:19:34 2017 +0000

    Convert more functions in ssl/statem/statem_dtls.c to use SSLfatal()
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/4778)

commit d4d2f3a4c14113c20eaa9350cbbf32cfb3e4f10c
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Nov 23 10:37:51 2017 +0000

    Convert more functions in ssl/statem/statem.c to use SSLfatal()
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/4778)

commit 3ec8d113a59162a8ae9020d4f8a501ac2f33d744
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Nov 22 17:43:20 2017 +0000

    Convert remaining functions in statem_srvr.c to use SSLfatal()
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/4778)

commit a2c2e000509131b629b5cde0ce121ea6436bc23e
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Nov 22 17:18:39 2017 +0000

    Convert remaining functions in statem_clnt.c to use SSLfatal()
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/4778)

commit f63a17d66dec01c123630682e0b20450b34c086a
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Nov 21 17:18:43 2017 +0000

    Convert the state machine code to use SSLfatal()
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/4778)

commit 4752c5deb20cae92a7146c4b89ad41045a041970
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Nov 23 16:25:05 2017 +0000

    Replace some usage of SSLerr with SSLfatal()
    
    This is an initial step towards using SSLfatal() everywhere. Initially in
    this commit and in subsequent commits we focus on the state machine code.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/4778)

commit 1f359471f9eebab29fe2b0e8bf0e0f7b93f3bc26
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Nov 23 16:21:46 2017 +0000

    Provide an SSLfatal() macro
    
    Typically if a fatal error occurs three things need to happen:
    
    - Put an error on the error queue
    - Send an alert
    - Put the state machine into the error state
    
    Although all 3 of these things need to be done every time we hit a fatal
    error the responsibilities for doing this are distributed throughout the
    code. The place where the error goes on the queue, where the alert gets
    sent and where the state machine goes into the error state are almost
    invariably different. It has been a common pattern to pass alert codes up
    and down the stack to get the alert information from the point in the code
    where the error is detected to the point in the code where the alert gets
    sent.
    
    This commit provides an SSLfatal() macro (backed by an ossl_statem_fatal
    function) that does all 3 of the above error tasks. This is largely a drop
    in replacement for SSLerr, but takes a couple of extra parameters (the SSL
    object, and an alert code).
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/4778)

-----------------------------------------------------------------------

Summary of changes:
 crypto/err/openssl.txt          |   72 +++
 include/openssl/sslerr.h        |   66 +++
 ssl/record/rec_layer_d1.c       |   12 +-
 ssl/record/ssl3_buffer.c        |   12 +-
 ssl/s3_enc.c                    |  163 ++++--
 ssl/s3_lib.c                    |   50 +-
 ssl/ssl_err.c                   |  112 ++++
 ssl/ssl_lib.c                   |   96 ++--
 ssl/ssl_locl.h                  |   22 +-
 ssl/ssl_sess.c                  |   46 +-
 ssl/statem/extensions.c         |  316 ++++++-----
 ssl/statem/extensions_clnt.c    |  506 ++++++++++-------
 ssl/statem/extensions_cust.c    |   30 +-
 ssl/statem/extensions_srvr.c    |  362 +++++++-----
 ssl/statem/statem.c             |  104 +++-
 ssl/statem/statem.h             |   11 +-
 ssl/statem/statem_clnt.c        | 1179 ++++++++++++++++++++------------------
 ssl/statem/statem_dtls.c        |   91 +--
 ssl/statem/statem_lib.c         |  547 +++++++++---------
 ssl/statem/statem_locl.h        |  164 +++---
 ssl/statem/statem_srvr.c        | 1194 +++++++++++++++++++++------------------
 ssl/t1_enc.c                    |  183 +++---
 ssl/t1_lib.c                    |   89 +--
 ssl/tls13_enc.c                 |   79 ++-
 ssl/tls_srp.c                   |   60 +-
 test/ossl_shim/ossl_config.json |    2 +-
 test/tls13secretstest.c         |    5 +
 27 files changed, 3259 insertions(+), 2314 deletions(-)

diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index 23c32fb..932fc46 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -965,9 +965,13 @@ SSL_F_ADD_CLIENT_KEY_SHARE_EXT:438:*
 SSL_F_ADD_KEY_SHARE:512:add_key_share
 SSL_F_BYTES_TO_CIPHER_LIST:519:bytes_to_cipher_list
 SSL_F_CHECK_SUITEB_CIPHER_LIST:331:check_suiteb_cipher_list
+SSL_F_CONSTRUCT_CA_NAMES:552:construct_ca_names
+SSL_F_CONSTRUCT_KEY_EXCHANGE_TBS:553:construct_key_exchange_tbs
 SSL_F_CREATE_SYNTHETIC_MESSAGE_HASH:539:create_synthetic_message_hash
 SSL_F_CT_MOVE_SCTS:345:ct_move_scts
 SSL_F_CT_STRICT:349:ct_strict
+SSL_F_CUSTOM_EXT_ADD:554:custom_ext_add
+SSL_F_CUSTOM_EXT_PARSE:555:custom_ext_parse
 SSL_F_D2I_SSL_SESSION:103:d2i_SSL_SESSION
 SSL_F_DANE_CTX_ENABLE:347:dane_ctx_enable
 SSL_F_DANE_MTYPE_SET:393:dane_mtype_set
@@ -992,24 +996,47 @@ SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST:385:\
 	dtls_construct_hello_verify_request
 SSL_F_DTLS_GET_REASSEMBLED_MESSAGE:370:dtls_get_reassembled_message
 SSL_F_DTLS_PROCESS_HELLO_VERIFY:386:dtls_process_hello_verify
+SSL_F_DTLS_WAIT_FOR_DRY:592:dtls_wait_for_dry
 SSL_F_EARLY_DATA_COUNT_OK:532:early_data_count_ok
+SSL_F_FINAL_EARLY_DATA:556:final_early_data
 SSL_F_FINAL_EC_PT_FORMATS:485:final_ec_pt_formats
 SSL_F_FINAL_EMS:486:final_ems
 SSL_F_FINAL_KEY_SHARE:503:final_key_share
+SSL_F_FINAL_MAXFRAGMENTLEN:557:final_maxfragmentlen
 SSL_F_FINAL_RENEGOTIATE:483:final_renegotiate
+SSL_F_FINAL_SERVER_NAME:558:final_server_name
 SSL_F_FINAL_SIG_ALGS:497:final_sig_algs
+SSL_F_GET_CERT_VERIFY_TBS_DATA:588:get_cert_verify_tbs_data
 SSL_F_NSS_KEYLOG_INT:500:nss_keylog_int
 SSL_F_OPENSSL_INIT_SSL:342:OPENSSL_init_ssl
 SSL_F_OSSL_STATEM_CLIENT13_READ_TRANSITION:436:*
+SSL_F_OSSL_STATEM_CLIENT13_WRITE_TRANSITION:598:\
+	ossl_statem_client13_write_transition
 SSL_F_OSSL_STATEM_CLIENT_CONSTRUCT_MESSAGE:430:*
+SSL_F_OSSL_STATEM_CLIENT_POST_PROCESS_MESSAGE:593:\
+	ossl_statem_client_post_process_message
+SSL_F_OSSL_STATEM_CLIENT_PROCESS_MESSAGE:594:ossl_statem_client_process_message
 SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION:417:ossl_statem_client_read_transition
+SSL_F_OSSL_STATEM_CLIENT_WRITE_TRANSITION:599:\
+	ossl_statem_client_write_transition
 SSL_F_OSSL_STATEM_SERVER13_READ_TRANSITION:437:*
+SSL_F_OSSL_STATEM_SERVER13_WRITE_TRANSITION:600:\
+	ossl_statem_server13_write_transition
 SSL_F_OSSL_STATEM_SERVER_CONSTRUCT_MESSAGE:431:*
+SSL_F_OSSL_STATEM_SERVER_POST_PROCESS_MESSAGE:601:\
+	ossl_statem_server_post_process_message
+SSL_F_OSSL_STATEM_SERVER_POST_WORK:602:ossl_statem_server_post_work
+SSL_F_OSSL_STATEM_SERVER_PROCESS_MESSAGE:603:ossl_statem_server_process_message
 SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION:418:ossl_statem_server_read_transition
+SSL_F_OSSL_STATEM_SERVER_WRITE_TRANSITION:604:\
+	ossl_statem_server_write_transition
 SSL_F_PARSE_CA_NAMES:541:parse_ca_names
 SSL_F_PROCESS_KEY_SHARE_EXT:439:*
 SSL_F_READ_STATE_MACHINE:352:read_state_machine
 SSL_F_SET_CLIENT_CIPHERSUITE:540:set_client_ciphersuite
+SSL_F_SRP_GENERATE_CLIENT_MASTER_SECRET:595:srp_generate_client_master_secret
+SSL_F_SRP_GENERATE_SERVER_MASTER_SECRET:589:srp_generate_server_master_secret
+SSL_F_SRP_VERIFY_SERVER_PARAM:596:srp_verify_server_param
 SSL_F_SSL3_CHANGE_CIPHER_STATE:129:ssl3_change_cipher_state
 SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM:130:ssl3_check_cert_and_algorithm
 SSL_F_SSL3_CTRL:213:ssl3_ctrl
@@ -1017,6 +1044,7 @@ SSL_F_SSL3_CTX_CTRL:133:ssl3_ctx_ctrl
 SSL_F_SSL3_DIGEST_CACHED_RECORDS:293:ssl3_digest_cached_records
 SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC:292:ssl3_do_change_cipher_spec
 SSL_F_SSL3_FINAL_FINISH_MAC:285:ssl3_final_finish_mac
+SSL_F_SSL3_FINISH_MAC:587:ssl3_finish_mac
 SSL_F_SSL3_GENERATE_KEY_BLOCK:238:ssl3_generate_key_block
 SSL_F_SSL3_GENERATE_MASTER_SECRET:388:ssl3_generate_master_secret
 SSL_F_SSL3_GET_RECORD:143:ssl3_get_record
@@ -1051,7 +1079,9 @@ SSL_F_SSL_CERT_NEW:162:ssl_cert_new
 SSL_F_SSL_CERT_SET0_CHAIN:340:ssl_cert_set0_chain
 SSL_F_SSL_CHECK_PRIVATE_KEY:163:SSL_check_private_key
 SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT:280:*
+SSL_F_SSL_CHECK_SRP_EXT_CLIENTHELLO:606:ssl_check_srp_ext_ClientHello
 SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG:279:ssl_check_srvr_ecc_cert_and_alg
+SSL_F_SSL_CHOOSE_CLIENT_VERSION:607:ssl_choose_client_version
 SSL_F_SSL_CIPHER_LIST_TO_BYTES:425:ssl_cipher_list_to_bytes
 SSL_F_SSL_CIPHER_PROCESS_RULESTR:230:ssl_cipher_process_rulestr
 SSL_F_SSL_CIPHER_STRENGTH_SORT:231:ssl_cipher_strength_sort
@@ -1087,15 +1117,18 @@ SSL_F_SSL_CTX_USE_SERVERINFO_EX:543:SSL_CTX_use_serverinfo_ex
 SSL_F_SSL_CTX_USE_SERVERINFO_FILE:337:SSL_CTX_use_serverinfo_file
 SSL_F_SSL_DANE_DUP:403:ssl_dane_dup
 SSL_F_SSL_DANE_ENABLE:395:SSL_dane_enable
+SSL_F_SSL_DERIVE:590:ssl_derive
 SSL_F_SSL_DO_CONFIG:391:ssl_do_config
 SSL_F_SSL_DO_HANDSHAKE:180:SSL_do_handshake
 SSL_F_SSL_DUP_CA_LIST:408:SSL_dup_CA_list
 SSL_F_SSL_ENABLE_CT:402:SSL_enable_ct
+SSL_F_SSL_GENERATE_PKEY_GROUP:559:ssl_generate_pkey_group
 SSL_F_SSL_GENERATE_SESSION_ID:547:ssl_generate_session_id
 SSL_F_SSL_GET_NEW_SESSION:181:ssl_get_new_session
 SSL_F_SSL_GET_PREV_SESSION:217:ssl_get_prev_session
 SSL_F_SSL_GET_SERVER_CERT_INDEX:322:*
 SSL_F_SSL_GET_SIGN_PKEY:183:*
+SSL_F_SSL_HANDSHAKE_HASH:560:ssl_handshake_hash
 SSL_F_SSL_INIT_WBIO_BUFFER:184:ssl_init_wbio_buffer
 SSL_F_SSL_KEY_UPDATE:515:SSL_key_update
 SSL_F_SSL_LOAD_CLIENT_CA_FILE:185:SSL_load_client_CA_file
@@ -1103,6 +1136,7 @@ SSL_F_SSL_LOG_MASTER_SECRET:498:*
 SSL_F_SSL_LOG_RSA_CLIENT_KEY_EXCHANGE:499:ssl_log_rsa_client_key_exchange
 SSL_F_SSL_MODULE_INIT:392:ssl_module_init
 SSL_F_SSL_NEW:186:SSL_new
+SSL_F_SSL_NEXT_PROTO_VALIDATE:565:ssl_next_proto_validate
 SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT:300:*
 SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT:302:*
 SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT:310:*
@@ -1163,6 +1197,9 @@ SSL_F_STATE_MACHINE:353:state_machine
 SSL_F_TLS12_CHECK_PEER_SIGALG:333:tls12_check_peer_sigalg
 SSL_F_TLS12_COPY_SIGALGS:533:tls12_copy_sigalgs
 SSL_F_TLS13_CHANGE_CIPHER_STATE:440:tls13_change_cipher_state
+SSL_F_TLS13_FINAL_FINISH_MAC:605:tls13_final_finish_mac
+SSL_F_TLS13_GENERATE_SECRET:591:tls13_generate_secret
+SSL_F_TLS13_HKDF_EXPAND:561:tls13_hkdf_expand
 SSL_F_TLS13_SETUP_KEY_BLOCK:441:tls13_setup_key_block
 SSL_F_TLS1_CHANGE_CIPHER_STATE:209:tls1_change_cipher_state
 SSL_F_TLS1_CHECK_DUPLICATE_EXTENSIONS:341:*
@@ -1256,19 +1293,43 @@ SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS:544:\
 SSL_F_TLS_CONSTRUCT_STOC_USE_SRTP:462:tls_construct_stoc_use_srtp
 SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO:521:\
 	tls_early_post_process_client_hello
+SSL_F_TLS_FINISH_HANDSHAKE:597:tls_finish_handshake
 SSL_F_TLS_GET_MESSAGE_BODY:351:tls_get_message_body
 SSL_F_TLS_GET_MESSAGE_HEADER:387:tls_get_message_header
+SSL_F_TLS_HANDLE_ALPN:562:tls_handle_alpn
+SSL_F_TLS_HANDLE_STATUS_REQUEST:563:tls_handle_status_request
+SSL_F_TLS_PARSE_CERTIFICATE_AUTHORITIES:566:tls_parse_certificate_authorities
 SSL_F_TLS_PARSE_CLIENTHELLO_TLSEXT:449:*
+SSL_F_TLS_PARSE_CTOS_ALPN:567:tls_parse_ctos_alpn
+SSL_F_TLS_PARSE_CTOS_EARLY_DATA:568:tls_parse_ctos_early_data
+SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS:569:tls_parse_ctos_ec_pt_formats
+SSL_F_TLS_PARSE_CTOS_EMS:570:tls_parse_ctos_ems
 SSL_F_TLS_PARSE_CTOS_KEY_SHARE:463:tls_parse_ctos_key_share
+SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN:571:tls_parse_ctos_maxfragmentlen
 SSL_F_TLS_PARSE_CTOS_PSK:505:tls_parse_ctos_psk
+SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES:572:tls_parse_ctos_psk_kex_modes
 SSL_F_TLS_PARSE_CTOS_RENEGOTIATE:464:tls_parse_ctos_renegotiate
+SSL_F_TLS_PARSE_CTOS_SERVER_NAME:573:tls_parse_ctos_server_name
+SSL_F_TLS_PARSE_CTOS_SESSION_TICKET:574:tls_parse_ctos_session_ticket
+SSL_F_TLS_PARSE_CTOS_SIG_ALGS:575:tls_parse_ctos_sig_algs
+SSL_F_TLS_PARSE_CTOS_SRP:576:tls_parse_ctos_srp
+SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST:577:tls_parse_ctos_status_request
+SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS:578:tls_parse_ctos_supported_groups
 SSL_F_TLS_PARSE_CTOS_USE_SRTP:465:tls_parse_ctos_use_srtp
+SSL_F_TLS_PARSE_STOC_ALPN:579:tls_parse_stoc_alpn
 SSL_F_TLS_PARSE_STOC_COOKIE:534:tls_parse_stoc_cookie
 SSL_F_TLS_PARSE_STOC_EARLY_DATA:538:tls_parse_stoc_early_data
 SSL_F_TLS_PARSE_STOC_EARLY_DATA_INFO:528:*
+SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS:580:tls_parse_stoc_ec_pt_formats
 SSL_F_TLS_PARSE_STOC_KEY_SHARE:445:tls_parse_stoc_key_share
+SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN:581:tls_parse_stoc_maxfragmentlen
+SSL_F_TLS_PARSE_STOC_NPN:582:tls_parse_stoc_npn
 SSL_F_TLS_PARSE_STOC_PSK:502:tls_parse_stoc_psk
 SSL_F_TLS_PARSE_STOC_RENEGOTIATE:448:tls_parse_stoc_renegotiate
+SSL_F_TLS_PARSE_STOC_SCT:564:tls_parse_stoc_sct
+SSL_F_TLS_PARSE_STOC_SERVER_NAME:583:tls_parse_stoc_server_name
+SSL_F_TLS_PARSE_STOC_SESSION_TICKET:584:tls_parse_stoc_session_ticket
+SSL_F_TLS_PARSE_STOC_STATUS_REQUEST:585:tls_parse_stoc_status_request
 SSL_F_TLS_PARSE_STOC_USE_SRTP:446:tls_parse_stoc_use_srtp
 SSL_F_TLS_POST_PROCESS_CLIENT_HELLO:378:tls_post_process_client_hello
 SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE:384:\
@@ -1309,6 +1370,7 @@ SSL_F_TLS_PSK_DO_BINDER:506:tls_psk_do_binder
 SSL_F_TLS_SCAN_CLIENTHELLO_TLSEXT:450:*
 SSL_F_TLS_SETUP_HANDSHAKE:508:tls_setup_handshake
 SSL_F_USE_CERTIFICATE_CHAIN_FILE:220:use_certificate_chain_file
+SSL_F_WRITE_STATE_MACHINE:586:write_state_machine
 TS_F_DEF_SERIAL_CB:110:def_serial_cb
 TS_F_DEF_TIME_CB:111:def_time_cb
 TS_F_ESS_ADD_SIGNING_CERT:112:ess_add_signing_cert
@@ -2286,14 +2348,17 @@ SSL_R_BAD_DATA_RETURNED_BY_CALLBACK:106:bad data returned by callback
 SSL_R_BAD_DECOMPRESSION:107:bad decompression
 SSL_R_BAD_DH_VALUE:102:bad dh value
 SSL_R_BAD_DIGEST_LENGTH:111:bad digest length
+SSL_R_BAD_EARLY_DATA:233:bad early data
 SSL_R_BAD_ECC_CERT:304:bad ecc cert
 SSL_R_BAD_ECPOINT:306:bad ecpoint
 SSL_R_BAD_EXTENSION:110:bad extension
 SSL_R_BAD_HANDSHAKE_LENGTH:332:bad handshake length
+SSL_R_BAD_HANDSHAKE_STATE:236:bad handshake state
 SSL_R_BAD_HELLO_REQUEST:105:bad hello request
 SSL_R_BAD_KEY_SHARE:108:bad key share
 SSL_R_BAD_KEY_UPDATE:122:bad key update
 SSL_R_BAD_LENGTH:271:bad length
+SSL_R_BAD_PACKET:240:bad packet
 SSL_R_BAD_PACKET_LENGTH:115:bad packet length
 SSL_R_BAD_PROTOCOL_VERSION_NUMBER:116:bad protocol version number
 SSL_R_BAD_PSK:219:bad psk
@@ -2308,9 +2373,11 @@ SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST:353:bad srtp protection profile list
 SSL_R_BAD_SSL_FILETYPE:124:bad ssl filetype
 SSL_R_BAD_VALUE:384:bad value
 SSL_R_BAD_WRITE_RETRY:127:bad write retry
+SSL_R_BINDER_DOES_NOT_VERIFY:253:binder does not verify
 SSL_R_BIO_NOT_SET:128:bio not set
 SSL_R_BLOCK_CIPHER_PAD_IS_WRONG:129:block cipher pad is wrong
 SSL_R_BN_LIB:130:bn lib
+SSL_R_CALLBACK_FAILED:234:callback failed
 SSL_R_CANNOT_CHANGE_CIPHER:109:cannot change cipher
 SSL_R_CA_DN_LENGTH_MISMATCH:131:ca dn length mismatch
 SSL_R_CA_KEY_TOO_SMALL:397:ca key too small
@@ -2379,7 +2446,9 @@ SSL_R_INCONSISTENT_COMPRESSION:340:inconsistent compression
 SSL_R_INCONSISTENT_EARLY_DATA_ALPN:222:inconsistent early data alpn
 SSL_R_INCONSISTENT_EARLY_DATA_SNI:231:inconsistent early data sni
 SSL_R_INCONSISTENT_EXTMS:104:inconsistent extms
+SSL_R_INSUFFICIENT_SECURITY:241:insufficient security
 SSL_R_INVALID_ALERT:205:invalid alert
+SSL_R_INVALID_CERTIFICATE_OR_ALG:238:invalid certificate or alg
 SSL_R_INVALID_COMMAND:280:invalid command
 SSL_R_INVALID_COMPRESSION_ALGORITHM:341:invalid compression algorithm
 SSL_R_INVALID_CONFIGURATION_NAME:113:invalid configuration name
@@ -2399,6 +2468,7 @@ SSL_R_LIBRARY_BUG:274:library bug
 SSL_R_LIBRARY_HAS_NO_CIPHERS:161:library has no ciphers
 SSL_R_MISSING_DSA_SIGNING_CERT:165:missing dsa signing cert
 SSL_R_MISSING_ECDSA_SIGNING_CERT:381:missing ecdsa signing cert
+SSL_R_MISSING_FATAL:256:missing fatal
 SSL_R_MISSING_RSA_CERTIFICATE:168:missing rsa certificate
 SSL_R_MISSING_RSA_ENCRYPTING_CERT:169:missing rsa encrypting cert
 SSL_R_MISSING_RSA_SIGNING_CERT:170:missing rsa signing cert
@@ -2409,6 +2479,7 @@ SSL_R_MISSING_SUPPORTED_GROUPS_EXTENSION:209:missing supported groups extension
 SSL_R_MISSING_TMP_DH_KEY:171:missing tmp dh key
 SSL_R_MISSING_TMP_ECDH_KEY:311:missing tmp ecdh key
 SSL_R_NOT_ON_RECORD_BOUNDARY:182:not on record boundary
+SSL_R_NO_APPLICATION_PROTOCOL:235:no application protocol
 SSL_R_NO_CERTIFICATES_RETURNED:176:no certificates returned
 SSL_R_NO_CERTIFICATE_ASSIGNED:177:no certificate assigned
 SSL_R_NO_CERTIFICATE_SET:179:no certificate set
@@ -2439,6 +2510,7 @@ SSL_R_NULL_SSL_METHOD_PASSED:196:null ssl method passed
 SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED:197:old session cipher not returned
 SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED:344:\
 	old session compression algorithm not returned
+SSL_R_OVERFLOW_ERROR:237:overflow error
 SSL_R_PACKET_LENGTH_TOO_LONG:198:packet length too long
 SSL_R_PARSE_TLSEXT:227:parse tlsext
 SSL_R_PATH_TOO_LONG:270:path too long
diff --git a/include/openssl/sslerr.h b/include/openssl/sslerr.h
index 3450b4c..ef6b9dd 100644
--- a/include/openssl/sslerr.h
+++ b/include/openssl/sslerr.h
@@ -26,9 +26,13 @@ int ERR_load_SSL_strings(void);
 # define SSL_F_ADD_KEY_SHARE                              512
 # define SSL_F_BYTES_TO_CIPHER_LIST                       519
 # define SSL_F_CHECK_SUITEB_CIPHER_LIST                   331
+# define SSL_F_CONSTRUCT_CA_NAMES                         552
+# define SSL_F_CONSTRUCT_KEY_EXCHANGE_TBS                 553
 # define SSL_F_CREATE_SYNTHETIC_MESSAGE_HASH              539
 # define SSL_F_CT_MOVE_SCTS                               345
 # define SSL_F_CT_STRICT                                  349
+# define SSL_F_CUSTOM_EXT_ADD                             554
+# define SSL_F_CUSTOM_EXT_PARSE                           555
 # define SSL_F_D2I_SSL_SESSION                            103
 # define SSL_F_DANE_CTX_ENABLE                            347
 # define SSL_F_DANE_MTYPE_SET                             393
@@ -52,24 +56,41 @@ int ERR_load_SSL_strings(void);
 # define SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST        385
 # define SSL_F_DTLS_GET_REASSEMBLED_MESSAGE               370
 # define SSL_F_DTLS_PROCESS_HELLO_VERIFY                  386
+# define SSL_F_DTLS_WAIT_FOR_DRY                          592
 # define SSL_F_EARLY_DATA_COUNT_OK                        532
+# define SSL_F_FINAL_EARLY_DATA                           556
 # define SSL_F_FINAL_EC_PT_FORMATS                        485
 # define SSL_F_FINAL_EMS                                  486
 # define SSL_F_FINAL_KEY_SHARE                            503
+# define SSL_F_FINAL_MAXFRAGMENTLEN                       557
 # define SSL_F_FINAL_RENEGOTIATE                          483
+# define SSL_F_FINAL_SERVER_NAME                          558
 # define SSL_F_FINAL_SIG_ALGS                             497
+# define SSL_F_GET_CERT_VERIFY_TBS_DATA                   588
 # define SSL_F_NSS_KEYLOG_INT                             500
 # define SSL_F_OPENSSL_INIT_SSL                           342
 # define SSL_F_OSSL_STATEM_CLIENT13_READ_TRANSITION       436
+# define SSL_F_OSSL_STATEM_CLIENT13_WRITE_TRANSITION      598
 # define SSL_F_OSSL_STATEM_CLIENT_CONSTRUCT_MESSAGE       430
+# define SSL_F_OSSL_STATEM_CLIENT_POST_PROCESS_MESSAGE    593
+# define SSL_F_OSSL_STATEM_CLIENT_PROCESS_MESSAGE         594
 # define SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION         417
+# define SSL_F_OSSL_STATEM_CLIENT_WRITE_TRANSITION        599
 # define SSL_F_OSSL_STATEM_SERVER13_READ_TRANSITION       437
+# define SSL_F_OSSL_STATEM_SERVER13_WRITE_TRANSITION      600
 # define SSL_F_OSSL_STATEM_SERVER_CONSTRUCT_MESSAGE       431
+# define SSL_F_OSSL_STATEM_SERVER_POST_PROCESS_MESSAGE    601
+# define SSL_F_OSSL_STATEM_SERVER_POST_WORK               602
+# define SSL_F_OSSL_STATEM_SERVER_PROCESS_MESSAGE         603
 # define SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION         418
+# define SSL_F_OSSL_STATEM_SERVER_WRITE_TRANSITION        604
 # define SSL_F_PARSE_CA_NAMES                             541
 # define SSL_F_PROCESS_KEY_SHARE_EXT                      439
 # define SSL_F_READ_STATE_MACHINE                         352
 # define SSL_F_SET_CLIENT_CIPHERSUITE                     540
+# define SSL_F_SRP_GENERATE_CLIENT_MASTER_SECRET          595
+# define SSL_F_SRP_GENERATE_SERVER_MASTER_SECRET          589
+# define SSL_F_SRP_VERIFY_SERVER_PARAM                    596
 # define SSL_F_SSL3_CHANGE_CIPHER_STATE                   129
 # define SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM              130
 # define SSL_F_SSL3_CTRL                                  213
@@ -77,6 +98,7 @@ int ERR_load_SSL_strings(void);
 # define SSL_F_SSL3_DIGEST_CACHED_RECORDS                 293
 # define SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC                 292
 # define SSL_F_SSL3_FINAL_FINISH_MAC                      285
+# define SSL_F_SSL3_FINISH_MAC                            587
 # define SSL_F_SSL3_GENERATE_KEY_BLOCK                    238
 # define SSL_F_SSL3_GENERATE_MASTER_SECRET                388
 # define SSL_F_SSL3_GET_RECORD                            143
@@ -110,7 +132,9 @@ int ERR_load_SSL_strings(void);
 # define SSL_F_SSL_CERT_SET0_CHAIN                        340
 # define SSL_F_SSL_CHECK_PRIVATE_KEY                      163
 # define SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT               280
+# define SSL_F_SSL_CHECK_SRP_EXT_CLIENTHELLO              606
 # define SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG            279
+# define SSL_F_SSL_CHOOSE_CLIENT_VERSION                  607
 # define SSL_F_SSL_CIPHER_LIST_TO_BYTES                   425
 # define SSL_F_SSL_CIPHER_PROCESS_RULESTR                 230
 # define SSL_F_SSL_CIPHER_STRENGTH_SORT                   231
@@ -145,15 +169,18 @@ int ERR_load_SSL_strings(void);
 # define SSL_F_SSL_CTX_USE_SERVERINFO_FILE                337
 # define SSL_F_SSL_DANE_DUP                               403
 # define SSL_F_SSL_DANE_ENABLE                            395
+# define SSL_F_SSL_DERIVE                                 590
 # define SSL_F_SSL_DO_CONFIG                              391
 # define SSL_F_SSL_DO_HANDSHAKE                           180
 # define SSL_F_SSL_DUP_CA_LIST                            408
 # define SSL_F_SSL_ENABLE_CT                              402
+# define SSL_F_SSL_GENERATE_PKEY_GROUP                    559
 # define SSL_F_SSL_GENERATE_SESSION_ID                    547
 # define SSL_F_SSL_GET_NEW_SESSION                        181
 # define SSL_F_SSL_GET_PREV_SESSION                       217
 # define SSL_F_SSL_GET_SERVER_CERT_INDEX                  322
 # define SSL_F_SSL_GET_SIGN_PKEY                          183
+# define SSL_F_SSL_HANDSHAKE_HASH                         560
 # define SSL_F_SSL_INIT_WBIO_BUFFER                       184
 # define SSL_F_SSL_KEY_UPDATE                             515
 # define SSL_F_SSL_LOAD_CLIENT_CA_FILE                    185
@@ -161,6 +188,7 @@ int ERR_load_SSL_strings(void);
 # define SSL_F_SSL_LOG_RSA_CLIENT_KEY_EXCHANGE            499
 # define SSL_F_SSL_MODULE_INIT                            392
 # define SSL_F_SSL_NEW                                    186
+# define SSL_F_SSL_NEXT_PROTO_VALIDATE                    565
 # define SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT      300
 # define SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT               302
 # define SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT         310
@@ -221,6 +249,9 @@ int ERR_load_SSL_strings(void);
 # define SSL_F_TLS12_CHECK_PEER_SIGALG                    333
 # define SSL_F_TLS12_COPY_SIGALGS                         533
 # define SSL_F_TLS13_CHANGE_CIPHER_STATE                  440
+# define SSL_F_TLS13_FINAL_FINISH_MAC                     605
+# define SSL_F_TLS13_GENERATE_SECRET                      591
+# define SSL_F_TLS13_HKDF_EXPAND                          561
 # define SSL_F_TLS13_SETUP_KEY_BLOCK                      441
 # define SSL_F_TLS1_CHANGE_CIPHER_STATE                   209
 # define SSL_F_TLS1_CHECK_DUPLICATE_EXTENSIONS            341
@@ -309,19 +340,43 @@ int ERR_load_SSL_strings(void);
 # define SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS        544
 # define SSL_F_TLS_CONSTRUCT_STOC_USE_SRTP                462
 # define SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO        521
+# define SSL_F_TLS_FINISH_HANDSHAKE                       597
 # define SSL_F_TLS_GET_MESSAGE_BODY                       351
 # define SSL_F_TLS_GET_MESSAGE_HEADER                     387
+# define SSL_F_TLS_HANDLE_ALPN                            562
+# define SSL_F_TLS_HANDLE_STATUS_REQUEST                  563
+# define SSL_F_TLS_PARSE_CERTIFICATE_AUTHORITIES          566
 # define SSL_F_TLS_PARSE_CLIENTHELLO_TLSEXT               449
+# define SSL_F_TLS_PARSE_CTOS_ALPN                        567
+# define SSL_F_TLS_PARSE_CTOS_EARLY_DATA                  568
+# define SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS               569
+# define SSL_F_TLS_PARSE_CTOS_EMS                         570
 # define SSL_F_TLS_PARSE_CTOS_KEY_SHARE                   463
+# define SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN              571
 # define SSL_F_TLS_PARSE_CTOS_PSK                         505
+# define SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES               572
 # define SSL_F_TLS_PARSE_CTOS_RENEGOTIATE                 464
+# define SSL_F_TLS_PARSE_CTOS_SERVER_NAME                 573
+# define SSL_F_TLS_PARSE_CTOS_SESSION_TICKET              574
+# define SSL_F_TLS_PARSE_CTOS_SIG_ALGS                    575
+# define SSL_F_TLS_PARSE_CTOS_SRP                         576
+# define SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST              577
+# define SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS            578
 # define SSL_F_TLS_PARSE_CTOS_USE_SRTP                    465
+# define SSL_F_TLS_PARSE_STOC_ALPN                        579
 # define SSL_F_TLS_PARSE_STOC_COOKIE                      534
 # define SSL_F_TLS_PARSE_STOC_EARLY_DATA                  538
 # define SSL_F_TLS_PARSE_STOC_EARLY_DATA_INFO             528
+# define SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS               580
 # define SSL_F_TLS_PARSE_STOC_KEY_SHARE                   445
+# define SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN              581
+# define SSL_F_TLS_PARSE_STOC_NPN                         582
 # define SSL_F_TLS_PARSE_STOC_PSK                         502
 # define SSL_F_TLS_PARSE_STOC_RENEGOTIATE                 448
+# define SSL_F_TLS_PARSE_STOC_SCT                         564
+# define SSL_F_TLS_PARSE_STOC_SERVER_NAME                 583
+# define SSL_F_TLS_PARSE_STOC_SESSION_TICKET              584
+# define SSL_F_TLS_PARSE_STOC_STATUS_REQUEST              585
 # define SSL_F_TLS_PARSE_STOC_USE_SRTP                    446
 # define SSL_F_TLS_POST_PROCESS_CLIENT_HELLO              378
 # define SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE       384
@@ -361,6 +416,7 @@ int ERR_load_SSL_strings(void);
 # define SSL_F_TLS_SCAN_CLIENTHELLO_TLSEXT                450
 # define SSL_F_TLS_SETUP_HANDSHAKE                        508
 # define SSL_F_USE_CERTIFICATE_CHAIN_FILE                 220
+# define SSL_F_WRITE_STATE_MACHINE                        586
 
 /*
  * SSL reason codes.
@@ -376,14 +432,17 @@ int ERR_load_SSL_strings(void);
 # define SSL_R_BAD_DECOMPRESSION                          107
 # define SSL_R_BAD_DH_VALUE                               102
 # define SSL_R_BAD_DIGEST_LENGTH                          111
+# define SSL_R_BAD_EARLY_DATA                             233
 # define SSL_R_BAD_ECC_CERT                               304
 # define SSL_R_BAD_ECPOINT                                306
 # define SSL_R_BAD_EXTENSION                              110
 # define SSL_R_BAD_HANDSHAKE_LENGTH                       332
+# define SSL_R_BAD_HANDSHAKE_STATE                        236
 # define SSL_R_BAD_HELLO_REQUEST                          105
 # define SSL_R_BAD_KEY_SHARE                              108
 # define SSL_R_BAD_KEY_UPDATE                             122
 # define SSL_R_BAD_LENGTH                                 271
+# define SSL_R_BAD_PACKET                                 240
 # define SSL_R_BAD_PACKET_LENGTH                          115
 # define SSL_R_BAD_PROTOCOL_VERSION_NUMBER                116
 # define SSL_R_BAD_PSK                                    219
@@ -398,9 +457,11 @@ int ERR_load_SSL_strings(void);
 # define SSL_R_BAD_SSL_FILETYPE                           124
 # define SSL_R_BAD_VALUE                                  384
 # define SSL_R_BAD_WRITE_RETRY                            127
+# define SSL_R_BINDER_DOES_NOT_VERIFY                     253
 # define SSL_R_BIO_NOT_SET                                128
 # define SSL_R_BLOCK_CIPHER_PAD_IS_WRONG                  129
 # define SSL_R_BN_LIB                                     130
+# define SSL_R_CALLBACK_FAILED                            234
 # define SSL_R_CANNOT_CHANGE_CIPHER                       109
 # define SSL_R_CA_DN_LENGTH_MISMATCH                      131
 # define SSL_R_CA_KEY_TOO_SMALL                           397
@@ -466,7 +527,9 @@ int ERR_load_SSL_strings(void);
 # define SSL_R_INCONSISTENT_EARLY_DATA_ALPN               222
 # define SSL_R_INCONSISTENT_EARLY_DATA_SNI                231
 # define SSL_R_INCONSISTENT_EXTMS                         104
+# define SSL_R_INSUFFICIENT_SECURITY                      241
 # define SSL_R_INVALID_ALERT                              205
+# define SSL_R_INVALID_CERTIFICATE_OR_ALG                 238
 # define SSL_R_INVALID_COMMAND                            280
 # define SSL_R_INVALID_COMPRESSION_ALGORITHM              341
 # define SSL_R_INVALID_CONFIGURATION_NAME                 113
@@ -486,6 +549,7 @@ int ERR_load_SSL_strings(void);
 # define SSL_R_LIBRARY_HAS_NO_CIPHERS                     161
 # define SSL_R_MISSING_DSA_SIGNING_CERT                   165
 # define SSL_R_MISSING_ECDSA_SIGNING_CERT                 381
+# define SSL_R_MISSING_FATAL                              256
 # define SSL_R_MISSING_RSA_CERTIFICATE                    168
 # define SSL_R_MISSING_RSA_ENCRYPTING_CERT                169
 # define SSL_R_MISSING_RSA_SIGNING_CERT                   170
@@ -496,6 +560,7 @@ int ERR_load_SSL_strings(void);
 # define SSL_R_MISSING_TMP_DH_KEY                         171
 # define SSL_R_MISSING_TMP_ECDH_KEY                       311
 # define SSL_R_NOT_ON_RECORD_BOUNDARY                     182
+# define SSL_R_NO_APPLICATION_PROTOCOL                    235
 # define SSL_R_NO_CERTIFICATES_RETURNED                   176
 # define SSL_R_NO_CERTIFICATE_ASSIGNED                    177
 # define SSL_R_NO_CERTIFICATE_SET                         179
@@ -524,6 +589,7 @@ int ERR_load_SSL_strings(void);
 # define SSL_R_NULL_SSL_METHOD_PASSED                     196
 # define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED            197
 # define SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED 344
+# define SSL_R_OVERFLOW_ERROR                             237
 # define SSL_R_PACKET_LENGTH_TOO_LONG                     198
 # define SSL_R_PARSE_TLSEXT                               227
 # define SSL_R_PATH_TOO_LONG                              270
diff --git a/ssl/record/rec_layer_d1.c b/ssl/record/rec_layer_d1.c
index 3eabf71..596ea2e 100644
--- a/ssl/record/rec_layer_d1.c
+++ b/ssl/record/rec_layer_d1.c
@@ -397,8 +397,12 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
     }
 
     /* Check for timeout */
-    if (dtls1_handle_timeout(s) > 0)
+    if (dtls1_handle_timeout(s) > 0) {
         goto start;
+    } else if (ossl_statem_in_error(s)) {
+        /* dtls1_handle_timeout() has failed with a fatal error */
+        return -1;
+    }
 
     /* get new packet if necessary */
     if ((SSL3_RECORD_get_length(rr) == 0)
@@ -633,7 +637,11 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
             if (dtls1_check_timeout_num(s) < 0)
                 return -1;
 
-            dtls1_retransmit_buffered_messages(s);
+            if (dtls1_retransmit_buffered_messages(s) <= 0) {
+                /* Fail if we encountered a fatal error */
+                if (ossl_statem_in_error(s))
+                    return -1;
+            }
             SSL3_RECORD_set_length(rr, 0);
             goto start;
         }
diff --git a/ssl/record/ssl3_buffer.c b/ssl/record/ssl3_buffer.c
index da23b36..6d3a232 100644
--- a/ssl/record/ssl3_buffer.c
+++ b/ssl/record/ssl3_buffer.c
@@ -116,7 +116,9 @@ int ssl3_setup_write_buffer(SSL *s, size_t numwpipes, size_t len)
             p = OPENSSL_malloc(len);
             if (p == NULL) {
                 s->rlayer.numwpipes = currpipe;
-                goto err;
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_SSL3_SETUP_WRITE_BUFFER, ERR_R_MALLOC_FAILURE);
+                return 0;
             }
             memset(thiswb, 0, sizeof(SSL3_BUFFER));
             thiswb->buf = p;
@@ -125,18 +127,16 @@ int ssl3_setup_write_buffer(SSL *s, size_t numwpipes, size_t len)
     }
 
     return 1;
-
- err:
-    SSLerr(SSL_F_SSL3_SETUP_WRITE_BUFFER, ERR_R_MALLOC_FAILURE);
-    return 0;
 }
 
 int ssl3_setup_buffers(SSL *s)
 {
     if (!ssl3_setup_read_buffer(s))
         return 0;
-    if (!ssl3_setup_write_buffer(s, 1, 0))
+    if (!ssl3_setup_write_buffer(s, 1, 0)) {
+        /* SSLfatal() already called */
         return 0;
+    }
     return 1;
 }
 
diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c
index 02e0598..4c63d4a 100644
--- a/ssl/s3_enc.c
+++ b/ssl/s3_enc.c
@@ -30,7 +30,8 @@ static int ssl3_generate_key_block(SSL *s, unsigned char *km, int num)
     m5 = EVP_MD_CTX_new();
     s1 = EVP_MD_CTX_new();
     if (m5 == NULL || s1 == NULL) {
-        SSLerr(SSL_F_SSL3_GENERATE_KEY_BLOCK, ERR_R_MALLOC_FAILURE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GENERATE_KEY_BLOCK,
+                 ERR_R_MALLOC_FAILURE);
         goto err;
     }
     EVP_MD_CTX_set_flags(m5, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
@@ -38,7 +39,8 @@ static int ssl3_generate_key_block(SSL *s, unsigned char *km, int num)
         k++;
         if (k > sizeof(buf)) {
             /* bug: 'buf' is too small for this ciphersuite */
-            SSLerr(SSL_F_SSL3_GENERATE_KEY_BLOCK, ERR_R_INTERNAL_ERROR);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GENERATE_KEY_BLOCK,
+                     ERR_R_INTERNAL_ERROR);
             goto err;
         }
 
@@ -55,15 +57,24 @@ static int ssl3_generate_key_block(SSL *s, unsigned char *km, int num)
             || !EVP_DigestInit_ex(m5, EVP_md5(), NULL)
             || !EVP_DigestUpdate(m5, s->session->master_key,
                                  s->session->master_key_length)
-            || !EVP_DigestUpdate(m5, smd, SHA_DIGEST_LENGTH))
+            || !EVP_DigestUpdate(m5, smd, SHA_DIGEST_LENGTH)) {
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GENERATE_KEY_BLOCK,
+                     ERR_R_INTERNAL_ERROR);
             goto err;
+        }
         if ((int)(i + MD5_DIGEST_LENGTH) > num) {
-            if (!EVP_DigestFinal_ex(m5, smd, NULL))
+            if (!EVP_DigestFinal_ex(m5, smd, NULL)) {
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_SSL3_GENERATE_KEY_BLOCK, ERR_R_INTERNAL_ERROR);
                 goto err;
+            }
             memcpy(km, smd, (num - i));
         } else {
-            if (!EVP_DigestFinal_ex(m5, km, NULL))
+            if (!EVP_DigestFinal_ex(m5, km, NULL)) {
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_SSL3_GENERATE_KEY_BLOCK, ERR_R_INTERNAL_ERROR);
                 goto err;
+            }
         }
 
         km += MD5_DIGEST_LENGTH;
@@ -96,8 +107,9 @@ int ssl3_change_cipher_state(SSL *s, int which)
     m = s->s3->tmp.new_hash;
     /* m == NULL will lead to a crash later */
     if (!ossl_assert(m != NULL)) {
-        SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
-        goto err2;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
+                 ERR_R_INTERNAL_ERROR);
+        goto err;
     }
 #ifndef OPENSSL_NO_COMP
     if (s->s3->tmp.new_compression == NULL)
@@ -107,20 +119,24 @@ int ssl3_change_cipher_state(SSL *s, int which)
 #endif
 
     if (which & SSL3_CC_READ) {
-        if (s->enc_read_ctx != NULL)
+        if (s->enc_read_ctx != NULL) {
             reuse_dd = 1;
-        else if ((s->enc_read_ctx = EVP_CIPHER_CTX_new()) == NULL)
+        } else if ((s->enc_read_ctx = EVP_CIPHER_CTX_new()) == NULL) {
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
+                     ERR_R_MALLOC_FAILURE);
             goto err;
-        else
+        } else {
             /*
              * make sure it's initialised in case we exit later with an error
              */
             EVP_CIPHER_CTX_reset(s->enc_read_ctx);
+        }
         dd = s->enc_read_ctx;
 
         if (ssl_replace_hash(&s->read_hash, m) == NULL) {
-            SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
-            goto err2;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
+                     ERR_R_INTERNAL_ERROR);
+            goto err;
         }
 #ifndef OPENSSL_NO_COMP
         /* COMPRESS */
@@ -129,28 +145,33 @@ int ssl3_change_cipher_state(SSL *s, int which)
         if (comp != NULL) {
             s->expand = COMP_CTX_new(comp);
             if (s->expand == NULL) {
-                SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE,
-                       SSL_R_COMPRESSION_LIBRARY_ERROR);
-                goto err2;
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_SSL3_CHANGE_CIPHER_STATE,
+                         SSL_R_COMPRESSION_LIBRARY_ERROR);
+                goto err;
             }
         }
 #endif
         RECORD_LAYER_reset_read_sequence(&s->rlayer);
         mac_secret = &(s->s3->read_mac_secret[0]);
     } else {
-        if (s->enc_write_ctx != NULL)
+        if (s->enc_write_ctx != NULL) {
             reuse_dd = 1;
-        else if ((s->enc_write_ctx = EVP_CIPHER_CTX_new()) == NULL)
+        } else if ((s->enc_write_ctx = EVP_CIPHER_CTX_new()) == NULL) {
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
+                     ERR_R_MALLOC_FAILURE);
             goto err;
-        else
+        } else {
             /*
              * make sure it's initialised in case we exit later with an error
              */
             EVP_CIPHER_CTX_reset(s->enc_write_ctx);
+        }
         dd = s->enc_write_ctx;
         if (ssl_replace_hash(&s->write_hash, m) == NULL) {
-            SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
-            goto err2;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
+                     ERR_R_MALLOC_FAILURE);
+            goto err;
         }
 #ifndef OPENSSL_NO_COMP
         /* COMPRESS */
@@ -159,9 +180,10 @@ int ssl3_change_cipher_state(SSL *s, int which)
         if (comp != NULL) {
             s->compress = COMP_CTX_new(comp);
             if (s->compress == NULL) {
-                SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE,
-                       SSL_R_COMPRESSION_LIBRARY_ERROR);
-                goto err2;
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_SSL3_CHANGE_CIPHER_STATE,
+                         SSL_R_COMPRESSION_LIBRARY_ERROR);
+                goto err;
             }
         }
 #endif
@@ -174,8 +196,11 @@ int ssl3_change_cipher_state(SSL *s, int which)
 
     p = s->s3->tmp.key_block;
     mdi = EVP_MD_size(m);
-    if (mdi < 0)
-        goto err2;
+    if (mdi < 0) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
+                 ERR_R_INTERNAL_ERROR);
+        goto err;
+    }
     i = mdi;
     cl = EVP_CIPHER_key_length(c);
     j = cl;
@@ -199,21 +224,23 @@ int ssl3_change_cipher_state(SSL *s, int which)
     }
 
     if (n > s->s3->tmp.key_block_length) {
-        SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
-        goto err2;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
+                 ERR_R_INTERNAL_ERROR);
+        goto err;
     }
 
     memcpy(mac_secret, ms, i);
 
-    if (!EVP_CipherInit_ex(dd, c, NULL, key, iv, (which & SSL3_CC_WRITE)))
-        goto err2;
+    if (!EVP_CipherInit_ex(dd, c, NULL, key, iv, (which & SSL3_CC_WRITE))) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
+                 ERR_R_INTERNAL_ERROR);
+        goto err;
+    }
 
     OPENSSL_cleanse(exp_key, sizeof(exp_key));
     OPENSSL_cleanse(exp_iv, sizeof(exp_iv));
     return 1;
  err:
-    SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE);
- err2:
     OPENSSL_cleanse(exp_key, sizeof(exp_key));
     OPENSSL_cleanse(exp_iv, sizeof(exp_iv));
     return 0;
@@ -232,7 +259,8 @@ int ssl3_setup_key_block(SSL *s)
         return 1;
 
     if (!ssl_cipher_get_evp(s->session, &c, &hash, NULL, NULL, &comp, 0)) {
-        SSLerr(SSL_F_SSL3_SETUP_KEY_BLOCK, SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_SETUP_KEY_BLOCK,
+                 SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
         return 0;
     }
 
@@ -253,12 +281,16 @@ int ssl3_setup_key_block(SSL *s)
 
     ssl3_cleanup_key_block(s);
 
-    if ((p = OPENSSL_malloc(num)) == NULL)
-        goto err;
+    if ((p = OPENSSL_malloc(num)) == NULL) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_SETUP_KEY_BLOCK,
+                 ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
 
     s->s3->tmp.key_block_length = num;
     s->s3->tmp.key_block = p;
 
+    /* Calls SSLfatal() as required */
     ret = ssl3_generate_key_block(s, p, num);
 
     if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)) {
@@ -280,10 +312,6 @@ int ssl3_setup_key_block(SSL *s)
     }
 
     return ret;
-
- err:
-    SSLerr(SSL_F_SSL3_SETUP_KEY_BLOCK, ERR_R_MALLOC_FAILURE);
-    return 0;
 }
 
 void ssl3_cleanup_key_block(SSL *s)
@@ -298,7 +326,8 @@ int ssl3_init_finished_mac(SSL *s)
     BIO *buf = BIO_new(BIO_s_mem());
 
     if (buf == NULL) {
-        SSLerr(SSL_F_SSL3_INIT_FINISHED_MAC, ERR_R_MALLOC_FAILURE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_INIT_FINISHED_MAC,
+                 ERR_R_MALLOC_FAILURE);
         return 0;
     }
     ssl3_free_digest_list(s);
@@ -322,16 +351,30 @@ void ssl3_free_digest_list(SSL *s)
 
 int ssl3_finish_mac(SSL *s, const unsigned char *buf, size_t len)
 {
+    int ret;
+
     if (s->s3->handshake_dgst == NULL) {
-        int ret;
         /* Note: this writes to a memory BIO so a failure is a fatal error */
-        if (len > INT_MAX)
+        if (len > INT_MAX) {
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINISH_MAC,
+                     SSL_R_OVERFLOW_ERROR);
             return 0;
+        }
         ret = BIO_write(s->s3->handshake_buffer, (void *)buf, (int)len);
-        return ret > 0 && ret == (int)len;
+        if (ret <= 0 || ret != (int)len) {
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINISH_MAC,
+                     ERR_R_INTERNAL_ERROR);
+            return 0;
+        }
     } else {
-        return EVP_DigestUpdate(s->s3->handshake_dgst, buf, len);
+        ret = EVP_DigestUpdate(s->s3->handshake_dgst, buf, len);
+        if (!ret) {
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINISH_MAC,
+                     ERR_R_INTERNAL_ERROR);
+            return 0;
+        }
     }
+    return 1;
 }
 
 int ssl3_digest_cached_records(SSL *s, int keep)
@@ -343,21 +386,23 @@ int ssl3_digest_cached_records(SSL *s, int keep)
     if (s->s3->handshake_dgst == NULL) {
         hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
         if (hdatalen <= 0) {
-            SSLerr(SSL_F_SSL3_DIGEST_CACHED_RECORDS,
-                   SSL_R_BAD_HANDSHAKE_LENGTH);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_DIGEST_CACHED_RECORDS,
+                     SSL_R_BAD_HANDSHAKE_LENGTH);
             return 0;
         }
 
         s->s3->handshake_dgst = EVP_MD_CTX_new();
         if (s->s3->handshake_dgst == NULL) {
-            SSLerr(SSL_F_SSL3_DIGEST_CACHED_RECORDS, ERR_R_MALLOC_FAILURE);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_DIGEST_CACHED_RECORDS,
+                     ERR_R_MALLOC_FAILURE);
             return 0;
         }
 
         md = ssl_handshake_md(s);
         if (md == NULL || !EVP_DigestInit_ex(s->s3->handshake_dgst, md, NULL)
             || !EVP_DigestUpdate(s->s3->handshake_dgst, hdata, hdatalen)) {
-            SSLerr(SSL_F_SSL3_DIGEST_CACHED_RECORDS, ERR_R_INTERNAL_ERROR);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_DIGEST_CACHED_RECORDS,
+                     ERR_R_INTERNAL_ERROR);
             return 0;
         }
     }
@@ -375,26 +420,33 @@ size_t ssl3_final_finish_mac(SSL *s, const char *sender, size_t len,
     int ret;
     EVP_MD_CTX *ctx = NULL;
 
-    if (!ssl3_digest_cached_records(s, 0))
+    if (!ssl3_digest_cached_records(s, 0)) {
+        /* SSLfatal() already called */
         return 0;
+    }
 
     if (EVP_MD_CTX_type(s->s3->handshake_dgst) != NID_md5_sha1) {
-        SSLerr(SSL_F_SSL3_FINAL_FINISH_MAC, SSL_R_NO_REQUIRED_DIGEST);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC,
+                 SSL_R_NO_REQUIRED_DIGEST);
         return 0;
     }
 
     ctx = EVP_MD_CTX_new();
     if (ctx == NULL) {
-        SSLerr(SSL_F_SSL3_FINAL_FINISH_MAC, ERR_R_MALLOC_FAILURE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC,
+                 ERR_R_MALLOC_FAILURE);
         return 0;
     }
     if (!EVP_MD_CTX_copy_ex(ctx, s->s3->handshake_dgst)) {
-        SSLerr(SSL_F_SSL3_FINAL_FINISH_MAC, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
     ret = EVP_MD_CTX_size(ctx);
     if (ret < 0) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC,
+                 ERR_R_INTERNAL_ERROR);
         EVP_MD_CTX_reset(ctx);
         return 0;
     }
@@ -404,7 +456,8 @@ size_t ssl3_final_finish_mac(SSL *s, const char *sender, size_t len,
                            (int)s->session->master_key_length,
                            s->session->master_key) <= 0
         || EVP_DigestFinal_ex(ctx, p, NULL) <= 0) {
-        SSLerr(SSL_F_SSL3_FINAL_FINISH_MAC, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC,
+                 ERR_R_INTERNAL_ERROR);
         ret = 0;
     }
 
@@ -434,7 +487,8 @@ int ssl3_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
     size_t ret_secret_size = 0;
 
     if (ctx == NULL) {
-        SSLerr(SSL_F_SSL3_GENERATE_MASTER_SECRET, ERR_R_MALLOC_FAILURE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GENERATE_MASTER_SECRET,
+                 ERR_R_MALLOC_FAILURE);
         return 0;
     }
     for (i = 0; i < 3; i++) {
@@ -452,7 +506,8 @@ int ssl3_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
             || EVP_DigestUpdate(ctx, p, len) <= 0
             || EVP_DigestUpdate(ctx, buf, n) <= 0
             || EVP_DigestFinal_ex(ctx, out, &n) <= 0) {
-            SSLerr(SSL_F_SSL3_GENERATE_MASTER_SECRET, ERR_R_INTERNAL_ERROR);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_SSL3_GENERATE_MASTER_SECRET, ERR_R_INTERNAL_ERROR);
             ret = 0;
             break;
         }
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index e71373d..48fecd2 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -4590,8 +4590,10 @@ int ssl_generate_master_secret(SSL *s, unsigned char *pms, size_t pmslen,
         s->s3->tmp.psk = NULL;
         if (!s->method->ssl3_enc->generate_master_secret(s,
                     s->session->master_key,pskpms, pskpmslen,
-                    &s->session->master_key_length))
+                    &s->session->master_key_length)) {
+            /* SSLfatal() already called */
             goto err;
+        }
         OPENSSL_clear_free(pskpms, pskpmslen);
 #else
         /* Should never happen */
@@ -4600,8 +4602,10 @@ int ssl_generate_master_secret(SSL *s, unsigned char *pms, size_t pmslen,
     } else {
         if (!s->method->ssl3_enc->generate_master_secret(s,
                 s->session->master_key, pms, pmslen,
-                &s->session->master_key_length))
+                &s->session->master_key_length)) {
+            /* SSLfatal() already called */
             goto err;
+        }
     }
 
     ret = 1;
@@ -4641,28 +4645,42 @@ EVP_PKEY *ssl_generate_pkey(EVP_PKEY *pm)
 }
 #ifndef OPENSSL_NO_EC
 /* Generate a private key from a group ID */
-EVP_PKEY *ssl_generate_pkey_group(uint16_t id)
+EVP_PKEY *ssl_generate_pkey_group(SSL *s, uint16_t id)
 {
     EVP_PKEY_CTX *pctx = NULL;
     EVP_PKEY *pkey = NULL;
     const TLS_GROUP_INFO *ginf = tls1_group_id_lookup(id);
     uint16_t gtype;
 
-    if (ginf == NULL)
+    if (ginf == NULL) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_PKEY_GROUP,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
+    }
     gtype = ginf->flags & TLS_CURVE_TYPE;
     if (gtype == TLS_CURVE_CUSTOM)
         pctx = EVP_PKEY_CTX_new_id(ginf->nid, NULL);
     else
         pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
-    if (pctx == NULL)
+    if (pctx == NULL) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_PKEY_GROUP,
+                 ERR_R_MALLOC_FAILURE);
         goto err;
-    if (EVP_PKEY_keygen_init(pctx) <= 0)
+    }
+    if (EVP_PKEY_keygen_init(pctx) <= 0) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_PKEY_GROUP,
+                 ERR_R_EVP_LIB);
         goto err;
+    }
     if (gtype != TLS_CURVE_CUSTOM
-            && EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, ginf->nid) <= 0)
+            && EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, ginf->nid) <= 0) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_PKEY_GROUP,
+                 ERR_R_EVP_LIB);
         goto err;
+    }
     if (EVP_PKEY_keygen(pctx, &pkey) <= 0) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_PKEY_GROUP,
+                 ERR_R_EVP_LIB);
         EVP_PKEY_free(pkey);
         pkey = NULL;
     }
@@ -4718,25 +4736,37 @@ int ssl_derive(SSL *s, EVP_PKEY *privkey, EVP_PKEY *pubkey, int gensecret)
     size_t pmslen = 0;
     EVP_PKEY_CTX *pctx;
 
-    if (privkey == NULL || pubkey == NULL)
+    if (privkey == NULL || pubkey == NULL) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_DERIVE,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
+    }
 
     pctx = EVP_PKEY_CTX_new(privkey, NULL);
 
     if (EVP_PKEY_derive_init(pctx) <= 0
         || EVP_PKEY_derive_set_peer(pctx, pubkey) <= 0
         || EVP_PKEY_derive(pctx, NULL, &pmslen) <= 0) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_DERIVE,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
     }
 
     pms = OPENSSL_malloc(pmslen);
-    if (pms == NULL)
+    if (pms == NULL) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_DERIVE,
+                 ERR_R_MALLOC_FAILURE);
         goto err;
+    }
 
-    if (EVP_PKEY_derive(pctx, pms, &pmslen) <= 0)
+    if (EVP_PKEY_derive(pctx, pms, &pmslen) <= 0) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_DERIVE,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
+    }
 
     if (gensecret) {
+        /* SSLfatal() called as appropriate in the below functions */
         if (SSL_IS_TLS13(s)) {
             /*
              * If we are resuming then we already generated the early secret
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index 17a2413..7710ef0 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -20,10 +20,15 @@ static const ERR_STRING_DATA SSL_str_functs[] = {
      "bytes_to_cipher_list"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_CHECK_SUITEB_CIPHER_LIST, 0),
      "check_suiteb_cipher_list"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_CONSTRUCT_CA_NAMES, 0), "construct_ca_names"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_CONSTRUCT_KEY_EXCHANGE_TBS, 0),
+     "construct_key_exchange_tbs"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_CREATE_SYNTHETIC_MESSAGE_HASH, 0),
      "create_synthetic_message_hash"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_CT_MOVE_SCTS, 0), "ct_move_scts"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_CT_STRICT, 0), "ct_strict"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_CUSTOM_EXT_ADD, 0), "custom_ext_add"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_CUSTOM_EXT_PARSE, 0), "custom_ext_parse"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_D2I_SSL_SESSION, 0), "d2i_SSL_SESSION"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_DANE_CTX_ENABLE, 0), "dane_ctx_enable"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_DANE_MTYPE_SET, 0), "dane_mtype_set"},
@@ -59,29 +64,60 @@ static const ERR_STRING_DATA SSL_str_functs[] = {
      "dtls_get_reassembled_message"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS_PROCESS_HELLO_VERIFY, 0),
      "dtls_process_hello_verify"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_DTLS_WAIT_FOR_DRY, 0), "dtls_wait_for_dry"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_EARLY_DATA_COUNT_OK, 0),
      "early_data_count_ok"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_EARLY_DATA, 0), "final_early_data"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_EC_PT_FORMATS, 0),
      "final_ec_pt_formats"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_EMS, 0), "final_ems"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_KEY_SHARE, 0), "final_key_share"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_MAXFRAGMENTLEN, 0),
+     "final_maxfragmentlen"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_RENEGOTIATE, 0), "final_renegotiate"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_SERVER_NAME, 0), "final_server_name"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_SIG_ALGS, 0), "final_sig_algs"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_GET_CERT_VERIFY_TBS_DATA, 0),
+     "get_cert_verify_tbs_data"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_NSS_KEYLOG_INT, 0), "nss_keylog_int"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_OPENSSL_INIT_SSL, 0), "OPENSSL_init_ssl"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_CLIENT13_READ_TRANSITION, 0), ""},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_CLIENT13_WRITE_TRANSITION, 0),
+     "ossl_statem_client13_write_transition"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_CLIENT_CONSTRUCT_MESSAGE, 0), ""},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_CLIENT_POST_PROCESS_MESSAGE, 0),
+     "ossl_statem_client_post_process_message"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_CLIENT_PROCESS_MESSAGE, 0),
+     "ossl_statem_client_process_message"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION, 0),
      "ossl_statem_client_read_transition"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_CLIENT_WRITE_TRANSITION, 0),
+     "ossl_statem_client_write_transition"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER13_READ_TRANSITION, 0), ""},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER13_WRITE_TRANSITION, 0),
+     "ossl_statem_server13_write_transition"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER_CONSTRUCT_MESSAGE, 0), ""},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER_POST_PROCESS_MESSAGE, 0),
+     "ossl_statem_server_post_process_message"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER_POST_WORK, 0),
+     "ossl_statem_server_post_work"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER_PROCESS_MESSAGE, 0),
+     "ossl_statem_server_process_message"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION, 0),
      "ossl_statem_server_read_transition"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_OSSL_STATEM_SERVER_WRITE_TRANSITION, 0),
+     "ossl_statem_server_write_transition"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_PARSE_CA_NAMES, 0), "parse_ca_names"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_PROCESS_KEY_SHARE_EXT, 0), ""},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_READ_STATE_MACHINE, 0), "read_state_machine"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_SET_CLIENT_CIPHERSUITE, 0),
      "set_client_ciphersuite"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_SRP_GENERATE_CLIENT_MASTER_SECRET, 0),
+     "srp_generate_client_master_secret"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_SRP_GENERATE_SERVER_MASTER_SECRET, 0),
+     "srp_generate_server_master_secret"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_SRP_VERIFY_SERVER_PARAM, 0),
+     "srp_verify_server_param"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_CHANGE_CIPHER_STATE, 0),
      "ssl3_change_cipher_state"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, 0),
@@ -94,6 +130,7 @@ static const ERR_STRING_DATA SSL_str_functs[] = {
      "ssl3_do_change_cipher_spec"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_FINAL_FINISH_MAC, 0),
      "ssl3_final_finish_mac"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_FINISH_MAC, 0), "ssl3_finish_mac"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_GENERATE_KEY_BLOCK, 0),
      "ssl3_generate_key_block"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_GENERATE_MASTER_SECRET, 0),
@@ -143,8 +180,12 @@ static const ERR_STRING_DATA SSL_str_functs[] = {
     {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CHECK_PRIVATE_KEY, 0),
      "SSL_check_private_key"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT, 0), ""},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CHECK_SRP_EXT_CLIENTHELLO, 0),
+     "ssl_check_srp_ext_ClientHello"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG, 0),
      "ssl_check_srvr_ecc_cert_and_alg"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CHOOSE_CLIENT_VERSION, 0),
+     "ssl_choose_client_version"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CIPHER_LIST_TO_BYTES, 0),
      "ssl_cipher_list_to_bytes"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CIPHER_PROCESS_RULESTR, 0),
@@ -206,10 +247,13 @@ static const ERR_STRING_DATA SSL_str_functs[] = {
      "SSL_CTX_use_serverinfo_file"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_DANE_DUP, 0), "ssl_dane_dup"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_DANE_ENABLE, 0), "SSL_dane_enable"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_DERIVE, 0), "ssl_derive"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_DO_CONFIG, 0), "ssl_do_config"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_DO_HANDSHAKE, 0), "SSL_do_handshake"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_DUP_CA_LIST, 0), "SSL_dup_CA_list"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_ENABLE_CT, 0), "SSL_enable_ct"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_GENERATE_PKEY_GROUP, 0),
+     "ssl_generate_pkey_group"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_GENERATE_SESSION_ID, 0),
      "ssl_generate_session_id"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_GET_NEW_SESSION, 0),
@@ -218,6 +262,7 @@ static const ERR_STRING_DATA SSL_str_functs[] = {
      "ssl_get_prev_session"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_GET_SERVER_CERT_INDEX, 0), ""},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_GET_SIGN_PKEY, 0), ""},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_HANDSHAKE_HASH, 0), "ssl_handshake_hash"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_INIT_WBIO_BUFFER, 0),
      "ssl_init_wbio_buffer"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_KEY_UPDATE, 0), "SSL_key_update"},
@@ -228,6 +273,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = {
      "ssl_log_rsa_client_key_exchange"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_MODULE_INIT, 0), "ssl_module_init"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_NEW, 0), "SSL_new"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_NEXT_PROTO_VALIDATE, 0),
+     "ssl_next_proto_validate"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT, 0), ""},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT, 0), ""},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT, 0), ""},
@@ -315,6 +362,11 @@ static const ERR_STRING_DATA SSL_str_functs[] = {
     {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS12_COPY_SIGALGS, 0), "tls12_copy_sigalgs"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS13_CHANGE_CIPHER_STATE, 0),
      "tls13_change_cipher_state"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS13_FINAL_FINISH_MAC, 0),
+     "tls13_final_finish_mac"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS13_GENERATE_SECRET, 0),
+     "tls13_generate_secret"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS13_HKDF_EXPAND, 0), "tls13_hkdf_expand"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS13_SETUP_KEY_BLOCK, 0),
      "tls13_setup_key_block"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS1_CHANGE_CIPHER_STATE, 0),
@@ -474,28 +526,71 @@ static const ERR_STRING_DATA SSL_str_functs[] = {
      "tls_construct_stoc_use_srtp"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, 0),
      "tls_early_post_process_client_hello"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_FINISH_HANDSHAKE, 0),
+     "tls_finish_handshake"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_GET_MESSAGE_BODY, 0),
      "tls_get_message_body"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_GET_MESSAGE_HEADER, 0),
      "tls_get_message_header"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_HANDLE_ALPN, 0), "tls_handle_alpn"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_HANDLE_STATUS_REQUEST, 0),
+     "tls_handle_status_request"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CERTIFICATE_AUTHORITIES, 0),
+     "tls_parse_certificate_authorities"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CLIENTHELLO_TLSEXT, 0), ""},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_ALPN, 0),
+     "tls_parse_ctos_alpn"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_EARLY_DATA, 0),
+     "tls_parse_ctos_early_data"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS, 0),
+     "tls_parse_ctos_ec_pt_formats"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_EMS, 0), "tls_parse_ctos_ems"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_KEY_SHARE, 0),
      "tls_parse_ctos_key_share"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN, 0),
+     "tls_parse_ctos_maxfragmentlen"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_PSK, 0), "tls_parse_ctos_psk"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES, 0),
+     "tls_parse_ctos_psk_kex_modes"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE, 0),
      "tls_parse_ctos_renegotiate"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_SERVER_NAME, 0),
+     "tls_parse_ctos_server_name"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_SESSION_TICKET, 0),
+     "tls_parse_ctos_session_ticket"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_SIG_ALGS, 0),
+     "tls_parse_ctos_sig_algs"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_SRP, 0), "tls_parse_ctos_srp"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, 0),
+     "tls_parse_ctos_status_request"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS, 0),
+     "tls_parse_ctos_supported_groups"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_CTOS_USE_SRTP, 0),
      "tls_parse_ctos_use_srtp"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_ALPN, 0),
+     "tls_parse_stoc_alpn"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_COOKIE, 0),
      "tls_parse_stoc_cookie"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_EARLY_DATA, 0),
      "tls_parse_stoc_early_data"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_EARLY_DATA_INFO, 0), ""},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS, 0),
+     "tls_parse_stoc_ec_pt_formats"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_KEY_SHARE, 0),
      "tls_parse_stoc_key_share"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN, 0),
+     "tls_parse_stoc_maxfragmentlen"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_NPN, 0), "tls_parse_stoc_npn"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_PSK, 0), "tls_parse_stoc_psk"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_RENEGOTIATE, 0),
      "tls_parse_stoc_renegotiate"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_SCT, 0), "tls_parse_stoc_sct"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_SERVER_NAME, 0),
+     "tls_parse_stoc_server_name"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_SESSION_TICKET, 0),
+     "tls_parse_stoc_session_ticket"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_STATUS_REQUEST, 0),
+     "tls_parse_stoc_status_request"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PARSE_STOC_USE_SRTP, 0),
      "tls_parse_stoc_use_srtp"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_POST_PROCESS_CLIENT_HELLO, 0),
@@ -571,6 +666,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = {
      "tls_setup_handshake"},
     {ERR_PACK(ERR_LIB_SSL, SSL_F_USE_CERTIFICATE_CHAIN_FILE, 0),
      "use_certificate_chain_file"},
+    {ERR_PACK(ERR_LIB_SSL, SSL_F_WRITE_STATE_MACHINE, 0),
+     "write_state_machine"},
     {0, NULL}
 };
 
@@ -592,15 +689,19 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_DECOMPRESSION), "bad decompression"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_DH_VALUE), "bad dh value"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_DIGEST_LENGTH), "bad digest length"},
+    {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_EARLY_DATA), "bad early data"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_ECC_CERT), "bad ecc cert"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_ECPOINT), "bad ecpoint"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_EXTENSION), "bad extension"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_HANDSHAKE_LENGTH),
     "bad handshake length"},
+    {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_HANDSHAKE_STATE),
+    "bad handshake state"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_HELLO_REQUEST), "bad hello request"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_KEY_SHARE), "bad key share"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_KEY_UPDATE), "bad key update"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_LENGTH), "bad length"},
+    {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_PACKET), "bad packet"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_PACKET_LENGTH), "bad packet length"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_PROTOCOL_VERSION_NUMBER),
     "bad protocol version number"},
@@ -617,10 +718,13 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_SSL_FILETYPE), "bad ssl filetype"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_VALUE), "bad value"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_WRITE_RETRY), "bad write retry"},
+    {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BINDER_DOES_NOT_VERIFY),
+    "binder does not verify"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BIO_NOT_SET), "bio not set"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BLOCK_CIPHER_PAD_IS_WRONG),
     "block cipher pad is wrong"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BN_LIB), "bn lib"},
+    {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CALLBACK_FAILED), "callback failed"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CANNOT_CHANGE_CIPHER),
     "cannot change cipher"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CA_DN_LENGTH_MISMATCH),
@@ -739,7 +843,11 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INCONSISTENT_EARLY_DATA_SNI),
     "inconsistent early data sni"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INCONSISTENT_EXTMS), "inconsistent extms"},
+    {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INSUFFICIENT_SECURITY),
+    "insufficient security"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_ALERT), "invalid alert"},
+    {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_CERTIFICATE_OR_ALG),
+    "invalid certificate or alg"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_COMMAND), "invalid command"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_COMPRESSION_ALGORITHM),
     "invalid compression algorithm"},
@@ -773,6 +881,7 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
     "missing dsa signing cert"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_ECDSA_SIGNING_CERT),
     "missing ecdsa signing cert"},
+    {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_FATAL), "missing fatal"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_RSA_CERTIFICATE),
     "missing rsa certificate"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_RSA_ENCRYPTING_CERT),
@@ -792,6 +901,8 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
     "missing tmp ecdh key"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NOT_ON_RECORD_BOUNDARY),
     "not on record boundary"},
+    {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_APPLICATION_PROTOCOL),
+    "no application protocol"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_CERTIFICATES_RETURNED),
     "no certificates returned"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_CERTIFICATE_ASSIGNED),
@@ -838,6 +949,7 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
     "old session cipher not returned"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED),
     "old session compression algorithm not returned"},
+    {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_OVERFLOW_ERROR), "overflow error"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PACKET_LENGTH_TOO_LONG),
     "packet length too long"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PARSE_TLSEXT), "parse tlsext"},
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index b1173f0..a215f68 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -4201,16 +4201,22 @@ int ssl_handshake_hash(SSL *s, unsigned char *out, size_t outlen,
     int hashleni = EVP_MD_CTX_size(hdgst);
     int ret = 0;
 
-    if (hashleni < 0 || (size_t)hashleni > outlen)
+    if (hashleni < 0 || (size_t)hashleni > outlen) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_HANDSHAKE_HASH,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
+    }
 
     ctx = EVP_MD_CTX_new();
     if (ctx == NULL)
         goto err;
 
     if (!EVP_MD_CTX_copy_ex(ctx, hdgst)
-        || EVP_DigestFinal_ex(ctx, out, NULL) <= 0)
+        || EVP_DigestFinal_ex(ctx, out, NULL) <= 0) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_HANDSHAKE_HASH,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
+    }
 
     *hashlen = hashleni;
 
@@ -4630,7 +4636,8 @@ int ssl_validate_ct(SSL *s)
 
     ctx = CT_POLICY_EVAL_CTX_new();
     if (ctx == NULL) {
-        SSLerr(SSL_F_SSL_VALIDATE_CT, ERR_R_MALLOC_FAILURE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_VALIDATE_CT,
+                 ERR_R_MALLOC_FAILURE);
         goto end;
     }
 
@@ -4658,13 +4665,17 @@ int ssl_validate_ct(SSL *s)
      * ought to correspond to an inability to carry out its duties.
      */
     if (SCT_LIST_validate(scts, ctx) < 0) {
-        SSLerr(SSL_F_SSL_VALIDATE_CT, SSL_R_SCT_VERIFICATION_FAILED);
+        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_SSL_VALIDATE_CT,
+                 SSL_R_SCT_VERIFICATION_FAILED);
         goto end;
     }
 
     ret = s->ct_validation_callback(ctx, scts, s->ct_validation_callback_arg);
     if (ret < 0)
         ret = 0;                /* This function returns 0 on failure */
+    if (!ret)
+        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_SSL_VALIDATE_CT,
+                 SSL_R_CALLBACK_FAILED);
 
  end:
     CT_POLICY_EVAL_CTX_free(ctx);
@@ -4899,7 +4910,8 @@ static int nss_keylog_int(const char *prefix,
     prefix_len = strlen(prefix);
     out_len = prefix_len + (2*parameter_1_len) + (2*parameter_2_len) + 3;
     if ((out = cursor = OPENSSL_malloc(out_len)) == NULL) {
-        SSLerr(SSL_F_NSS_KEYLOG_INT, ERR_R_MALLOC_FAILURE);
+        SSLfatal(ssl, SSL_AD_INTERNAL_ERROR, SSL_F_NSS_KEYLOG_INT,
+                 ERR_R_MALLOC_FAILURE);
         return 0;
     }
 
@@ -4932,7 +4944,8 @@ int ssl_log_rsa_client_key_exchange(SSL *ssl,
                                     size_t premaster_len)
 {
     if (encrypted_premaster_len < 8) {
-        SSLerr(SSL_F_SSL_LOG_RSA_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+        SSLfatal(ssl, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_SSL_LOG_RSA_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
@@ -4960,23 +4973,21 @@ int ssl_log_secret(SSL *ssl,
 
 #define SSLV2_CIPHER_LEN    3
 
-int ssl_cache_cipherlist(SSL *s, PACKET *cipher_suites, int sslv2format,
-                         int *al)
+int ssl_cache_cipherlist(SSL *s, PACKET *cipher_suites, int sslv2format)
 {
     int n;
 
     n = sslv2format ? SSLV2_CIPHER_LEN : TLS_CIPHER_LEN;
 
     if (PACKET_remaining(cipher_suites) == 0) {
-        SSLerr(SSL_F_SSL_CACHE_CIPHERLIST, SSL_R_NO_CIPHERS_SPECIFIED);
-        *al = SSL_AD_ILLEGAL_PARAMETER;
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SSL_CACHE_CIPHERLIST,
+                 SSL_R_NO_CIPHERS_SPECIFIED);
         return 0;
     }
 
     if (PACKET_remaining(cipher_suites) % n != 0) {
-        SSLerr(SSL_F_SSL_CACHE_CIPHERLIST,
-               SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST);
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL_CACHE_CIPHERLIST,
+                 SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST);
         return 0;
     }
 
@@ -5000,8 +5011,9 @@ int ssl_cache_cipherlist(SSL *s, PACKET *cipher_suites, int sslv2format,
         raw = OPENSSL_malloc(numciphers * TLS_CIPHER_LEN);
         s->s3->tmp.ciphers_raw = raw;
         if (raw == NULL) {
-            *al = SSL_AD_INTERNAL_ERROR;
-            goto err;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CACHE_CIPHERLIST,
+                     ERR_R_MALLOC_FAILURE);
+            return 0;
         }
         for (s->s3->tmp.ciphers_rawlen = 0;
              PACKET_remaining(&sslv2ciphers) > 0;
@@ -5012,41 +5024,40 @@ int ssl_cache_cipherlist(SSL *s, PACKET *cipher_suites, int sslv2format,
                                               TLS_CIPHER_LEN))
                     || (leadbyte != 0
                         && !PACKET_forward(&sslv2ciphers, TLS_CIPHER_LEN))) {
-                *al = SSL_AD_DECODE_ERROR;
+                SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL_CACHE_CIPHERLIST,
+                         SSL_R_BAD_PACKET);
                 OPENSSL_free(s->s3->tmp.ciphers_raw);
                 s->s3->tmp.ciphers_raw = NULL;
                 s->s3->tmp.ciphers_rawlen = 0;
-                goto err;
+                return 0;
             }
             if (leadbyte == 0)
                 s->s3->tmp.ciphers_rawlen += TLS_CIPHER_LEN;
         }
     } else if (!PACKET_memdup(cipher_suites, &s->s3->tmp.ciphers_raw,
                            &s->s3->tmp.ciphers_rawlen)) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        goto err;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CACHE_CIPHERLIST,
+                 ERR_R_INTERNAL_ERROR);
+        return 0;
     }
     return 1;
- err:
-    return 0;
 }
 
 int SSL_bytes_to_cipher_list(SSL *s, const unsigned char *bytes, size_t len,
                              int isv2format, STACK_OF(SSL_CIPHER) **sk,
                              STACK_OF(SSL_CIPHER) **scsvs)
 {
-    int alert;
     PACKET pkt;
 
     if (!PACKET_buf_init(&pkt, bytes, len))
         return 0;
-    return bytes_to_cipher_list(s, &pkt, sk, scsvs, isv2format, &alert);
+    return bytes_to_cipher_list(s, &pkt, sk, scsvs, isv2format, 0);
 }
 
 int bytes_to_cipher_list(SSL *s, PACKET *cipher_suites,
                          STACK_OF(SSL_CIPHER) **skp,
                          STACK_OF(SSL_CIPHER) **scsvs_out,
-                         int sslv2format, int *al)
+                         int sslv2format, int fatal)
 {
     const SSL_CIPHER *c;
     STACK_OF(SSL_CIPHER) *sk = NULL;
@@ -5058,23 +5069,32 @@ int bytes_to_cipher_list(SSL *s, PACKET *cipher_suites,
     n = sslv2format ? SSLV2_CIPHER_LEN : TLS_CIPHER_LEN;
 
     if (PACKET_remaining(cipher_suites) == 0) {
-        SSLerr(SSL_F_BYTES_TO_CIPHER_LIST, SSL_R_NO_CIPHERS_SPECIFIED);
-        *al = SSL_AD_ILLEGAL_PARAMETER;
+        if (fatal)
+            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_BYTES_TO_CIPHER_LIST,
+                     SSL_R_NO_CIPHERS_SPECIFIED);
+        else
+            SSLerr(SSL_F_BYTES_TO_CIPHER_LIST, SSL_R_NO_CIPHERS_SPECIFIED);
         return 0;
     }
 
     if (PACKET_remaining(cipher_suites) % n != 0) {
-        SSLerr(SSL_F_BYTES_TO_CIPHER_LIST,
-               SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST);
-        *al = SSL_AD_DECODE_ERROR;
+        if (fatal)
+            SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_BYTES_TO_CIPHER_LIST,
+                     SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST);
+        else
+            SSLerr(SSL_F_BYTES_TO_CIPHER_LIST,
+                   SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST);
         return 0;
     }
 
     sk = sk_SSL_CIPHER_new_null();
     scsvs = sk_SSL_CIPHER_new_null();
     if (sk == NULL || scsvs == NULL) {
-        SSLerr(SSL_F_BYTES_TO_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
-        *al = SSL_AD_INTERNAL_ERROR;
+        if (fatal)
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_BYTES_TO_CIPHER_LIST,
+                     ERR_R_MALLOC_FAILURE);
+        else
+            SSLerr(SSL_F_BYTES_TO_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
@@ -5092,15 +5112,21 @@ int bytes_to_cipher_list(SSL *s, PACKET *cipher_suites,
         if (c != NULL) {
             if ((c->valid && !sk_SSL_CIPHER_push(sk, c)) ||
                 (!c->valid && !sk_SSL_CIPHER_push(scsvs, c))) {
-                SSLerr(SSL_F_BYTES_TO_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
-                *al = SSL_AD_INTERNAL_ERROR;
+                if (fatal)
+                    SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                             SSL_F_BYTES_TO_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
+                else
+                    SSLerr(SSL_F_BYTES_TO_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
                 goto err;
             }
         }
     }
     if (PACKET_remaining(cipher_suites) > 0) {
-        *al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_BYTES_TO_CIPHER_LIST, SSL_R_BAD_LENGTH);
+        if (fatal)
+            SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_BYTES_TO_CIPHER_LIST,
+                     SSL_R_BAD_LENGTH);
+        else
+            SSLerr(SSL_F_BYTES_TO_CIPHER_LIST, SSL_R_BAD_LENGTH);
         goto err;
     }
 
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 5e1426a..c812eef 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -2132,7 +2132,7 @@ void ssl_cert_clear_certs(CERT *c);
 void ssl_cert_free(CERT *c);
 __owur int ssl_generate_session_id(SSL *s, SSL_SESSION *ss);
 __owur int ssl_get_new_session(SSL *s, int session);
-__owur int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello, int *al);
+__owur int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello);
 __owur SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket);
 __owur int ssl_cipher_id_cmp(const SSL_CIPHER *a, const SSL_CIPHER *b);
 DECLARE_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER, ssl_cipher_id);
@@ -2144,12 +2144,11 @@ __owur STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *meth,
                                                     **sorted,
                                                     const char *rule_str,
                                                     CERT *c);
-__owur int ssl_cache_cipherlist(SSL *s, PACKET *cipher_suites,
-                                int sslv2format, int *al);
+__owur int ssl_cache_cipherlist(SSL *s, PACKET *cipher_suites, int sslv2format);
 __owur int bytes_to_cipher_list(SSL *s, PACKET *cipher_suites,
                                 STACK_OF(SSL_CIPHER) **skp,
                                 STACK_OF(SSL_CIPHER) **scsvs, int sslv2format,
-                                int *al);
+                                int fatal);
 void ssl_update_cache(SSL *s, int mode);
 __owur int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
                               const EVP_MD **md, int *mac_pkey_type,
@@ -2231,7 +2230,7 @@ __owur size_t ssl3_final_finish_mac(SSL *s, const char *sender, size_t slen,
 __owur int ssl3_finish_mac(SSL *s, const unsigned char *buf, size_t len);
 void ssl3_free_digest_list(SSL *s);
 __owur unsigned long ssl3_output_cert_chain(SSL *s, WPACKET *pkt,
-                                            CERT_PKEY *cpk, int *al);
+                                            CERT_PKEY *cpk);
 __owur const SSL_CIPHER *ssl3_choose_cipher(SSL *ssl,
                                             STACK_OF(SSL_CIPHER) *clnt,
                                             STACK_OF(SSL_CIPHER) *srvr);
@@ -2267,8 +2266,7 @@ __owur int ssl_check_version_downgrade(SSL *s);
 __owur int ssl_set_version_bound(int method_version, int version, int *bound);
 __owur int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello,
                                      DOWNGRADE *dgrd);
-__owur int ssl_choose_client_version(SSL *s, int version, int checkdgrd,
-                                     int *al);
+__owur int ssl_choose_client_version(SSL *s, int version, int checkdgrd);
 int ssl_get_min_max_version(const SSL *s, int *min_version, int *max_version);
 
 __owur long tls1_default_timeout(void);
@@ -2386,7 +2384,7 @@ __owur int tls1_set_groups_list(uint16_t **pext, size_t *pextlen,
 void tls1_get_formatlist(SSL *s, const unsigned char **pformats,
                          size_t *num_formats);
 __owur int tls1_check_ec_tmp_key(SSL *s, unsigned long id);
-__owur EVP_PKEY *ssl_generate_pkey_group(uint16_t id);
+__owur EVP_PKEY *ssl_generate_pkey_group(SSL *s, uint16_t id);
 __owur EVP_PKEY *ssl_generate_param_group(uint16_t id);
 #  endif                        /* OPENSSL_NO_EC */
 
@@ -2444,7 +2442,7 @@ __owur int ssl_security_cert(SSL *s, SSL_CTX *ctx, X509 *x, int vfy, int is_ee);
 __owur int ssl_security_cert_chain(SSL *s, STACK_OF(X509) *sk, X509 *ex,
                                    int vfy);
 
-int tls_choose_sigalg(SSL *s, int *al);
+int tls_choose_sigalg(SSL *s, int fatalerrs);
 
 __owur EVP_MD_CTX *ssl_replace_hash(EVP_MD_CTX **hash, const EVP_MD *md);
 void ssl_clear_hash_ctx(EVP_MD_CTX **hash);
@@ -2508,7 +2506,7 @@ __owur int ssl3_cbc_digest_record(const EVP_MD_CTX *ctx,
 
 __owur int srp_generate_server_master_secret(SSL *s);
 __owur int srp_generate_client_master_secret(SSL *s);
-__owur int srp_verify_server_param(SSL *s, int *al);
+__owur int srp_verify_server_param(SSL *s);
 
 /* statem/extensions_cust.c */
 
@@ -2520,9 +2518,9 @@ void custom_ext_init(custom_ext_methods *meths);
 
 __owur int custom_ext_parse(SSL *s, unsigned int context, unsigned int ext_type,
                             const unsigned char *ext_data, size_t ext_size,
-                            X509 *x, size_t chainidx, int *al);
+                            X509 *x, size_t chainidx);
 __owur int custom_ext_add(SSL *s, int context, WPACKET *pkt, X509 *x,
-                          size_t chainidx, int maxversion, int *al);
+                          size_t chainidx, int maxversion);
 
 __owur int custom_exts_copy(custom_ext_methods *dst,
                             const custom_ext_methods *src);
diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c
index c8d1cc3..08c0037 100644
--- a/ssl/ssl_sess.c
+++ b/ssl/ssl_sess.c
@@ -322,7 +322,8 @@ int ssl_generate_session_id(SSL *s, SSL_SESSION *ss)
         ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
         break;
     default:
-        SSLerr(SSL_F_SSL_GENERATE_SESSION_ID, SSL_R_UNSUPPORTED_SSL_VERSION);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_SESSION_ID,
+                 SSL_R_UNSUPPORTED_SSL_VERSION);
         return 0;
     }
 
@@ -360,8 +361,8 @@ int ssl_generate_session_id(SSL *s, SSL_SESSION *ss)
     tmp = (int)ss->session_id_length;
     if (!cb(s, ss->session_id, &tmp)) {
         /* The callback failed */
-        SSLerr(SSL_F_SSL_GENERATE_SESSION_ID,
-               SSL_R_SSL_SESSION_ID_CALLBACK_FAILED);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_SESSION_ID,
+                 SSL_R_SSL_SESSION_ID_CALLBACK_FAILED);
         return 0;
     }
     /*
@@ -370,15 +371,16 @@ int ssl_generate_session_id(SSL *s, SSL_SESSION *ss)
      */
     if (tmp == 0 || tmp > ss->session_id_length) {
         /* The callback set an illegal length */
-        SSLerr(SSL_F_SSL_GENERATE_SESSION_ID,
-               SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_SESSION_ID,
+                 SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH);
         return 0;
     }
     ss->session_id_length = tmp;
     /* Finally, check for a conflict */
     if (SSL_has_matching_session_id(s, ss->session_id,
                                     (unsigned int)ss->session_id_length)) {
-        SSLerr(SSL_F_SSL_GENERATE_SESSION_ID, SSL_R_SSL_SESSION_ID_CONFLICT);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GENERATE_SESSION_ID,
+                 SSL_R_SSL_SESSION_ID_CONFLICT);
         return 0;
     }
 
@@ -391,8 +393,11 @@ int ssl_get_new_session(SSL *s, int session)
 
     SSL_SESSION *ss = NULL;
 
-    if ((ss = SSL_SESSION_new()) == NULL)
+    if ((ss = SSL_SESSION_new()) == NULL) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_NEW_SESSION,
+                 ERR_R_MALLOC_FAILURE);
         return 0;
+    }
 
     /* If the context has a default timeout, use it */
     if (s->session_ctx->session_timeout == 0)
@@ -405,6 +410,7 @@ int ssl_get_new_session(SSL *s, int session)
 
     if (session) {
         if (!ssl_generate_session_id(s, ss)) {
+            /* SSLfatal() already called */
             SSL_SESSION_free(ss);
             return 0;
         }
@@ -412,7 +418,8 @@ int ssl_get_new_session(SSL *s, int session)
         if (s->ext.hostname) {
             ss->ext.hostname = OPENSSL_strdup(s->ext.hostname);
             if (ss->ext.hostname == NULL) {
-                SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_INTERNAL_ERROR);
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_NEW_SESSION,
+                         ERR_R_INTERNAL_ERROR);
                 SSL_SESSION_free(ss);
                 return 0;
             }
@@ -422,7 +429,8 @@ int ssl_get_new_session(SSL *s, int session)
     }
 
     if (s->sid_ctx_length > sizeof ss->sid_ctx) {
-        SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_NEW_SESSION,
+                 ERR_R_INTERNAL_ERROR);
         SSL_SESSION_free(ss);
         return 0;
     }
@@ -456,7 +464,7 @@ int ssl_get_new_session(SSL *s, int session)
  *   - Both for new and resumed sessions, s->ext.ticket_expected is set to 1
  *     if the server should issue a new session ticket (to 0 otherwise).
  */
-int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello, int *al)
+int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello)
 {
     /* This is used only by servers. */
 
@@ -468,9 +476,9 @@ int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello, int *al)
     if (SSL_IS_TLS13(s)) {
         if (!tls_parse_extension(s, TLSEXT_IDX_psk_kex_modes,
                                  SSL_EXT_CLIENT_HELLO, hello->pre_proc_exts,
-                                 NULL, 0, al)
+                                 NULL, 0)
                 || !tls_parse_extension(s, TLSEXT_IDX_psk, SSL_EXT_CLIENT_HELLO,
-                                        hello->pre_proc_exts, NULL, 0, al))
+                                        hello->pre_proc_exts, NULL, 0))
             return -1;
 
         ret = s->session;
@@ -481,6 +489,8 @@ int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello, int *al)
         case TICKET_FATAL_ERR_MALLOC:
         case TICKET_FATAL_ERR_OTHER:
             fatal = 1;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_PREV_SESSION,
+                     ERR_R_INTERNAL_ERROR);
             goto err;
         case TICKET_NONE:
         case TICKET_EMPTY:
@@ -584,8 +594,8 @@ int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello, int *al)
          * noticing).
          */
 
-        SSLerr(SSL_F_SSL_GET_PREV_SESSION,
-               SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_PREV_SESSION,
+                 SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED);
         fatal = 1;
         goto err;
     }
@@ -604,8 +614,8 @@ int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello, int *al)
     if (ret->flags & SSL_SESS_FLAG_EXTMS) {
         /* If old session includes extms, but new does not: abort handshake */
         if (!(s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS)) {
-            SSLerr(SSL_F_SSL_GET_PREV_SESSION, SSL_R_INCONSISTENT_EXTMS);
-            ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SSL_GET_PREV_SESSION,
+                     SSL_R_INCONSISTENT_EXTMS);
             fatal = 1;
             goto err;
         }
@@ -640,10 +650,8 @@ int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello, int *al)
             s->ext.ticket_expected = 1;
         }
     }
-    if (fatal) {
-        *al = SSL_AD_INTERNAL_ERROR;
+    if (fatal)
         return -1;
-    }
 
     return 0;
 }
diff --git a/ssl/statem/extensions.c b/ssl/statem/extensions.c
index a72859c..464a5ef 100644
--- a/ssl/statem/extensions.c
+++ b/ssl/statem/extensions.c
@@ -12,14 +12,11 @@
 #include "../ssl_locl.h"
 #include "statem_locl.h"
 
-static int final_renegotiate(SSL *s, unsigned int context, int sent,
-                                     int *al);
+static int final_renegotiate(SSL *s, unsigned int context, int sent);
 static int init_server_name(SSL *s, unsigned int context);
-static int final_server_name(SSL *s, unsigned int context, int sent,
-                                     int *al);
+static int final_server_name(SSL *s, unsigned int context, int sent);
 #ifndef OPENSSL_NO_EC
-static int final_ec_pt_formats(SSL *s, unsigned int context, int sent,
-                                       int *al);
+static int final_ec_pt_formats(SSL *s, unsigned int context, int sent);
 #endif
 static int init_session_ticket(SSL *s, unsigned int context);
 #ifndef OPENSSL_NO_OCSP
@@ -29,33 +26,32 @@ static int init_status_request(SSL *s, unsigned int context);
 static int init_npn(SSL *s, unsigned int context);
 #endif
 static int init_alpn(SSL *s, unsigned int context);
-static int final_alpn(SSL *s, unsigned int context, int sent, int *al);
+static int final_alpn(SSL *s, unsigned int context, int sent);
 static int init_sig_algs(SSL *s, unsigned int context);
 static int init_certificate_authorities(SSL *s, unsigned int context);
 static EXT_RETURN tls_construct_certificate_authorities(SSL *s, WPACKET *pkt,
                                                         unsigned int context,
                                                         X509 *x,
-                                                        size_t chainidx,
-                                                        int *al);
+                                                        size_t chainidx);
 static int tls_parse_certificate_authorities(SSL *s, PACKET *pkt,
                                              unsigned int context, X509 *x,
-                                             size_t chainidx, int *al);
+                                             size_t chainidx);
 #ifndef OPENSSL_NO_SRP
 static int init_srp(SSL *s, unsigned int context);
 #endif
 static int init_etm(SSL *s, unsigned int context);
 static int init_ems(SSL *s, unsigned int context);
-static int final_ems(SSL *s, unsigned int context, int sent, int *al);
+static int final_ems(SSL *s, unsigned int context, int sent);
 static int init_psk_kex_modes(SSL *s, unsigned int context);
 #ifndef OPENSSL_NO_EC
-static int final_key_share(SSL *s, unsigned int context, int sent, int *al);
+static int final_key_share(SSL *s, unsigned int context, int sent);
 #endif
 #ifndef OPENSSL_NO_SRTP
 static int init_srtp(SSL *s, unsigned int context);
 #endif
-static int final_sig_algs(SSL *s, unsigned int context, int sent, int *al);
-static int final_early_data(SSL *s, unsigned int context, int sent, int *al);
-static int final_maxfragmentlen(SSL *s, unsigned int context, int sent, int *al);
+static int final_sig_algs(SSL *s, unsigned int context, int sent);
+static int final_early_data(SSL *s, unsigned int context, int sent);
+static int final_maxfragmentlen(SSL *s, unsigned int context, int sent);
 
 /* Structure to define a built-in extension */
 typedef struct extensions_definition_st {
@@ -73,22 +69,22 @@ typedef struct extensions_definition_st {
     int (*init)(SSL *s, unsigned int context);
     /* Parse extension sent from client to server */
     int (*parse_ctos)(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                      size_t chainidx, int *al);
+                      size_t chainidx);
     /* Parse extension send from server to client */
     int (*parse_stoc)(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                      size_t chainidx, int *al);
+                      size_t chainidx);
     /* Construct extension sent from server to client */
     EXT_RETURN (*construct_stoc)(SSL *s, WPACKET *pkt, unsigned int context,
-                                 X509 *x, size_t chainidx, int *al);
+                                 X509 *x, size_t chainidx);
     /* Construct extension sent from client to server */
     EXT_RETURN (*construct_ctos)(SSL *s, WPACKET *pkt, unsigned int context,
-                                 X509 *x, size_t chainidx, int *al);
+                                 X509 *x, size_t chainidx);
     /*
      * Finalise extension after parsing. Always called where an extensions was
      * initialised even if the extension was not present. |sent| is set to 1 if
      * the extension was seen, or 0 otherwise.
      */
-    int (*final)(SSL *s, unsigned int context, int sent, int *al);
+    int (*final)(SSL *s, unsigned int context, int sent);
 } EXTENSION_DEFINITION;
 
 /*
@@ -443,12 +439,11 @@ int extension_is_relevant(SSL *s, unsigned int extctx, unsigned int thisctx)
 /*
  * Gather a list of all the extensions from the data in |packet]. |context|
  * tells us which message this extension is for. The raw extension data is
- * stored in |*res| on success. In the event of an error the alert type to use
- * is stored in |*al|. We don't actually process the content of the extensions
- * yet, except to check their types. This function also runs the initialiser
- * functions for all known extensions if |init| is nonzero (whether we have
- * collected them or not). If successful the caller is responsible for freeing
- * the contents of |*res|.
+ * stored in |*res| on success. We don't actually process the content of the
+ * extensions yet, except to check their types. This function also runs the
+ * initialiser functions for all known extensions if |init| is nonzero (whether
+ * we have collected them or not). If successful the caller is responsible for
+ * freeing the contents of |*res|.
  *
  * Per http://tools.ietf.org/html/rfc5246#section-7.4.1.4, there may not be
  * more than one extension of the same type in a ClientHello or ServerHello.
@@ -458,8 +453,7 @@ int extension_is_relevant(SSL *s, unsigned int extctx, unsigned int thisctx)
  * extensions that we know about. We ignore others.
  */
 int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
-                           RAW_EXTENSION **res, int *al, size_t *len,
-                           int init)
+                           RAW_EXTENSION **res, size_t *len, int init)
 {
     PACKET extensions = *packet;
     size_t i = 0;
@@ -480,8 +474,8 @@ int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
     num_exts = OSSL_NELEM(ext_defs) + (exts != NULL ? exts->meths_count : 0);
     raw_extensions = OPENSSL_zalloc(num_exts * sizeof(*raw_extensions));
     if (raw_extensions == NULL) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_COLLECT_EXTENSIONS, ERR_R_MALLOC_FAILURE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_COLLECT_EXTENSIONS,
+                 ERR_R_MALLOC_FAILURE);
         return 0;
     }
 
@@ -493,8 +487,8 @@ int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
 
         if (!PACKET_get_net_2(&extensions, &type) ||
             !PACKET_get_length_prefixed_2(&extensions, &extension)) {
-            SSLerr(SSL_F_TLS_COLLECT_EXTENSIONS, SSL_R_BAD_EXTENSION);
-            *al = SSL_AD_DECODE_ERROR;
+            SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_COLLECT_EXTENSIONS,
+                     SSL_R_BAD_EXTENSION);
             goto err;
         }
         /*
@@ -507,8 +501,8 @@ int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
                 || (type == TLSEXT_TYPE_psk
                     && (context & SSL_EXT_CLIENT_HELLO) != 0
                     && PACKET_remaining(&extensions) != 0)) {
-            SSLerr(SSL_F_TLS_COLLECT_EXTENSIONS, SSL_R_BAD_EXTENSION);
-            *al = SSL_AD_ILLEGAL_PARAMETER;
+            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_COLLECT_EXTENSIONS,
+                     SSL_R_BAD_EXTENSION);
             goto err;
         }
         idx = thisex - raw_extensions;
@@ -534,8 +528,8 @@ int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
                 && type != TLSEXT_TYPE_renegotiate
                 && type != TLSEXT_TYPE_signed_certificate_timestamp
                 && (s->ext.extflags[idx] & SSL_EXT_FLAG_SENT) == 0) {
-            SSLerr(SSL_F_TLS_COLLECT_EXTENSIONS, SSL_R_UNSOLICITED_EXTENSION);
-            *al = SSL_AD_UNSUPPORTED_EXTENSION;
+            SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION,
+                     SSL_F_TLS_COLLECT_EXTENSIONS, SSL_R_UNSOLICITED_EXTENSION);
             goto err;
         }
         if (thisex != NULL) {
@@ -561,7 +555,7 @@ int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
             if (thisexd->init != NULL && (thisexd->context & context) != 0
                 && extension_is_relevant(s, thisexd->context, context)
                 && !thisexd->init(s, context)) {
-                *al = SSL_AD_INTERNAL_ERROR;
+                /* SSLfatal() already called */
                 goto err;
             }
         }
@@ -584,16 +578,15 @@ int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
  * given |context| and the parser has not already been run. If this is for a
  * Certificate message, then we also provide the parser with the relevant
  * Certificate |x| and its position in the |chainidx| with 0 being the first
- * Certificate. Returns 1 on success or 0 on failure. In the event of a failure
- * |*al| is populated with a suitable alert code. If an extension is not present
- * this counted as success.
+ * Certificate. Returns 1 on success or 0 on failure. If an extension is not
+ * present this counted as success.
  */
 int tls_parse_extension(SSL *s, TLSEXT_INDEX idx, int context,
-                        RAW_EXTENSION *exts, X509 *x, size_t chainidx, int *al)
+                        RAW_EXTENSION *exts, X509 *x, size_t chainidx)
 {
     RAW_EXTENSION *currext = &exts[idx];
     int (*parser)(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                  size_t chainidx, int *al) = NULL;
+                  size_t chainidx) = NULL;
 
     /* Skip if the extension is not present */
     if (!currext->present)
@@ -616,7 +609,7 @@ int tls_parse_extension(SSL *s, TLSEXT_INDEX idx, int context,
         parser = s->server ? extdef->parse_ctos : extdef->parse_stoc;
 
         if (parser != NULL)
-            return parser(s, &currext->data, context, x, chainidx, al);
+            return parser(s, &currext->data, context, x, chainidx);
 
         /*
          * If the parser is NULL we fall through to the custom extension
@@ -625,13 +618,10 @@ int tls_parse_extension(SSL *s, TLSEXT_INDEX idx, int context,
     }
 
     /* Parse custom extensions */
-    if (custom_ext_parse(s, context, currext->type,
-                         PACKET_data(&currext->data),
-                         PACKET_remaining(&currext->data),
-                         x, chainidx, al) <= 0)
-        return 0;
-
-    return 1;
+    return custom_ext_parse(s, context, currext->type,
+                            PACKET_data(&currext->data),
+                            PACKET_remaining(&currext->data),
+                            x, chainidx);
 }
 
 /*
@@ -639,11 +629,10 @@ int tls_parse_extension(SSL *s, TLSEXT_INDEX idx, int context,
  * finalisation for all extensions at the end if |fin| is nonzero, whether we
  * collected them or not. Returns 1 for success or 0 for failure. If we are
  * working on a Certificate message then we also pass the Certificate |x| and
- * its position in the |chainidx|, with 0 being the first certificate. On
- * failure, |*al| is populated with a suitable alert code.
+ * its position in the |chainidx|, with 0 being the first certificate.
  */
 int tls_parse_all_extensions(SSL *s, int context, RAW_EXTENSION *exts, X509 *x,
-                             size_t chainidx, int *al, int fin)
+                             size_t chainidx, int fin)
 {
     size_t i, numexts = OSSL_NELEM(ext_defs);
     const EXTENSION_DEFINITION *thisexd;
@@ -653,8 +642,10 @@ int tls_parse_all_extensions(SSL *s, int context, RAW_EXTENSION *exts, X509 *x,
 
     /* Parse each extension in turn */
     for (i = 0; i < numexts; i++) {
-        if (!tls_parse_extension(s, i, context, exts, x, chainidx, al))
+        if (!tls_parse_extension(s, i, context, exts, x, chainidx)) {
+            /* SSLfatal() already called */
             return 0;
+        }
     }
 
     if (fin) {
@@ -665,8 +656,10 @@ int tls_parse_all_extensions(SSL *s, int context, RAW_EXTENSION *exts, X509 *x,
         for (i = 0, thisexd = ext_defs; i < OSSL_NELEM(ext_defs);
              i++, thisexd++) {
             if (thisexd->final != NULL && (thisexd->context & context) != 0
-                && !thisexd->final(s, context, exts[i].present, al))
+                && !thisexd->final(s, context, exts[i].present)) {
+                /* SSLfatal() already called */
                 return 0;
+            }
         }
     }
 
@@ -702,23 +695,16 @@ int should_add_extension(SSL *s, unsigned int extctx, unsigned int thisctx,
  * them to |pkt|. If this is an extension for a Certificate in a Certificate
  * message, then |x| will be set to the Certificate we are handling, and
  * |chainidx| will indicate the position in the chainidx we are processing (with
- * 0 being the first in the chain). Returns 1 on success or 0 on failure. If a
- * failure occurs then |al| is populated with a suitable alert code. On a
+ * 0 being the first in the chain). Returns 1 on success or 0 on failure. On a
  * failure construction stops at the first extension to fail to construct.
  */
 int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context,
-                             X509 *x, size_t chainidx, int *al)
+                             X509 *x, size_t chainidx)
 {
     size_t i;
-    int min_version, max_version = 0, reason, tmpal;
+    int min_version, max_version = 0, reason;
     const EXTENSION_DEFINITION *thisexd;
 
-    /*
-     * Normally if something goes wrong during construction it's an internal
-     * error. We can always override this later.
-     */
-    tmpal = SSL_AD_INTERNAL_ERROR;
-
     if (!WPACKET_start_sub_packet_u16(pkt)
                /*
                 * If extensions are of zero length then we don't even add the
@@ -729,15 +715,17 @@ int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context,
                  (SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO)) != 0
                 && !WPACKET_set_flags(pkt,
                                      WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH))) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_EXTENSIONS, ERR_R_INTERNAL_ERROR);
-        goto err;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_EXTENSIONS,
+                 ERR_R_INTERNAL_ERROR);
+        return 0;
     }
 
     if ((context & SSL_EXT_CLIENT_HELLO) != 0) {
         reason = ssl_get_min_max_version(s, &min_version, &max_version);
         if (reason != 0) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_EXTENSIONS, reason);
-            goto err;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_EXTENSIONS,
+                     reason);
+            return 0;
         }
     }
 
@@ -746,14 +734,14 @@ int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context,
         /* On the server side with initialise during ClientHello parsing */
         custom_ext_init(&s->cert->custext);
     }
-    if (!custom_ext_add(s, context, pkt, x, chainidx, max_version, &tmpal)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_EXTENSIONS, ERR_R_INTERNAL_ERROR);
-        goto err;
+    if (!custom_ext_add(s, context, pkt, x, chainidx, max_version)) {
+        /* SSLfatal() already called */
+        return 0;
     }
 
     for (i = 0, thisexd = ext_defs; i < OSSL_NELEM(ext_defs); i++, thisexd++) {
         EXT_RETURN (*construct)(SSL *s, WPACKET *pkt, unsigned int context,
-                                X509 *x, size_t chainidx, int *al);
+                                X509 *x, size_t chainidx);
         EXT_RETURN ret;
 
         /* Skip if not relevant for our context */
@@ -766,9 +754,11 @@ int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context,
         if (construct == NULL)
             continue;
 
-        ret = construct(s, pkt, context, x, chainidx, &tmpal);
-        if (ret == EXT_RETURN_FAIL)
-            goto err;
+        ret = construct(s, pkt, context, x, chainidx);
+        if (ret == EXT_RETURN_FAIL) {
+            /* SSLfatal() already called */
+            return 0;
+        }
         if (ret == EXT_RETURN_SENT
                 && (context & (SSL_EXT_CLIENT_HELLO
                                | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST
@@ -777,27 +767,22 @@ int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context,
     }
 
     if (!WPACKET_close(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_EXTENSIONS, ERR_R_INTERNAL_ERROR);
-        goto err;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_EXTENSIONS,
+                 ERR_R_INTERNAL_ERROR);
+        return 0;
     }
 
     return 1;
-
- err:
-    *al = tmpal;
-    return 0;
 }
 
 /*
  * Built in extension finalisation and initialisation functions. All initialise
  * or finalise the associated extension type for the given |context|. For
  * finalisers |sent| is set to 1 if we saw the extension during parsing, and 0
- * otherwise. These functions return 1 on success or 0 on failure. In the event
- * of a failure then |*al| is populated with a suitable error code.
+ * otherwise. These functions return 1 on success or 0 on failure.
  */
 
-static int final_renegotiate(SSL *s, unsigned int context, int sent,
-                                     int *al)
+static int final_renegotiate(SSL *s, unsigned int context, int sent)
 {
     if (!s->server) {
         /*
@@ -807,9 +792,8 @@ static int final_renegotiate(SSL *s, unsigned int context, int sent,
         if (!(s->options & SSL_OP_LEGACY_SERVER_CONNECT)
                 && !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)
                 && !sent) {
-            *al = SSL_AD_HANDSHAKE_FAILURE;
-            SSLerr(SSL_F_FINAL_RENEGOTIATE,
-                   SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
+            SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_FINAL_RENEGOTIATE,
+                     SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
             return 0;
         }
 
@@ -820,9 +804,8 @@ static int final_renegotiate(SSL *s, unsigned int context, int sent,
     if (s->renegotiate
             && !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)
             && !sent) {
-        *al = SSL_AD_HANDSHAKE_FAILURE;
-        SSLerr(SSL_F_FINAL_RENEGOTIATE,
-               SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
+        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_FINAL_RENEGOTIATE,
+                 SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
         return 0;
     }
 
@@ -838,8 +821,7 @@ static int init_server_name(SSL *s, unsigned int context)
     return 1;
 }
 
-static int final_server_name(SSL *s, unsigned int context, int sent,
-                                     int *al)
+static int final_server_name(SSL *s, unsigned int context, int sent)
 {
     int ret = SSL_TLSEXT_ERR_NOACK, discard;
     int altmp = SSL_AD_UNRECOGNIZED_NAME;
@@ -890,23 +872,25 @@ static int final_server_name(SSL *s, unsigned int context, int sent,
                 ss->ext.tick_age_add = 0;
                 ss->ext.tick_identity = 0;
                 if (!ssl_generate_session_id(s, ss)) {
-                    ret = SSL_TLSEXT_ERR_ALERT_FATAL;
-                    altmp = SSL_AD_INTERNAL_ERROR;
+                    SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME,
+                             ERR_R_INTERNAL_ERROR);
+                    return 0;
                 }
             } else {
-                ret = SSL_TLSEXT_ERR_ALERT_FATAL;
-                altmp = SSL_AD_INTERNAL_ERROR;
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME,
+                         ERR_R_INTERNAL_ERROR);
+                return 0;
             }
         }
     }
 
     switch (ret) {
     case SSL_TLSEXT_ERR_ALERT_FATAL:
-        *al = altmp;
+        SSLfatal(s, altmp, SSL_F_FINAL_SERVER_NAME, SSL_R_CALLBACK_FAILED);
         return 0;
 
     case SSL_TLSEXT_ERR_ALERT_WARNING:
-        *al = altmp;
+        ssl3_send_alert(s, SSL3_AL_WARNING, altmp);
         return 1;
 
     case SSL_TLSEXT_ERR_NOACK:
@@ -919,8 +903,7 @@ static int final_server_name(SSL *s, unsigned int context, int sent,
 }
 
 #ifndef OPENSSL_NO_EC
-static int final_ec_pt_formats(SSL *s, unsigned int context, int sent,
-                                       int *al)
+static int final_ec_pt_formats(SSL *s, unsigned int context, int sent)
 {
     unsigned long alg_k, alg_a;
 
@@ -949,8 +932,8 @@ static int final_ec_pt_formats(SSL *s, unsigned int context, int sent,
                 break;
         }
         if (i == s->session->ext.ecpointformats_len) {
-            SSLerr(SSL_F_FINAL_EC_PT_FORMATS,
-                   SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST);
+            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_FINAL_EC_PT_FORMATS,
+                     SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST);
             return 0;
         }
     }
@@ -1008,7 +991,7 @@ static int init_alpn(SSL *s, unsigned int context)
     return 1;
 }
 
-static int final_alpn(SSL *s, unsigned int context, int sent, int *al)
+static int final_alpn(SSL *s, unsigned int context, int sent)
 {
     if (!s->server && !sent && s->session->ext.alpn_selected != NULL)
             s->ext.early_data_ok = 0;
@@ -1022,8 +1005,10 @@ static int final_alpn(SSL *s, unsigned int context, int sent, int *al)
      * we also have to do this before we decide whether to accept early_data.
      * In TLSv1.3 we've already negotiated our cipher so we do this call now.
      * For < TLSv1.3 we defer it until after cipher negotiation.
+     * 
+     * On failure SSLfatal() already called.
      */
-    return tls_handle_alpn(s, al);
+    return tls_handle_alpn(s);
 }
 
 static int init_sig_algs(SSL *s, unsigned int context)
@@ -1060,7 +1045,7 @@ static int init_ems(SSL *s, unsigned int context)
     return 1;
 }
 
-static int final_ems(SSL *s, unsigned int context, int sent, int *al)
+static int final_ems(SSL *s, unsigned int context, int sent)
 {
     if (!s->server && s->hit) {
         /*
@@ -1069,8 +1054,8 @@ static int final_ems(SSL *s, unsigned int context, int sent, int *al)
          */
         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);
+            SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_FINAL_EMS,
+                     SSL_R_INCONSISTENT_EXTMS);
             return 0;
         }
     }
@@ -1088,8 +1073,7 @@ static int init_certificate_authorities(SSL *s, unsigned int context)
 static EXT_RETURN tls_construct_certificate_authorities(SSL *s, WPACKET *pkt,
                                                         unsigned int context,
                                                         X509 *x,
-                                                        size_t chainidx,
-                                                        int *al)
+                                                        size_t chainidx)
 {
     const STACK_OF(X509_NAME) *ca_sk = SSL_get0_CA_list(s);
 
@@ -1097,25 +1081,37 @@ static EXT_RETURN tls_construct_certificate_authorities(SSL *s, WPACKET *pkt,
         return EXT_RETURN_NOT_SENT;
 
     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,
+        || !WPACKET_start_sub_packet_u16(pkt)) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_CERTIFICATE_AUTHORITIES,
                ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
+    if (!construct_ca_names(s, pkt)) {
+        /* SSLfatal() already called */
+        return EXT_RETURN_FAIL;
+    }
+
+    if (!WPACKET_close(pkt)) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_CERTIFICATE_AUTHORITIES,
+                 ERR_R_INTERNAL_ERROR);
+        return EXT_RETURN_FAIL;
+    }
+
     return EXT_RETURN_SENT;
 }
 
 static int tls_parse_certificate_authorities(SSL *s, PACKET *pkt,
                                              unsigned int context, X509 *x,
-                                             size_t chainidx, int *al)
+                                             size_t chainidx)
 {
-    if (!parse_ca_names(s, pkt, al))
+    if (!parse_ca_names(s, pkt))
         return 0;
     if (PACKET_remaining(pkt) != 0) {
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR,
+                 SSL_F_TLS_PARSE_CERTIFICATE_AUTHORITIES, SSL_R_BAD_EXTENSION);
         return 0;
     }
     return 1;
@@ -1131,11 +1127,11 @@ static int init_srtp(SSL *s, unsigned int context)
 }
 #endif
 
-static int final_sig_algs(SSL *s, unsigned int context, int sent, int *al)
+static int final_sig_algs(SSL *s, unsigned int context, int sent)
 {
     if (!sent && SSL_IS_TLS13(s) && !s->hit) {
-        *al = TLS13_AD_MISSING_EXTENSION;
-        SSLerr(SSL_F_FINAL_SIG_ALGS, SSL_R_MISSING_SIGALGS_EXTENSION);
+        SSLfatal(s, TLS13_AD_MISSING_EXTENSION, SSL_F_FINAL_SIG_ALGS,
+                 SSL_R_MISSING_SIGALGS_EXTENSION);
         return 0;
     }
 
@@ -1143,7 +1139,7 @@ static int final_sig_algs(SSL *s, unsigned int context, int sent, int *al)
 }
 
 #ifndef OPENSSL_NO_EC
-static int final_key_share(SSL *s, unsigned int context, int sent, int *al)
+static int final_key_share(SSL *s, unsigned int context, int sent)
 {
     if (!SSL_IS_TLS13(s))
         return 1;
@@ -1168,8 +1164,8 @@ static int final_key_share(SSL *s, unsigned int context, int sent, int *al)
             && (!s->hit
                 || (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE) == 0)) {
         /* Nothing left we can do - just fail */
-        *al = SSL_AD_MISSING_EXTENSION;
-        SSLerr(SSL_F_FINAL_KEY_SHARE, SSL_R_NO_SUITABLE_KEY_SHARE);
+        SSLfatal(s, SSL_AD_MISSING_EXTENSION, SSL_F_FINAL_KEY_SHARE,
+                 SSL_R_NO_SUITABLE_KEY_SHARE);
         return 0;
     }
     /*
@@ -1230,11 +1226,9 @@ static int final_key_share(SSL *s, unsigned int context, int sent, int *al)
         if (!s->hit
                 || (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE) == 0) {
             /* Nothing left we can do - just fail */
-            if (!sent)
-                *al = SSL_AD_MISSING_EXTENSION;
-            else
-                *al = SSL_AD_HANDSHAKE_FAILURE;
-            SSLerr(SSL_F_FINAL_KEY_SHARE, SSL_R_NO_SUITABLE_KEY_SHARE);
+            SSLfatal(s,
+                     sent ? SSL_AD_HANDSHAKE_FAILURE : SSL_AD_MISSING_EXTENSION,
+                     SSL_F_FINAL_KEY_SHARE, SSL_R_NO_SUITABLE_KEY_SHARE);
             return 0;
         }
     }
@@ -1249,8 +1243,8 @@ static int final_key_share(SSL *s, unsigned int context, int sent, int *al)
      * 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);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_KEY_SHARE,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
@@ -1298,7 +1292,8 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
     }
 
     if (sess->master_key_length != hashsize) {
-        SSLerr(SSL_F_TLS_PSK_DO_BINDER, SSL_R_BAD_PSK);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
+                 SSL_R_BAD_PSK);
         goto err;
     }
 
@@ -1310,7 +1305,7 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
                                (const unsigned char *)nonce_label,
                                sizeof(nonce_label) - 1, sess->ext.tick_nonce,
                                sess->ext.tick_nonce_len, psk, hashsize)) {
-            SSLerr(SSL_F_TLS_PSK_DO_BINDER, ERR_R_INTERNAL_ERROR);
+            /* SSLfatal() already called */
             goto err;
         }
     }
@@ -1328,7 +1323,7 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
     else
         early_secret = (unsigned char *)sess->early_secret;
     if (!tls13_generate_secret(s, md, NULL, psk, hashsize, early_secret)) {
-        SSLerr(SSL_F_TLS_PSK_DO_BINDER, ERR_R_INTERNAL_ERROR);
+        /* SSLfatal() already called */
         goto err;
     }
 
@@ -1340,25 +1335,27 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
     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);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
     }
 
     /* Generate the binder key */
     if (!tls13_hkdf_expand(s, md, early_secret, (unsigned char *)label,
                            labelsize, hash, hashsize, binderkey, hashsize)) {
-        SSLerr(SSL_F_TLS_PSK_DO_BINDER, ERR_R_INTERNAL_ERROR);
+        /* SSLfatal() already called */
         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);
+        /* SSLfatal() already called */
         goto err;
     }
 
     if (EVP_DigestInit_ex(mctx, md, NULL) <= 0) {
-        SSLerr(SSL_F_TLS_PSK_DO_BINDER, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
     }
 
@@ -1373,7 +1370,8 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
 
         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);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
+                     SSL_R_BAD_HANDSHAKE_LENGTH);
             goto err;
         }
 
@@ -1390,27 +1388,31 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
                     || !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);
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR, 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);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, 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);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, 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);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
     }
 
@@ -1422,7 +1424,8 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
             || 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);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
     }
 
@@ -1431,6 +1434,9 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
     } else {
         /* HMAC keys can't do EVP_DigestVerify* - use CRYPTO_memcmp instead */
         ret = (CRYPTO_memcmp(binderin, binderout, hashsize) == 0);
+        if (!ret)
+            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PSK_DO_BINDER,
+                     SSL_R_BINDER_DOES_NOT_VERIFY);
     }
 
  err:
@@ -1442,7 +1448,7 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
     return ret;
 }
 
-static int final_early_data(SSL *s, unsigned int context, int sent, int *al)
+static int final_early_data(SSL *s, unsigned int context, int sent)
 {
     if (!sent)
         return 1;
@@ -1456,7 +1462,8 @@ static int final_early_data(SSL *s, unsigned int context, int sent, int *al)
              * later realised that it shouldn't have done (e.g. inconsistent
              * ALPN)
              */
-            *al = SSL_AD_ILLEGAL_PARAMETER;
+            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_FINAL_EARLY_DATA,
+                     SSL_R_BAD_EARLY_DATA);
             return 0;
         }
 
@@ -1475,7 +1482,7 @@ static int final_early_data(SSL *s, unsigned int context, int sent, int *al)
 
         if (!tls13_change_cipher_state(s,
                     SSL3_CC_EARLY | SSL3_CHANGE_CIPHER_SERVER_READ)) {
-            *al = SSL_AD_INTERNAL_ERROR;
+            /* SSLfatal() already called */
             return 0;
         }
     }
@@ -1483,24 +1490,27 @@ static int final_early_data(SSL *s, unsigned int context, int sent, int *al)
     return 1;
 }
 
-static int final_maxfragmentlen(SSL *ssl, unsigned int context, int sent, int *al)
+static int final_maxfragmentlen(SSL *s, unsigned int context, int sent)
 {
     /*
      * Session resumption on server-side with MFL extension active
      *  BUT MFL extension packet was not resent (i.e. sent == 0)
      */
-    if (ssl->server && ssl->hit && USE_MAX_FRAGMENT_LENGTH_EXT(ssl->session)
+    if (s->server && s->hit && USE_MAX_FRAGMENT_LENGTH_EXT(s->session)
             && !sent ) {
-        *al = SSL_AD_MISSING_EXTENSION;
+        SSLfatal(s, SSL_AD_MISSING_EXTENSION, SSL_F_FINAL_MAXFRAGMENTLEN,
+                 SSL_R_BAD_EXTENSION);
         return 0;
     }
 
     /* Current SSL buffer is lower than requested MFL */
-    if (ssl->session && USE_MAX_FRAGMENT_LENGTH_EXT(ssl->session)
-            && ssl->max_send_fragment < GET_MAX_FRAGMENT_LENGTH(ssl->session))
+    if (s->session && USE_MAX_FRAGMENT_LENGTH_EXT(s->session)
+            && s->max_send_fragment < GET_MAX_FRAGMENT_LENGTH(s->session))
         /* trigger a larger buffer reallocation */
-        if (!ssl3_setup_buffers(ssl))   
+        if (!ssl3_setup_buffers(s)) {
+            /* SSLfatal() already called */
             return 0;
+        }
 
     return 1;
 }
diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c
index 0dc1c49..b7ef54e 100644
--- a/ssl/statem/extensions_clnt.c
+++ b/ssl/statem/extensions_clnt.c
@@ -14,7 +14,7 @@
 
 EXT_RETURN tls_construct_ctos_renegotiate(SSL *s, WPACKET *pkt,
                                           unsigned int context, X509 *x,
-                                          size_t chainidx, int *al)
+                                          size_t chainidx)
 {
     /* Add RI if renegotiating */
     if (!s->renegotiate)
@@ -25,7 +25,8 @@ EXT_RETURN tls_construct_ctos_renegotiate(SSL *s, WPACKET *pkt,
             || !WPACKET_sub_memcpy_u8(pkt, s->s3->previous_client_finished,
                                s->s3->previous_client_finished_len)
             || !WPACKET_close(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE,
+                 ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -34,7 +35,7 @@ EXT_RETURN tls_construct_ctos_renegotiate(SSL *s, WPACKET *pkt,
 
 EXT_RETURN tls_construct_ctos_server_name(SSL *s, WPACKET *pkt,
                                           unsigned int context, X509 *x,
-                                          size_t chainidx, int *al)
+                                          size_t chainidx)
 {
     if (s->ext.hostname == NULL)
         return EXT_RETURN_NOT_SENT;
@@ -50,7 +51,8 @@ EXT_RETURN tls_construct_ctos_server_name(SSL *s, WPACKET *pkt,
                                        strlen(s->ext.hostname))
             || !WPACKET_close(pkt)
             || !WPACKET_close(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_SERVER_NAME, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_SERVER_NAME,
+                 ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -60,7 +62,7 @@ EXT_RETURN tls_construct_ctos_server_name(SSL *s, WPACKET *pkt,
 /* Push a Max Fragment Len extension into ClientHello */
 EXT_RETURN tls_construct_ctos_maxfragmentlen(SSL *s, WPACKET *pkt,
                                              unsigned int context, X509 *x,
-                                             size_t chainidx, int *al)
+                                             size_t chainidx)
 {
     if (s->ext.max_fragment_len_mode == TLSEXT_max_fragment_length_DISABLED)
         return EXT_RETURN_NOT_SENT;
@@ -75,7 +77,8 @@ EXT_RETURN tls_construct_ctos_maxfragmentlen(SSL *s, WPACKET *pkt,
             || !WPACKET_start_sub_packet_u16(pkt)
             || !WPACKET_put_bytes_u8(pkt, s->ext.max_fragment_len_mode)
             || !WPACKET_close(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_MAXFRAGMENTLEN, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_CTOS_MAXFRAGMENTLEN, ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -84,7 +87,7 @@ EXT_RETURN tls_construct_ctos_maxfragmentlen(SSL *s, WPACKET *pkt,
 
 #ifndef OPENSSL_NO_SRP
 EXT_RETURN tls_construct_ctos_srp(SSL *s, WPACKET *pkt, unsigned int context,
-                                  X509 *x, size_t chainidx, int *al)
+                                  X509 *x, size_t chainidx)
 {
     /* Add SRP username if there is one */
     if (s->srp_ctx.login == NULL)
@@ -100,7 +103,8 @@ EXT_RETURN tls_construct_ctos_srp(SSL *s, WPACKET *pkt, unsigned int context,
                                strlen(s->srp_ctx.login))
             || !WPACKET_close(pkt)
             || !WPACKET_close(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_SRP, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_SRP,
+                 ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -137,7 +141,7 @@ static int use_ecc(SSL *s)
 
 EXT_RETURN tls_construct_ctos_ec_pt_formats(SSL *s, WPACKET *pkt,
                                             unsigned int context, X509 *x,
-                                            size_t chainidx, int *al)
+                                            size_t chainidx)
 {
     const unsigned char *pformats;
     size_t num_formats;
@@ -153,7 +157,8 @@ EXT_RETURN tls_construct_ctos_ec_pt_formats(SSL *s, WPACKET *pkt,
             || !WPACKET_start_sub_packet_u16(pkt)
             || !WPACKET_sub_memcpy_u8(pkt, pformats, num_formats)
             || !WPACKET_close(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_CTOS_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -162,7 +167,7 @@ EXT_RETURN tls_construct_ctos_ec_pt_formats(SSL *s, WPACKET *pkt,
 
 EXT_RETURN tls_construct_ctos_supported_groups(SSL *s, WPACKET *pkt,
                                                unsigned int context, X509 *x,
-                                               size_t chainidx, int *al)
+                                               size_t chainidx)
 {
     const uint16_t *pgroups = NULL;
     size_t num_groups = 0, i;
@@ -180,8 +185,9 @@ EXT_RETURN tls_construct_ctos_supported_groups(SSL *s, WPACKET *pkt,
                /* Sub-packet for supported_groups extension */
             || !WPACKET_start_sub_packet_u16(pkt)
             || !WPACKET_start_sub_packet_u16(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS,
-               ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS,
+                 ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
     /* Copy curve ID if supported */
@@ -190,15 +196,17 @@ EXT_RETURN tls_construct_ctos_supported_groups(SSL *s, WPACKET *pkt,
 
         if (tls_curve_allowed(s, ctmp, SSL_SECOP_CURVE_SUPPORTED)) {
             if (!WPACKET_put_bytes_u16(pkt, ctmp)) {
-                    SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS,
-                           ERR_R_INTERNAL_ERROR);
+                    SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                             SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS,
+                             ERR_R_INTERNAL_ERROR);
                     return EXT_RETURN_FAIL;
                 }
         }
     }
     if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS,
-               ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS,
+                 ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -208,7 +216,7 @@ EXT_RETURN tls_construct_ctos_supported_groups(SSL *s, WPACKET *pkt,
 
 EXT_RETURN tls_construct_ctos_session_ticket(SSL *s, WPACKET *pkt,
                                              unsigned int context, X509 *x,
-                                             size_t chainidx, int *al)
+                                             size_t chainidx)
 {
     size_t ticklen;
 
@@ -224,8 +232,9 @@ EXT_RETURN tls_construct_ctos_session_ticket(SSL *s, WPACKET *pkt,
         ticklen = s->ext.session_ticket->length;
         s->session->ext.tick = OPENSSL_malloc(ticklen);
         if (s->session->ext.tick == NULL) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_SESSION_TICKET,
-                   ERR_R_INTERNAL_ERROR);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_CTOS_SESSION_TICKET,
+                     ERR_R_INTERNAL_ERROR);
             return EXT_RETURN_FAIL;
         }
         memcpy(s->session->ext.tick,
@@ -241,7 +250,8 @@ EXT_RETURN tls_construct_ctos_session_ticket(SSL *s, WPACKET *pkt,
 
     if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_session_ticket)
             || !WPACKET_sub_memcpy_u16(pkt, s->session->ext.tick, ticklen)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_CTOS_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -250,7 +260,7 @@ EXT_RETURN tls_construct_ctos_session_ticket(SSL *s, WPACKET *pkt,
 
 EXT_RETURN tls_construct_ctos_sig_algs(SSL *s, WPACKET *pkt,
                                        unsigned int context, X509 *x,
-                                       size_t chainidx, int *al)
+                                       size_t chainidx)
 {
     size_t salglen;
     const uint16_t *salg;
@@ -267,7 +277,8 @@ EXT_RETURN tls_construct_ctos_sig_algs(SSL *s, WPACKET *pkt,
             || !tls12_copy_sigalgs(s, pkt, salg, salglen)
             || !WPACKET_close(pkt)
             || !WPACKET_close(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_SIG_ALGS, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_SIG_ALGS,
+                 ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -277,7 +288,7 @@ EXT_RETURN tls_construct_ctos_sig_algs(SSL *s, WPACKET *pkt,
 #ifndef OPENSSL_NO_OCSP
 EXT_RETURN tls_construct_ctos_status_request(SSL *s, WPACKET *pkt,
                                              unsigned int context, X509 *x,
-                                             size_t chainidx, int *al)
+                                             size_t chainidx)
 {
     int i;
 
@@ -294,7 +305,8 @@ EXT_RETURN tls_construct_ctos_status_request(SSL *s, WPACKET *pkt,
             || !WPACKET_put_bytes_u8(pkt, TLSEXT_STATUSTYPE_ocsp)
                /* Sub-packet for the ids */
             || !WPACKET_start_sub_packet_u16(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
     for (i = 0; i < sk_OCSP_RESPID_num(s->ext.ocsp.ids); i++) {
@@ -306,14 +318,16 @@ EXT_RETURN tls_construct_ctos_status_request(SSL *s, WPACKET *pkt,
                    /* Sub-packet for an individual id */
                 || !WPACKET_sub_allocate_bytes_u16(pkt, idlen, &idbytes)
                 || i2d_OCSP_RESPID(id, &idbytes) != idlen) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST,
-                   ERR_R_INTERNAL_ERROR);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST,
+                     ERR_R_INTERNAL_ERROR);
             return EXT_RETURN_FAIL;
         }
     }
     if (!WPACKET_close(pkt)
             || !WPACKET_start_sub_packet_u16(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
     if (s->ext.ocsp.exts) {
@@ -321,20 +335,23 @@ EXT_RETURN tls_construct_ctos_status_request(SSL *s, WPACKET *pkt,
         int extlen = i2d_X509_EXTENSIONS(s->ext.ocsp.exts, NULL);
 
         if (extlen < 0) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST,
-                   ERR_R_INTERNAL_ERROR);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST,
+                     ERR_R_INTERNAL_ERROR);
             return EXT_RETURN_FAIL;
         }
         if (!WPACKET_allocate_bytes(pkt, extlen, &extbytes)
                 || i2d_X509_EXTENSIONS(s->ext.ocsp.exts, &extbytes)
                    != extlen) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST,
-                   ERR_R_INTERNAL_ERROR);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST,
+                     ERR_R_INTERNAL_ERROR);
             return EXT_RETURN_FAIL;
        }
     }
     if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -344,7 +361,7 @@ EXT_RETURN tls_construct_ctos_status_request(SSL *s, WPACKET *pkt,
 
 #ifndef OPENSSL_NO_NEXTPROTONEG
 EXT_RETURN tls_construct_ctos_npn(SSL *s, WPACKET *pkt, unsigned int context,
-                                  X509 *x, size_t chainidx, int *al)
+                                  X509 *x, size_t chainidx)
 {
     if (s->ctx->ext.npn_select_cb == NULL || !SSL_IS_FIRST_HANDSHAKE(s))
         return EXT_RETURN_NOT_SENT;
@@ -355,7 +372,8 @@ EXT_RETURN tls_construct_ctos_npn(SSL *s, WPACKET *pkt, unsigned int context,
      */
     if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_next_proto_neg)
             || !WPACKET_put_bytes_u16(pkt, 0)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_NPN, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_NPN,
+                 ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -364,7 +382,7 @@ EXT_RETURN tls_construct_ctos_npn(SSL *s, WPACKET *pkt, unsigned int context,
 #endif
 
 EXT_RETURN tls_construct_ctos_alpn(SSL *s, WPACKET *pkt, unsigned int context,
-                                   X509 *x, size_t chainidx, int *al)
+                                   X509 *x, size_t chainidx)
 {
     s->s3->alpn_sent = 0;
 
@@ -377,7 +395,8 @@ EXT_RETURN tls_construct_ctos_alpn(SSL *s, WPACKET *pkt, unsigned int context,
             || !WPACKET_start_sub_packet_u16(pkt)
             || !WPACKET_sub_memcpy_u16(pkt, s->ext.alpn, s->ext.alpn_len)
             || !WPACKET_close(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_ALPN, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_ALPN,
+                 ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
     s->s3->alpn_sent = 1;
@@ -389,7 +408,7 @@ EXT_RETURN tls_construct_ctos_alpn(SSL *s, WPACKET *pkt, unsigned int context,
 #ifndef OPENSSL_NO_SRTP
 EXT_RETURN tls_construct_ctos_use_srtp(SSL *s, WPACKET *pkt,
                                        unsigned int context, X509 *x,
-                                       size_t chainidx, int *al)
+                                       size_t chainidx)
 {
     STACK_OF(SRTP_PROTECTION_PROFILE) *clnt = SSL_get_srtp_profiles(s);
     int i, end;
@@ -402,7 +421,8 @@ EXT_RETURN tls_construct_ctos_use_srtp(SSL *s, WPACKET *pkt,
             || !WPACKET_start_sub_packet_u16(pkt)
                /* Sub-packet for the protection profile list */
             || !WPACKET_start_sub_packet_u16(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP,
+                 ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -412,7 +432,8 @@ EXT_RETURN tls_construct_ctos_use_srtp(SSL *s, WPACKET *pkt,
             sk_SRTP_PROTECTION_PROFILE_value(clnt, i);
 
         if (prof == NULL || !WPACKET_put_bytes_u16(pkt, prof->id)) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP, ERR_R_INTERNAL_ERROR);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP, ERR_R_INTERNAL_ERROR);
             return EXT_RETURN_FAIL;
         }
     }
@@ -420,7 +441,8 @@ EXT_RETURN tls_construct_ctos_use_srtp(SSL *s, WPACKET *pkt,
                /* Add an empty use_mki value */
             || !WPACKET_put_bytes_u8(pkt, 0)
             || !WPACKET_close(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP,
+                 ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -429,14 +451,15 @@ EXT_RETURN tls_construct_ctos_use_srtp(SSL *s, WPACKET *pkt,
 #endif
 
 EXT_RETURN tls_construct_ctos_etm(SSL *s, WPACKET *pkt, unsigned int context,
-                                  X509 *x, size_t chainidx, int *al)
+                                  X509 *x, size_t chainidx)
 {
     if (s->options & SSL_OP_NO_ENCRYPT_THEN_MAC)
         return EXT_RETURN_NOT_SENT;
 
     if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_encrypt_then_mac)
             || !WPACKET_put_bytes_u16(pkt, 0)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_ETM, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_ETM,
+                 ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -445,7 +468,7 @@ EXT_RETURN tls_construct_ctos_etm(SSL *s, WPACKET *pkt, unsigned int context,
 
 #ifndef OPENSSL_NO_CT
 EXT_RETURN tls_construct_ctos_sct(SSL *s, WPACKET *pkt, unsigned int context,
-                                  X509 *x, size_t chainidx, int *al)
+                                  X509 *x, size_t chainidx)
 {
     if (s->ct_validation_callback == NULL)
         return EXT_RETURN_NOT_SENT;
@@ -456,7 +479,8 @@ EXT_RETURN tls_construct_ctos_sct(SSL *s, WPACKET *pkt, unsigned int context,
 
     if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_signed_certificate_timestamp)
             || !WPACKET_put_bytes_u16(pkt, 0)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_SCT, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_SCT,
+                 ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -465,11 +489,12 @@ EXT_RETURN tls_construct_ctos_sct(SSL *s, WPACKET *pkt, unsigned int context,
 #endif
 
 EXT_RETURN tls_construct_ctos_ems(SSL *s, WPACKET *pkt, unsigned int context,
-                                  X509 *x, size_t chainidx, int *al)
+                                  X509 *x, size_t chainidx)
 {
     if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_extended_master_secret)
             || !WPACKET_put_bytes_u16(pkt, 0)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_EMS, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EMS,
+                 ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -478,21 +503,23 @@ EXT_RETURN tls_construct_ctos_ems(SSL *s, WPACKET *pkt, unsigned int context,
 
 EXT_RETURN tls_construct_ctos_supported_versions(SSL *s, WPACKET *pkt,
                                                  unsigned int context, X509 *x,
-                                                 size_t chainidx, int *al)
+                                                 size_t chainidx)
 {
     int currv, min_version, max_version, reason;
 
     if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_versions)
             || !WPACKET_start_sub_packet_u16(pkt)
             || !WPACKET_start_sub_packet_u8(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS,
-               ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS,
+                 ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
     reason = ssl_get_min_max_version(s, &min_version, &max_version);
     if (reason != 0) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS, reason);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS, reason);
         return EXT_RETURN_FAIL;
     }
 
@@ -505,19 +532,22 @@ EXT_RETURN tls_construct_ctos_supported_versions(SSL *s, WPACKET *pkt,
         /* TODO(TLS1.3): Remove this first if clause prior to release!! */
         if (currv == TLS1_3_VERSION) {
             if (!WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT)) {
-                SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS,
-                       ERR_R_INTERNAL_ERROR);
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS,
+                         ERR_R_INTERNAL_ERROR);
                 return EXT_RETURN_FAIL;
             }
         } else if (!WPACKET_put_bytes_u16(pkt, currv)) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS,
-                   ERR_R_INTERNAL_ERROR);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS,
+                     ERR_R_INTERNAL_ERROR);
             return EXT_RETURN_FAIL;
         }
     }
     if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS,
-               ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS,
+                 ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -529,7 +559,7 @@ EXT_RETURN tls_construct_ctos_supported_versions(SSL *s, WPACKET *pkt,
  */
 EXT_RETURN tls_construct_ctos_psk_kex_modes(SSL *s, WPACKET *pkt,
                                             unsigned int context, X509 *x,
-                                            size_t chainidx, int *al)
+                                            size_t chainidx)
 {
 #ifndef OPENSSL_NO_TLS1_3
     int nodhe = s->options & SSL_OP_ALLOW_NO_DHE_KEX;
@@ -541,7 +571,8 @@ EXT_RETURN tls_construct_ctos_psk_kex_modes(SSL *s, WPACKET *pkt,
             || (nodhe && !WPACKET_put_bytes_u8(pkt, TLSEXT_KEX_MODE_KE))
             || !WPACKET_close(pkt)
             || !WPACKET_close(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES, ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -562,7 +593,8 @@ static int add_key_share(SSL *s, WPACKET *pkt, unsigned int curve_id)
 
     if (s->s3->tmp.pkey != NULL) {
         if (!ossl_assert(s->hello_retry_request)) {
-            SSLerr(SSL_F_ADD_KEY_SHARE, ERR_R_INTERNAL_ERROR);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_ADD_KEY_SHARE,
+                     ERR_R_INTERNAL_ERROR);
             return 0;
         }
         /*
@@ -570,9 +602,9 @@ static int add_key_share(SSL *s, WPACKET *pkt, unsigned int curve_id)
          */
         key_share_key = s->s3->tmp.pkey;
     } else {
-        key_share_key = ssl_generate_pkey_group(curve_id);
+        key_share_key = ssl_generate_pkey_group(s, curve_id);
         if (key_share_key == NULL) {
-            SSLerr(SSL_F_ADD_KEY_SHARE, ERR_R_EVP_LIB);
+            /* SSLfatal() already called */
             return 0;
         }
     }
@@ -581,14 +613,15 @@ static int add_key_share(SSL *s, WPACKET *pkt, unsigned int curve_id)
     encodedlen = EVP_PKEY_get1_tls_encodedpoint(key_share_key,
                                                 &encoded_point);
     if (encodedlen == 0) {
-        SSLerr(SSL_F_ADD_KEY_SHARE, ERR_R_EC_LIB);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_ADD_KEY_SHARE, ERR_R_EC_LIB);
         goto err;
     }
 
     /* Create KeyShareEntry */
     if (!WPACKET_put_bytes_u16(pkt, curve_id)
             || !WPACKET_sub_memcpy_u16(pkt, encoded_point, encodedlen)) {
-        SSLerr(SSL_F_ADD_KEY_SHARE, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_ADD_KEY_SHARE,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
     }
 
@@ -612,7 +645,7 @@ static int add_key_share(SSL *s, WPACKET *pkt, unsigned int curve_id)
 
 EXT_RETURN tls_construct_ctos_key_share(SSL *s, WPACKET *pkt,
                                         unsigned int context, X509 *x,
-                                        size_t chainidx, int *al)
+                                        size_t chainidx)
 {
 #ifndef OPENSSL_NO_TLS1_3
     size_t i, num_groups = 0;
@@ -625,7 +658,8 @@ EXT_RETURN tls_construct_ctos_key_share(SSL *s, WPACKET *pkt,
             || !WPACKET_start_sub_packet_u16(pkt)
                /* KeyShare list sub-packet */
             || !WPACKET_start_sub_packet_u16(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE,
+                 ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -649,15 +683,19 @@ EXT_RETURN tls_construct_ctos_key_share(SSL *s, WPACKET *pkt,
     }
 
     if (curve_id == 0) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE, SSL_R_NO_SUITABLE_KEY_SHARE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE,
+                 SSL_R_NO_SUITABLE_KEY_SHARE);
         return EXT_RETURN_FAIL;
     }
 
-    if (!add_key_share(s, pkt, curve_id))
+    if (!add_key_share(s, pkt, curve_id)) {
+        /* SSLfatal() already called */
         return EXT_RETURN_FAIL;
+    }
 
     if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE,
+                 ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 #endif
@@ -666,7 +704,7 @@ EXT_RETURN tls_construct_ctos_key_share(SSL *s, WPACKET *pkt,
 }
 
 EXT_RETURN tls_construct_ctos_cookie(SSL *s, WPACKET *pkt, unsigned int context,
-                                     X509 *x, size_t chainidx, int *al)
+                                     X509 *x, size_t chainidx)
 {
     EXT_RETURN ret = EXT_RETURN_FAIL;
 
@@ -680,7 +718,8 @@ EXT_RETURN tls_construct_ctos_cookie(SSL *s, WPACKET *pkt, unsigned int context,
             || !WPACKET_sub_memcpy_u16(pkt, s->ext.tls13_cookie,
                                        s->ext.tls13_cookie_len)
             || !WPACKET_close(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_COOKIE, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_COOKIE,
+                 ERR_R_INTERNAL_ERROR);
         goto end;
     }
 
@@ -695,7 +734,7 @@ EXT_RETURN tls_construct_ctos_cookie(SSL *s, WPACKET *pkt, unsigned int context,
 
 EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt,
                                          unsigned int context, X509 *x,
-                                         size_t chainidx, int *al)
+                                         size_t chainidx)
 {
     const unsigned char *id = NULL;
     size_t idlen = 0;
@@ -711,7 +750,8 @@ EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt,
                 || (psksess != NULL
                     && psksess->ssl_version != TLS1_3_VERSION))) {
         SSL_SESSION_free(psksess);
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, SSL_R_BAD_PSK);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
+                 SSL_R_BAD_PSK);
         return EXT_RETURN_FAIL;
     }
 
@@ -721,7 +761,8 @@ EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt,
         OPENSSL_free(s->psksession_id);
         s->psksession_id = OPENSSL_memdup(id, idlen);
         if (s->psksession_id == NULL) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, ERR_R_INTERNAL_ERROR);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, ERR_R_INTERNAL_ERROR);
             return EXT_RETURN_FAIL;
         }
         s->psksession_id_len = idlen;
@@ -740,15 +781,16 @@ EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt,
         if (s->ext.hostname == NULL
                 || (s->ext.hostname != NULL
                     && strcmp(s->ext.hostname, edsess->ext.hostname) != 0)) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
-                   SSL_R_INCONSISTENT_EARLY_DATA_SNI);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
+                     SSL_R_INCONSISTENT_EARLY_DATA_SNI);
             return EXT_RETURN_FAIL;
         }
     }
 
     if ((s->ext.alpn == NULL && edsess->ext.alpn_selected != NULL)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
-               SSL_R_INCONSISTENT_EARLY_DATA_ALPN);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
+                 SSL_R_INCONSISTENT_EARLY_DATA_ALPN);
         return EXT_RETURN_FAIL;
     }
 
@@ -761,7 +803,8 @@ EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt,
         int found = 0;
 
         if (!PACKET_buf_init(&prots, s->ext.alpn, s->ext.alpn_len)) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, ERR_R_INTERNAL_ERROR);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, ERR_R_INTERNAL_ERROR);
             return EXT_RETURN_FAIL;
         }
         while (PACKET_get_length_prefixed_1(&prots, &alpnpkt)) {
@@ -772,8 +815,9 @@ EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt,
             }
         }
         if (!found) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
-                   SSL_R_INCONSISTENT_EARLY_DATA_ALPN);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
+                     SSL_R_INCONSISTENT_EARLY_DATA_ALPN);
             return EXT_RETURN_FAIL;
         }
     }
@@ -781,7 +825,8 @@ EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt,
     if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data)
             || !WPACKET_start_sub_packet_u16(pkt)
             || !WPACKET_close(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
+                 ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -814,7 +859,7 @@ EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt,
 
 EXT_RETURN tls_construct_ctos_padding(SSL *s, WPACKET *pkt,
                                       unsigned int context, X509 *x,
-                                      size_t chainidx, int *al)
+                                      size_t chainidx)
 {
     unsigned char *padbytes;
     size_t hlen;
@@ -829,7 +874,8 @@ EXT_RETURN tls_construct_ctos_padding(SSL *s, WPACKET *pkt,
      * this extension MUST always appear second to last.
      */
     if (!WPACKET_get_total_written(pkt, &hlen)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PADDING, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PADDING,
+                 ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -869,7 +915,8 @@ EXT_RETURN tls_construct_ctos_padding(SSL *s, WPACKET *pkt,
 
         if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_padding)
                 || !WPACKET_sub_allocate_bytes_u16(pkt, hlen, &padbytes)) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PADDING, ERR_R_INTERNAL_ERROR);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PADDING,
+                     ERR_R_INTERNAL_ERROR);
             return EXT_RETURN_FAIL;
         }
         memset(padbytes, 0, hlen);
@@ -882,14 +929,13 @@ EXT_RETURN tls_construct_ctos_padding(SSL *s, WPACKET *pkt,
  * Construct the pre_shared_key extension
  */
 EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
-                                  X509 *x, size_t chainidx, int *al)
+                                  X509 *x, size_t chainidx)
 {
 #ifndef OPENSSL_NO_TLS1_3
     uint32_t now, agesec, agems = 0;
     size_t reshashsize = 0, pskhashsize = 0, binderoffset, msglen;
     unsigned char *resbinder = NULL, *pskbinder = NULL, *msgstart = NULL;
     const EVP_MD *handmd = NULL, *mdres = NULL, *mdpsk = NULL;
-    EXT_RETURN ret = EXT_RETURN_FAIL;
     int dores = 0;
 
     s->session->ext.tick_identity = TLSEXT_PSK_BAD_IDENTITY;
@@ -914,8 +960,9 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
     if (s->session->ext.ticklen != 0) {
         /* Get the digest associated with the ciphersuite in the session */
         if (s->session->cipher == NULL) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, ERR_R_INTERNAL_ERROR);
-            goto err;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
+                     ERR_R_INTERNAL_ERROR);
+            return EXT_RETURN_FAIL;
         }
         mdres = ssl_md(s->session->cipher->algorithm2);
         if (mdres == NULL) {
@@ -985,8 +1032,9 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
              * Don't recognize this cipher so we can't use the session.
              * If this happens it's an application bug.
              */
-            SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, SSL_R_BAD_PSK);
-            goto err;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
+                     SSL_R_BAD_PSK);
+            return EXT_RETURN_FAIL;
         }
 
         if (s->hello_retry_request && mdpsk != handmd) {
@@ -994,8 +1042,9 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
              * Selected ciphersuite hash does not match the hash for the PSK
              * session. This is an application bug.
              */
-            SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, SSL_R_BAD_PSK);
-            goto err;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
+                     SSL_R_BAD_PSK);
+            return EXT_RETURN_FAIL;
         }
 
         pskhashsize = EVP_MD_size(mdpsk);
@@ -1005,16 +1054,18 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
     if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_psk)
             || !WPACKET_start_sub_packet_u16(pkt)
             || !WPACKET_start_sub_packet_u16(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, ERR_R_INTERNAL_ERROR);
-        goto err;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
+                 ERR_R_INTERNAL_ERROR);
+        return EXT_RETURN_FAIL;
     }
 
     if (dores) {
         if (!WPACKET_sub_memcpy_u16(pkt, s->session->ext.tick,
                                            s->session->ext.ticklen)
                 || !WPACKET_put_bytes_u32(pkt, agems)) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, ERR_R_INTERNAL_ERROR);
-            goto err;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
+                     ERR_R_INTERNAL_ERROR);
+            return EXT_RETURN_FAIL;
         }
     }
 
@@ -1022,8 +1073,9 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
         if (!WPACKET_sub_memcpy_u16(pkt, s->psksession_id,
                                     s->psksession_id_len)
                 || !WPACKET_put_bytes_u32(pkt, 0)) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, ERR_R_INTERNAL_ERROR);
-            goto err;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
+                     ERR_R_INTERNAL_ERROR);
+            return EXT_RETURN_FAIL;
         }
     }
 
@@ -1042,8 +1094,9 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
                 * calculate the HMAC of the message up to the binders
                 */
             || !WPACKET_fill_lengths(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, ERR_R_INTERNAL_ERROR);
-        goto err;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
+                 ERR_R_INTERNAL_ERROR);
+        return EXT_RETURN_FAIL;
     }
 
     msgstart = WPACKET_get_curr(pkt) - msglen;
@@ -1051,15 +1104,15 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
     if (dores
             && tls_psk_do_binder(s, mdres, msgstart, binderoffset, NULL,
                                  resbinder, s->session, 1, 0) != 1) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, ERR_R_INTERNAL_ERROR);
-        goto err;
+        /* SSLfatal() already called */
+        return EXT_RETURN_FAIL;
     }
 
     if (s->psksession != NULL
             && tls_psk_do_binder(s, mdpsk, msgstart, binderoffset, NULL,
                                  pskbinder, s->psksession, 1, 1) != 1) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, ERR_R_INTERNAL_ERROR);
-        goto err;
+        /* SSLfatal() already called */
+        return EXT_RETURN_FAIL;
     }
 
     if (dores)
@@ -1067,9 +1120,7 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
     if (s->psksession != NULL)
         s->psksession->ext.tick_identity = (dores ? 1 : 0);
 
-    ret = EXT_RETURN_SENT;
- err:
-    return ret;
+    return EXT_RETURN_SENT;
 #else
     return EXT_RETURN_NOT_SENT;
 #endif
@@ -1079,7 +1130,7 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
  * Parse the server's renegotiation binding and abort if it's not right
  */
 int tls_parse_stoc_renegotiate(SSL *s, PACKET *pkt, unsigned int context,
-                               X509 *x, size_t chainidx, int *al)
+                               X509 *x, size_t chainidx)
 {
     size_t expected_len = s->s3->previous_client_finished_len
         + s->s3->previous_server_finished_len;
@@ -1091,49 +1142,45 @@ int tls_parse_stoc_renegotiate(SSL *s, PACKET *pkt, unsigned int context,
                      || s->s3->previous_client_finished_len != 0)
         || !ossl_assert(expected_len == 0
                         || s->s3->previous_server_finished_len != 0)) {
-        *al = SSL_AD_INTERNAL_ERROR;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
     /* Parse the length byte */
     if (!PACKET_get_1_len(pkt, &ilen)) {
-        SSLerr(SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
-               SSL_R_RENEGOTIATION_ENCODING_ERR);
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
+                 SSL_R_RENEGOTIATION_ENCODING_ERR);
         return 0;
     }
 
     /* Consistency check */
     if (PACKET_remaining(pkt) != ilen) {
-        SSLerr(SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
-               SSL_R_RENEGOTIATION_ENCODING_ERR);
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
+                 SSL_R_RENEGOTIATION_ENCODING_ERR);
         return 0;
     }
 
     /* Check that the extension matches */
     if (ilen != expected_len) {
-        SSLerr(SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
-               SSL_R_RENEGOTIATION_MISMATCH);
-        *al = SSL_AD_ILLEGAL_PARAMETER;
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
+                 SSL_R_RENEGOTIATION_MISMATCH);
         return 0;
     }
 
     if (!PACKET_get_bytes(pkt, &data, s->s3->previous_client_finished_len)
         || memcmp(data, s->s3->previous_client_finished,
                   s->s3->previous_client_finished_len) != 0) {
-        SSLerr(SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
-               SSL_R_RENEGOTIATION_MISMATCH);
-        *al = SSL_AD_ILLEGAL_PARAMETER;
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
+                 SSL_R_RENEGOTIATION_MISMATCH);
         return 0;
     }
 
     if (!PACKET_get_bytes(pkt, &data, s->s3->previous_server_finished_len)
         || memcmp(data, s->s3->previous_server_finished,
                   s->s3->previous_server_finished_len) != 0) {
-        SSLerr(SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
-               SSL_R_RENEGOTIATION_MISMATCH);
-        *al = SSL_AD_ILLEGAL_PARAMETER;
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
+                 SSL_R_RENEGOTIATION_MISMATCH);
         return 0;
     }
     s->s3->send_connection_binding = 1;
@@ -1143,18 +1190,21 @@ int tls_parse_stoc_renegotiate(SSL *s, PACKET *pkt, unsigned int context,
 
 /* Parse the server's max fragment len extension packet */
 int tls_parse_stoc_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
-                                  X509 *x, size_t chainidx, int *al)
+                                  X509 *x, size_t chainidx)
 {
     unsigned int value;
 
     if (PACKET_remaining(pkt) != 1 || !PACKET_get_1(pkt, &value)) {
-        *al = TLS1_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN, 
+                 SSL_R_BAD_EXTENSION);
         return 0;
     }
 
     /* |value| should contains a valid max-fragment-length code. */
     if (!IS_MAX_FRAGMENT_LENGTH_EXT_VALID(value)) {
-        *al = SSL_AD_ILLEGAL_PARAMETER;
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+                 SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN,
+                 SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
         return 0;
     }
 
@@ -1165,7 +1215,9 @@ int tls_parse_stoc_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
      * It must abort with SSL_AD_ILLEGAL_PARAMETER alert
      */
     if (value != s->ext.max_fragment_len_mode) {
-        *al = SSL_AD_ILLEGAL_PARAMETER;
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+                 SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN,
+                 SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
         return 0;
     }
 
@@ -1179,26 +1231,30 @@ int tls_parse_stoc_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
 }
 
 int tls_parse_stoc_server_name(SSL *s, PACKET *pkt, unsigned int context,
-                               X509 *x, size_t chainidx, int *al)
+                               X509 *x, size_t chainidx)
 {
     if (s->ext.hostname == NULL) {
-        *al = SSL_AD_INTERNAL_ERROR;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
     if (PACKET_remaining(pkt) > 0) {
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME,
+                 SSL_R_BAD_EXTENSION);
         return 0;
     }
 
     if (!s->hit) {
         if (s->session->ext.hostname != NULL) {
-            *al = SSL_AD_INTERNAL_ERROR;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME,
+                     ERR_R_INTERNAL_ERROR);
             return 0;
         }
         s->session->ext.hostname = OPENSSL_strdup(s->ext.hostname);
         if (s->session->ext.hostname == NULL) {
-            *al = SSL_AD_INTERNAL_ERROR;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME,
+                     ERR_R_INTERNAL_ERROR);
             return 0;
         }
     }
@@ -1208,13 +1264,14 @@ int tls_parse_stoc_server_name(SSL *s, PACKET *pkt, unsigned int context,
 
 #ifndef OPENSSL_NO_EC
 int tls_parse_stoc_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
-                                 X509 *x, size_t chainidx, int *al)
+                                 X509 *x, size_t chainidx)
 {
     unsigned int ecpointformats_len;
     PACKET ecptformatlist;
 
     if (!PACKET_as_length_prefixed_1(pkt, &ecptformatlist)) {
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS,
+                 SSL_R_BAD_EXTENSION);
         return 0;
     }
     if (!s->hit) {
@@ -1224,7 +1281,8 @@ int tls_parse_stoc_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
         OPENSSL_free(s->session->ext.ecpointformats);
         s->session->ext.ecpointformats = OPENSSL_malloc(ecpointformats_len);
         if (s->session->ext.ecpointformats == NULL) {
-            *al = SSL_AD_INTERNAL_ERROR;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
             return 0;
         }
 
@@ -1233,7 +1291,8 @@ int tls_parse_stoc_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
         if (!PACKET_copy_bytes(&ecptformatlist,
                                s->session->ext.ecpointformats,
                                ecpointformats_len)) {
-            *al = SSL_AD_INTERNAL_ERROR;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
             return 0;
         }
     }
@@ -1243,22 +1302,25 @@ int tls_parse_stoc_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
 #endif
 
 int tls_parse_stoc_session_ticket(SSL *s, PACKET *pkt, unsigned int context,
-                                  X509 *x, size_t chainidx, int *al)
+                                  X509 *x, size_t chainidx)
 {
     if (s->ext.session_ticket_cb != NULL &&
         !s->ext.session_ticket_cb(s, PACKET_data(pkt),
                               PACKET_remaining(pkt),
                               s->ext.session_ticket_cb_arg)) {
-        *al = SSL_AD_INTERNAL_ERROR;
+        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+                 SSL_F_TLS_PARSE_STOC_SESSION_TICKET, SSL_R_BAD_EXTENSION);
         return 0;
     }
 
     if (!tls_use_ticket(s)) {
-        *al = SSL_AD_UNSUPPORTED_EXTENSION;
+        SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION,
+                 SSL_F_TLS_PARSE_STOC_SESSION_TICKET, SSL_R_BAD_EXTENSION);
         return 0;
     }
     if (PACKET_remaining(pkt) > 0) {
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR,
+                 SSL_F_TLS_PARSE_STOC_SESSION_TICKET, SSL_R_BAD_EXTENSION);
         return 0;
     }
 
@@ -1269,18 +1331,20 @@ int tls_parse_stoc_session_ticket(SSL *s, PACKET *pkt, unsigned int context,
 
 #ifndef OPENSSL_NO_OCSP
 int tls_parse_stoc_status_request(SSL *s, PACKET *pkt, unsigned int context,
-                                  X509 *x, size_t chainidx, int *al)
+                                  X509 *x, size_t chainidx)
 {
     /*
      * MUST only be sent if we've requested a status
      * request message. In TLS <= 1.2 it must also be empty.
      */
     if (s->ext.status_type != TLSEXT_STATUSTYPE_ocsp) {
-        *al = SSL_AD_UNSUPPORTED_EXTENSION;
+        SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION,
+                 SSL_F_TLS_PARSE_STOC_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
         return 0;
     }
     if (!SSL_IS_TLS13(s) && PACKET_remaining(pkt) > 0) {
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR,
+                 SSL_F_TLS_PARSE_STOC_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
         return 0;
     }
 
@@ -1290,7 +1354,9 @@ int tls_parse_stoc_status_request(SSL *s, PACKET *pkt, unsigned int context,
          */
         if (chainidx != 0)
             return 1;
-        return tls_process_cert_status_body(s, pkt, al);
+
+        /* SSLfatal() already called */
+        return tls_process_cert_status_body(s, pkt);
     }
 
     /* Set flag to expect CertificateStatus message */
@@ -1303,7 +1369,7 @@ int tls_parse_stoc_status_request(SSL *s, PACKET *pkt, unsigned int context,
 
 #ifndef OPENSSL_NO_CT
 int tls_parse_stoc_sct(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                       size_t chainidx, int *al)
+                       size_t chainidx)
 {
     /*
      * Only take it if we asked for it - i.e if there is no CT validation
@@ -1322,7 +1388,8 @@ int tls_parse_stoc_sct(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
             s->ext.scts = OPENSSL_malloc(size);
             if (s->ext.scts == NULL
                     || !PACKET_copy_bytes(pkt, s->ext.scts, size)) {
-                *al = SSL_AD_INTERNAL_ERROR;
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SCT,
+                         ERR_R_INTERNAL_ERROR);
                 return 0;
             }
         }
@@ -1337,15 +1404,18 @@ int tls_parse_stoc_sct(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
         if (custom_ext_find(&s->cert->custext, role,
                             TLSEXT_TYPE_signed_certificate_timestamp,
                             NULL) == NULL) {
-            *al = TLS1_AD_UNSUPPORTED_EXTENSION;
+            SSLfatal(s, TLS1_AD_UNSUPPORTED_EXTENSION, SSL_F_TLS_PARSE_STOC_SCT,
+                     SSL_R_BAD_EXTENSION);
             return 0;
         }
 
-        if (custom_ext_parse(s, context,
+        if (!custom_ext_parse(s, context,
                              TLSEXT_TYPE_signed_certificate_timestamp,
                              PACKET_data(pkt), PACKET_remaining(pkt),
-                             x, chainidx, al) <= 0)
+                             x, chainidx)) {
+            /* SSLfatal already called */
             return 0;
+        }
     }
 
     return 1;
@@ -1359,21 +1429,24 @@ int tls_parse_stoc_sct(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
  * elements of zero length are allowed and the set of elements must exactly
  * fill the length of the block. Returns 1 on success or 0 on failure.
  */
-static int ssl_next_proto_validate(PACKET *pkt)
+static int ssl_next_proto_validate(SSL *s, PACKET *pkt)
 {
     PACKET tmp_protocol;
 
     while (PACKET_remaining(pkt)) {
         if (!PACKET_get_length_prefixed_1(pkt, &tmp_protocol)
-            || PACKET_remaining(&tmp_protocol) == 0)
+            || PACKET_remaining(&tmp_protocol) == 0) {
+            SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL_NEXT_PROTO_VALIDATE,
+                     SSL_R_BAD_EXTENSION);
             return 0;
+        }
     }
 
     return 1;
 }
 
 int tls_parse_stoc_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                       size_t chainidx, int *al)
+                       size_t chainidx)
 {
     unsigned char *selected;
     unsigned char selected_len;
@@ -1385,14 +1458,15 @@ int tls_parse_stoc_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
 
     /* We must have requested it. */
     if (s->ctx->ext.npn_select_cb == NULL) {
-        *al = SSL_AD_UNSUPPORTED_EXTENSION;
+        SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION, SSL_F_TLS_PARSE_STOC_NPN,
+                 SSL_R_BAD_EXTENSION);
         return 0;
     }
 
     /* The data must be valid */
     tmppkt = *pkt;
-    if (!ssl_next_proto_validate(&tmppkt)) {
-        *al = SSL_AD_DECODE_ERROR;
+    if (!ssl_next_proto_validate(s, &tmppkt)) {
+        /* SSLfatal() already called */
         return 0;
     }
     if (s->ctx->ext.npn_select_cb(s, &selected, &selected_len,
@@ -1400,7 +1474,8 @@ int tls_parse_stoc_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
                                   PACKET_remaining(pkt),
                                   s->ctx->ext.npn_select_cb_arg) !=
              SSL_TLSEXT_ERR_OK) {
-        *al = SSL_AD_INTERNAL_ERROR;
+        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PARSE_STOC_NPN,
+                 SSL_R_BAD_EXTENSION);
         return 0;
     }
 
@@ -1411,7 +1486,8 @@ int tls_parse_stoc_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
     OPENSSL_free(s->ext.npn);
     s->ext.npn = OPENSSL_malloc(selected_len);
     if (s->ext.npn == NULL) {
-        *al = SSL_AD_INTERNAL_ERROR;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_NPN,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
@@ -1424,13 +1500,14 @@ int tls_parse_stoc_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
 #endif
 
 int tls_parse_stoc_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                        size_t chainidx, int *al)
+                        size_t chainidx)
 {
     size_t len;
 
     /* We must have requested it. */
     if (!s->s3->alpn_sent) {
-        *al = SSL_AD_UNSUPPORTED_EXTENSION;
+        SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION, SSL_F_TLS_PARSE_STOC_ALPN,
+                 SSL_R_BAD_EXTENSION);
         return 0;
     }
     /*-
@@ -1442,17 +1519,20 @@ int tls_parse_stoc_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
     if (!PACKET_get_net_2_len(pkt, &len)
         || PACKET_remaining(pkt) != len || !PACKET_get_1_len(pkt, &len)
         || PACKET_remaining(pkt) != len) {
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_ALPN,
+                 SSL_R_BAD_EXTENSION);
         return 0;
     }
     OPENSSL_free(s->s3->alpn_selected);
     s->s3->alpn_selected = OPENSSL_malloc(len);
     if (s->s3->alpn_selected == NULL) {
-        *al = SSL_AD_INTERNAL_ERROR;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_ALPN,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
     }
     if (!PACKET_copy_bytes(pkt, s->s3->alpn_selected, len)) {
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_ALPN,
+                 SSL_R_BAD_EXTENSION);
         return 0;
     }
     s->s3->alpn_selected_len = len;
@@ -1469,7 +1549,8 @@ int tls_parse_stoc_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
         s->session->ext.alpn_selected =
             OPENSSL_memdup(s->s3->alpn_selected, s->s3->alpn_selected_len);
         if (s->session->ext.alpn_selected == NULL) {
-            *al = SSL_AD_INTERNAL_ERROR;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_ALPN,
+                     ERR_R_INTERNAL_ERROR);
             return 0;
         }
         s->session->ext.alpn_selected_len = s->s3->alpn_selected_len;
@@ -1480,7 +1561,7 @@ int tls_parse_stoc_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
 
 #ifndef OPENSSL_NO_SRTP
 int tls_parse_stoc_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                            size_t chainidx, int *al)
+                            size_t chainidx)
 {
     unsigned int id, ct, mki;
     int i;
@@ -1491,24 +1572,23 @@ int tls_parse_stoc_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
             || !PACKET_get_net_2(pkt, &id)
             || !PACKET_get_1(pkt, &mki)
             || PACKET_remaining(pkt) != 0) {
-        SSLerr(SSL_F_TLS_PARSE_STOC_USE_SRTP,
-               SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_USE_SRTP,
+                 SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
         return 0;
     }
 
     if (mki != 0) {
         /* Must be no MKI, since we never offer one */
-        SSLerr(SSL_F_TLS_PARSE_STOC_USE_SRTP, SSL_R_BAD_SRTP_MKI_VALUE);
-        *al = SSL_AD_ILLEGAL_PARAMETER;
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_USE_SRTP,
+                 SSL_R_BAD_SRTP_MKI_VALUE);
         return 0;
     }
 
     /* Throw an error if the server gave us an unsolicited extension */
     clnt = SSL_get_srtp_profiles(s);
     if (clnt == NULL) {
-        SSLerr(SSL_F_TLS_PARSE_STOC_USE_SRTP, SSL_R_NO_SRTP_PROFILES);
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_USE_SRTP,
+                 SSL_R_NO_SRTP_PROFILES);
         return 0;
     }
 
@@ -1521,20 +1601,18 @@ int tls_parse_stoc_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
 
         if (prof->id == id) {
             s->srtp_profile = prof;
-            *al = 0;
             return 1;
         }
     }
 
-    SSLerr(SSL_F_TLS_PARSE_STOC_USE_SRTP,
-           SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
-    *al = SSL_AD_DECODE_ERROR;
+    SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_USE_SRTP,
+             SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
     return 0;
 }
 #endif
 
 int tls_parse_stoc_etm(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                       size_t chainidx, int *al)
+                       size_t chainidx)
 {
     /* Ignore if inappropriate ciphersuite */
     if (!(s->options & SSL_OP_NO_ENCRYPT_THEN_MAC)
@@ -1546,7 +1624,7 @@ int tls_parse_stoc_etm(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
 }
 
 int tls_parse_stoc_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                       size_t chainidx, int *al)
+                       size_t chainidx)
 {
     s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS;
     if (!s->hit)
@@ -1556,7 +1634,7 @@ int tls_parse_stoc_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
 }
 
 int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                             size_t chainidx, int *al)
+                             size_t chainidx)
 {
 #ifndef OPENSSL_NO_TLS1_3
     unsigned int group_id;
@@ -1565,14 +1643,14 @@ int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
 
     /* Sanity check */
     if (ckey == NULL || s->s3->peer_tmp != NULL) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
     if (!PACKET_get_net_2(pkt, &group_id)) {
-        *al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_LENGTH_MISMATCH);
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
+                 SSL_R_LENGTH_MISMATCH);
         return 0;
     }
 
@@ -1581,8 +1659,8 @@ int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
         size_t i, num_groups;
 
         if (PACKET_remaining(pkt) != 0) {
-            *al = SSL_AD_DECODE_ERROR;
-            SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_LENGTH_MISMATCH);
+            SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
+                     SSL_R_LENGTH_MISMATCH);
             return 0;
         }
 
@@ -1591,8 +1669,8 @@ int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
          * already sent in the first ClientHello
          */
         if (group_id == s->s3->group_id) {
-            *al = SSL_AD_ILLEGAL_PARAMETER;
-            SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_KEY_SHARE);
+            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+                     SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_KEY_SHARE);
             return 0;
         }
 
@@ -1604,8 +1682,8 @@ int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
         }
         if (i >= num_groups
                 || !tls_curve_allowed(s, group_id, SSL_SECOP_CURVE_SUPPORTED)) {
-            *al = SSL_AD_ILLEGAL_PARAMETER;
-            SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_KEY_SHARE);
+            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+                     SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_KEY_SHARE);
             return 0;
         }
 
@@ -1620,35 +1698,34 @@ int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
          * This isn't for the group that we sent in the original
          * key_share!
          */
-        *al = SSL_AD_ILLEGAL_PARAMETER;
-        SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_KEY_SHARE);
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
+                 SSL_R_BAD_KEY_SHARE);
         return 0;
     }
 
     if (!PACKET_as_length_prefixed_2(pkt, &encoded_pt)
             || PACKET_remaining(&encoded_pt) == 0) {
-        *al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_LENGTH_MISMATCH);
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
+                 SSL_R_LENGTH_MISMATCH);
         return 0;
     }
 
     skey = ssl_generate_pkey(ckey);
     if (skey == NULL) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, ERR_R_MALLOC_FAILURE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
+                 ERR_R_MALLOC_FAILURE);
         return 0;
     }
     if (!EVP_PKEY_set1_tls_encodedpoint(skey, PACKET_data(&encoded_pt),
                                         PACKET_remaining(&encoded_pt))) {
-        *al = SSL_AD_ILLEGAL_PARAMETER;
-        SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_ECPOINT);
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
+                 SSL_R_BAD_ECPOINT);
         EVP_PKEY_free(skey);
         return 0;
     }
 
     if (ssl_derive(s, ckey, skey, 1) == 0) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR);
+        /* SSLfatal() already called */
         EVP_PKEY_free(skey);
         return 0;
     }
@@ -1659,15 +1736,15 @@ int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
 }
 
 int tls_parse_stoc_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                       size_t chainidx, int *al)
+                       size_t chainidx)
 {
     PACKET cookie;
 
     if (!PACKET_as_length_prefixed_2(pkt, &cookie)
             || !PACKET_memdup(&cookie, &s->ext.tls13_cookie,
                               &s->ext.tls13_cookie_len)) {
-        *al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PARSE_STOC_COOKIE, SSL_R_LENGTH_MISMATCH);
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_COOKIE,
+                 SSL_R_LENGTH_MISMATCH);
         return 0;
     }
 
@@ -1675,16 +1752,15 @@ int tls_parse_stoc_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
 }
 
 int tls_parse_stoc_early_data(SSL *s, PACKET *pkt, unsigned int context,
-                              X509 *x, size_t chainidx, int *al)
+                              X509 *x, size_t chainidx)
 {
     if (context == SSL_EXT_TLS1_3_NEW_SESSION_TICKET) {
         unsigned long max_early_data;
 
         if (!PACKET_get_net_4(pkt, &max_early_data)
                 || PACKET_remaining(pkt) != 0) {
-            SSLerr(SSL_F_TLS_PARSE_STOC_EARLY_DATA,
-                   SSL_R_INVALID_MAX_EARLY_DATA);
-            *al = SSL_AD_DECODE_ERROR;
+            SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_EARLY_DATA,
+                     SSL_R_INVALID_MAX_EARLY_DATA);
             return 0;
         }
 
@@ -1694,7 +1770,8 @@ int tls_parse_stoc_early_data(SSL *s, PACKET *pkt, unsigned int context,
     }
 
     if (PACKET_remaining(pkt) != 0) {
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_EARLY_DATA,
+                 SSL_R_BAD_EXTENSION);
         return 0;
     }
 
@@ -1706,7 +1783,8 @@ int tls_parse_stoc_early_data(SSL *s, PACKET *pkt, unsigned int context,
          * using the first identity, or the SNI/ALPN is not consistent so the
          * server should not be accepting it.
          */
-        *al = SSL_AD_ILLEGAL_PARAMETER;
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_EARLY_DATA,
+                 SSL_R_BAD_EXTENSION);
         return 0;
     }
 
@@ -1716,14 +1794,14 @@ int tls_parse_stoc_early_data(SSL *s, PACKET *pkt, unsigned int context,
 }
 
 int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                       size_t chainidx, int *al)
+                       size_t chainidx)
 {
 #ifndef OPENSSL_NO_TLS1_3
     unsigned int identity;
 
     if (!PACKET_get_net_2(pkt, &identity) || PACKET_remaining(pkt) != 0) {
-        *al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PARSE_STOC_PSK, SSL_R_LENGTH_MISMATCH);
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_PSK,
+                 SSL_R_LENGTH_MISMATCH);
         return 0;
     }
 
@@ -1736,8 +1814,8 @@ int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
 
     if (s->psksession == NULL
             || s->psksession->ext.tick_identity != (int)identity) {
-        *al = SSL_AD_ILLEGAL_PARAMETER;
-        SSLerr(SSL_F_TLS_PARSE_STOC_PSK, SSL_R_BAD_PSK_IDENTITY);
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_PSK,
+                 SSL_R_BAD_PSK_IDENTITY);
         return 0;
     }
 
diff --git a/ssl/statem/extensions_cust.c b/ssl/statem/extensions_cust.c
index 055c850..0a23630 100644
--- a/ssl/statem/extensions_cust.c
+++ b/ssl/statem/extensions_cust.c
@@ -112,8 +112,9 @@ void custom_ext_init(custom_ext_methods *exts)
 /* Pass received custom extension data to the application for parsing. */
 int custom_ext_parse(SSL *s, unsigned int context, unsigned int ext_type,
                      const unsigned char *ext_data, size_t ext_size, X509 *x,
-                     size_t chainidx, int *al)
+                     size_t chainidx)
 {
+    int al;
     custom_ext_methods *exts = &s->cert->custext;
     custom_ext_method *meth;
     ENDPOINT role = ENDPOINT_BOTH;
@@ -138,7 +139,8 @@ int custom_ext_parse(SSL *s, unsigned int context, unsigned int ext_type,
          * extensions not sent in ClientHello.
          */
         if ((meth->ext_flags & SSL_EXT_FLAG_SENT) == 0) {
-            *al = TLS1_AD_UNSUPPORTED_EXTENSION;
+            SSLfatal(s, TLS1_AD_UNSUPPORTED_EXTENSION, SSL_F_CUSTOM_EXT_PARSE,
+                     SSL_R_BAD_EXTENSION);
             return 0;
         }
     }
@@ -155,8 +157,13 @@ int custom_ext_parse(SSL *s, unsigned int context, unsigned int ext_type,
     if (!meth->parse_cb)
         return 1;
 
-    return meth->parse_cb(s, ext_type, context, ext_data, ext_size, x, chainidx,
-                          al, meth->parse_arg);
+    if (meth->parse_cb(s, ext_type, context, ext_data, ext_size, x, chainidx,
+                       &al, meth->parse_arg) <= 0) {
+        SSLfatal(s, al, SSL_F_CUSTOM_EXT_PARSE, SSL_R_BAD_EXTENSION);
+        return 0;
+    }
+
+    return 1;
 }
 
 /*
@@ -164,11 +171,12 @@ int custom_ext_parse(SSL *s, unsigned int context, unsigned int ext_type,
  * buffer.
  */
 int custom_ext_add(SSL *s, int context, WPACKET *pkt, X509 *x, size_t chainidx,
-                   int maxversion, int *al)
+                   int maxversion)
 {
     custom_ext_methods *exts = &s->cert->custext;
     custom_ext_method *meth;
     size_t i;
+    int al;
 
     for (i = 0; i < exts->meths_count; i++) {
         const unsigned char *out = NULL;
@@ -197,11 +205,13 @@ int custom_ext_add(SSL *s, int context, WPACKET *pkt, X509 *x, size_t chainidx,
 
         if (meth->add_cb != NULL) {
             int cb_retval = meth->add_cb(s, meth->ext_type, context, &out,
-                                         &outlen, x, chainidx, al,
+                                         &outlen, x, chainidx, &al,
                                          meth->add_arg);
 
-            if (cb_retval < 0)
+            if (cb_retval < 0) {
+                SSLfatal(s, al, SSL_F_CUSTOM_EXT_ADD, SSL_R_CALLBACK_FAILED);
                 return 0;       /* error */
+            }
             if (cb_retval == 0)
                 continue;       /* skip this extension */
         }
@@ -210,7 +220,8 @@ int custom_ext_add(SSL *s, int context, WPACKET *pkt, X509 *x, size_t chainidx,
                 || !WPACKET_start_sub_packet_u16(pkt)
                 || (outlen > 0 && !WPACKET_memcpy(pkt, out, outlen))
                 || !WPACKET_close(pkt)) {
-            *al = SSL_AD_INTERNAL_ERROR;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CUSTOM_EXT_ADD,
+                     ERR_R_INTERNAL_ERROR);
             return 0;
         }
         if ((context & SSL_EXT_CLIENT_HELLO) != 0) {
@@ -218,7 +229,8 @@ int custom_ext_add(SSL *s, int context, WPACKET *pkt, X509 *x, size_t chainidx,
              * We can't send duplicates: code logic should prevent this.
              */
             if (!ossl_assert((meth->ext_flags & SSL_EXT_FLAG_SENT) == 0)) {
-                *al = SSL_AD_INTERNAL_ERROR;
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CUSTOM_EXT_ADD,
+                         ERR_R_INTERNAL_ERROR);
                 return 0;
             }
             /*
diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c
index 1b56fa1..c626ba6 100644
--- a/ssl/statem/extensions_srvr.c
+++ b/ssl/statem/extensions_srvr.c
@@ -15,7 +15,7 @@
  * Parse the client's renegotiation binding and abort if it's not right
  */
 int tls_parse_ctos_renegotiate(SSL *s, PACKET *pkt, unsigned int context,
-                               X509 *x, size_t chainidx, int *al)
+                               X509 *x, size_t chainidx)
 {
     unsigned int ilen;
     const unsigned char *data;
@@ -23,25 +23,22 @@ int tls_parse_ctos_renegotiate(SSL *s, PACKET *pkt, unsigned int context,
     /* Parse the length byte */
     if (!PACKET_get_1(pkt, &ilen)
         || !PACKET_get_bytes(pkt, &data, ilen)) {
-        SSLerr(SSL_F_TLS_PARSE_CTOS_RENEGOTIATE,
-               SSL_R_RENEGOTIATION_ENCODING_ERR);
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE,
+                 SSL_R_RENEGOTIATION_ENCODING_ERR);
         return 0;
     }
 
     /* Check that the extension matches */
     if (ilen != s->s3->previous_client_finished_len) {
-        SSLerr(SSL_F_TLS_PARSE_CTOS_RENEGOTIATE,
-               SSL_R_RENEGOTIATION_MISMATCH);
-        *al = SSL_AD_HANDSHAKE_FAILURE;
+        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE,
+                 SSL_R_RENEGOTIATION_MISMATCH);
         return 0;
     }
 
     if (memcmp(data, s->s3->previous_client_finished,
                s->s3->previous_client_finished_len)) {
-        SSLerr(SSL_F_TLS_PARSE_CTOS_RENEGOTIATE,
-               SSL_R_RENEGOTIATION_MISMATCH);
-        *al = SSL_AD_HANDSHAKE_FAILURE;
+        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE,
+                 SSL_R_RENEGOTIATION_MISMATCH);
         return 0;
     }
 
@@ -74,7 +71,7 @@ int tls_parse_ctos_renegotiate(SSL *s, PACKET *pkt, unsigned int context,
  * - On session reconnect, the servername extension may be absent.
  */
 int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, unsigned int context,
-                               X509 *x, size_t chainidx, int *al)
+                               X509 *x, size_t chainidx)
 {
     unsigned int servname_type;
     PACKET sni, hostname;
@@ -82,7 +79,8 @@ int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, unsigned int context,
     if (!PACKET_as_length_prefixed_2(pkt, &sni)
         /* ServerNameList must be at least 1 byte long. */
         || PACKET_remaining(&sni) == 0) {
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
+                 SSL_R_BAD_EXTENSION);
         return 0;
     }
 
@@ -100,25 +98,31 @@ int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, unsigned int context,
     if (!PACKET_get_1(&sni, &servname_type)
         || servname_type != TLSEXT_NAMETYPE_host_name
         || !PACKET_as_length_prefixed_2(&sni, &hostname)) {
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
+                 SSL_R_BAD_EXTENSION);
         return 0;
     }
 
     if (!s->hit) {
         if (PACKET_remaining(&hostname) > TLSEXT_MAXLEN_host_name) {
-            *al = TLS1_AD_UNRECOGNIZED_NAME;
+            SSLfatal(s, SSL_AD_UNRECOGNIZED_NAME,
+                     SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
+                     SSL_R_BAD_EXTENSION);
             return 0;
         }
 
         if (PACKET_contains_zero_byte(&hostname)) {
-            *al = TLS1_AD_UNRECOGNIZED_NAME;
+            SSLfatal(s, SSL_AD_UNRECOGNIZED_NAME,
+                     SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
+                     SSL_R_BAD_EXTENSION);
             return 0;
         }
 
         OPENSSL_free(s->session->ext.hostname);
         s->session->ext.hostname = NULL;
         if (!PACKET_strndup(&hostname, &s->session->ext.hostname)) {
-            *al = TLS1_AD_INTERNAL_ERROR;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
+                     ERR_R_INTERNAL_ERROR);
             return 0;
         }
 
@@ -140,18 +144,21 @@ int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, unsigned int context,
 }
 
 int tls_parse_ctos_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
-                                  X509 *x, size_t chainidx, int *al)
+                                  X509 *x, size_t chainidx)
 {
     unsigned int value;
 
     if (PACKET_remaining(pkt) != 1 || !PACKET_get_1(pkt, &value)) {
-        *al = TLS1_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN,
+                 SSL_R_BAD_EXTENSION);
         return 0;
     }
 
     /* Received |value| should be a valid max-fragment-length code. */
     if (!IS_MAX_FRAGMENT_LENGTH_EXT_VALID(value)) {
-        *al = SSL_AD_ILLEGAL_PARAMETER;
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+                 SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN,
+                 SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
         return 0;
     }
 
@@ -161,7 +168,9 @@ int tls_parse_ctos_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
      * We should receive the same code as in resumed session !
      */
     if (s->hit && s->session->ext.max_fragment_len_mode != value) {
-        *al = SSL_AD_ILLEGAL_PARAMETER;
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+                 SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN,
+                 SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
         return 0;
     }
 
@@ -175,13 +184,15 @@ int tls_parse_ctos_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
 
 #ifndef OPENSSL_NO_SRP
 int tls_parse_ctos_srp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                       size_t chainidx, int *al)
+                       size_t chainidx)
 {
     PACKET srp_I;
 
     if (!PACKET_as_length_prefixed_1(pkt, &srp_I)
             || PACKET_contains_zero_byte(&srp_I)) {
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR,
+                 SSL_F_TLS_PARSE_CTOS_SRP,
+                 SSL_R_BAD_EXTENSION);
         return 0;
     }
 
@@ -190,7 +201,8 @@ int tls_parse_ctos_srp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
      * upon resumption. Instead, we MUST ignore the login.
      */
     if (!PACKET_strndup(&srp_I, &s->srp_ctx.login)) {
-        *al = SSL_AD_INTERNAL_ERROR;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_SRP,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
@@ -200,13 +212,14 @@ int tls_parse_ctos_srp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
 
 #ifndef OPENSSL_NO_EC
 int tls_parse_ctos_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
-                                 X509 *x, size_t chainidx, int *al)
+                                 X509 *x, size_t chainidx)
 {
     PACKET ec_point_format_list;
 
     if (!PACKET_as_length_prefixed_1(pkt, &ec_point_format_list)
         || PACKET_remaining(&ec_point_format_list) == 0) {
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS,
+                 SSL_R_BAD_EXTENSION);
         return 0;
     }
 
@@ -214,7 +227,8 @@ int tls_parse_ctos_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
         if (!PACKET_memdup(&ec_point_format_list,
                            &s->session->ext.ecpointformats,
                            &s->session->ext.ecpointformats_len)) {
-            *al = SSL_AD_INTERNAL_ERROR;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
             return 0;
         }
     }
@@ -224,13 +238,14 @@ int tls_parse_ctos_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
 #endif                          /* OPENSSL_NO_EC */
 
 int tls_parse_ctos_session_ticket(SSL *s, PACKET *pkt, unsigned int context,
-                                  X509 *x, size_t chainidx, int *al)
+                                  X509 *x, size_t chainidx)
 {
     if (s->ext.session_ticket_cb &&
             !s->ext.session_ticket_cb(s, PACKET_data(pkt),
                                   PACKET_remaining(pkt),
                                   s->ext.session_ticket_cb_arg)) {
-        *al = SSL_AD_INTERNAL_ERROR;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_PARSE_CTOS_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
@@ -238,18 +253,20 @@ int tls_parse_ctos_session_ticket(SSL *s, PACKET *pkt, unsigned int context,
 }
 
 int tls_parse_ctos_sig_algs(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                            size_t chainidx, int *al)
+                            size_t chainidx)
 {
     PACKET supported_sig_algs;
 
     if (!PACKET_as_length_prefixed_2(pkt, &supported_sig_algs)
             || PACKET_remaining(&supported_sig_algs) == 0) {
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR,
+                 SSL_F_TLS_PARSE_CTOS_SIG_ALGS, SSL_R_BAD_EXTENSION);
         return 0;
     }
 
     if (!s->hit && !tls1_save_sigalgs(s, &supported_sig_algs)) {
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR,
+                 SSL_F_TLS_PARSE_CTOS_SIG_ALGS, SSL_R_BAD_EXTENSION);
         return 0;
     }
 
@@ -258,7 +275,7 @@ int tls_parse_ctos_sig_algs(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
 
 #ifndef OPENSSL_NO_OCSP
 int tls_parse_ctos_status_request(SSL *s, PACKET *pkt, unsigned int context,
-                                  X509 *x, size_t chainidx, int *al)
+                                  X509 *x, size_t chainidx)
 {
     PACKET responder_id_list, exts;
 
@@ -267,7 +284,8 @@ int tls_parse_ctos_status_request(SSL *s, PACKET *pkt, unsigned int context,
         return 1;
 
     if (!PACKET_get_1(pkt, (unsigned int *)&s->ext.status_type)) {
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR,
+                 SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
         return 0;
     }
 
@@ -280,7 +298,8 @@ int tls_parse_ctos_status_request(SSL *s, PACKET *pkt, unsigned int context,
     }
 
     if (!PACKET_get_length_prefixed_2 (pkt, &responder_id_list)) {
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR,
+                 SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
         return 0;
     }
 
@@ -292,7 +311,8 @@ int tls_parse_ctos_status_request(SSL *s, PACKET *pkt, unsigned int context,
     if (PACKET_remaining(&responder_id_list) > 0) {
         s->ext.ocsp.ids = sk_OCSP_RESPID_new_null();
         if (s->ext.ocsp.ids == NULL) {
-            *al = SSL_AD_INTERNAL_ERROR;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, ERR_R_MALLOC_FAILURE);
             return 0;
         }
     } else {
@@ -306,7 +326,8 @@ int tls_parse_ctos_status_request(SSL *s, PACKET *pkt, unsigned int context,
 
         if (!PACKET_get_length_prefixed_2(&responder_id_list, &responder_id)
                 || PACKET_remaining(&responder_id) == 0) {
-            *al = SSL_AD_DECODE_ERROR;
+            SSLfatal(s, SSL_AD_DECODE_ERROR,
+                     SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
             return 0;
         }
 
@@ -315,26 +336,32 @@ int tls_parse_ctos_status_request(SSL *s, PACKET *pkt, unsigned int context,
         id = d2i_OCSP_RESPID(NULL, &id_data,
                              (int)PACKET_remaining(&responder_id));
         if (id == NULL) {
-            *al = SSL_AD_DECODE_ERROR;
+            SSLfatal(s, SSL_AD_DECODE_ERROR,
+                     SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
             return 0;
         }
 
         if (id_data != PACKET_end(&responder_id)) {
             OCSP_RESPID_free(id);
-            *al = SSL_AD_DECODE_ERROR;
+            SSLfatal(s, SSL_AD_DECODE_ERROR,
+                     SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
+
             return 0;
         }
 
         if (!sk_OCSP_RESPID_push(s->ext.ocsp.ids, id)) {
             OCSP_RESPID_free(id);
-            *al = SSL_AD_INTERNAL_ERROR;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
+
             return 0;
         }
     }
 
     /* Read in request_extensions */
     if (!PACKET_as_length_prefixed_2(pkt, &exts)) {
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR,
+                 SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
         return 0;
     }
 
@@ -346,7 +373,8 @@ int tls_parse_ctos_status_request(SSL *s, PACKET *pkt, unsigned int context,
         s->ext.ocsp.exts =
             d2i_X509_EXTENSIONS(NULL, &ext_data, (int)PACKET_remaining(&exts));
         if (s->ext.ocsp.exts == NULL || ext_data != PACKET_end(&exts)) {
-            *al = SSL_AD_DECODE_ERROR;
+            SSLfatal(s, SSL_AD_DECODE_ERROR,
+                     SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
             return 0;
         }
     }
@@ -357,7 +385,7 @@ int tls_parse_ctos_status_request(SSL *s, PACKET *pkt, unsigned int context,
 
 #ifndef OPENSSL_NO_NEXTPROTONEG
 int tls_parse_ctos_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                       size_t chainidx, int *al)
+                       size_t chainidx)
 {
     /*
      * We shouldn't accept this extension on a
@@ -372,11 +400,10 @@ int tls_parse_ctos_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
 
 /*
  * Save the ALPN extension in a ClientHello.|pkt| holds the contents of the ALPN
- * extension, not including type and length. |al| is a pointer to the alert
- * value to send in the event of a failure. Returns: 1 on success, 0 on error.
+ * extension, not including type and length. Returns: 1 on success, 0 on error.
  */
 int tls_parse_ctos_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                        size_t chainidx, int *al)
+                        size_t chainidx)
 {
     PACKET protocol_list, save_protocol_list, protocol;
 
@@ -385,7 +412,8 @@ int tls_parse_ctos_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
 
     if (!PACKET_as_length_prefixed_2(pkt, &protocol_list)
         || PACKET_remaining(&protocol_list) < 2) {
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_ALPN,
+                 SSL_R_BAD_EXTENSION);
         return 0;
     }
 
@@ -394,7 +422,8 @@ int tls_parse_ctos_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
         /* Protocol names can't be empty. */
         if (!PACKET_get_length_prefixed_1(&protocol_list, &protocol)
                 || PACKET_remaining(&protocol) == 0) {
-            *al = SSL_AD_DECODE_ERROR;
+            SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_ALPN,
+                     SSL_R_BAD_EXTENSION);
             return 0;
         }
     } while (PACKET_remaining(&protocol_list) != 0);
@@ -404,7 +433,8 @@ int tls_parse_ctos_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
     s->s3->alpn_proposed_len = 0;
     if (!PACKET_memdup(&save_protocol_list,
                        &s->s3->alpn_proposed, &s->s3->alpn_proposed_len)) {
-        *al = SSL_AD_INTERNAL_ERROR;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_ALPN,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
@@ -413,7 +443,7 @@ int tls_parse_ctos_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
 
 #ifndef OPENSSL_NO_SRTP
 int tls_parse_ctos_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                            size_t chainidx, int *al)
+                            size_t chainidx)
 {
     STACK_OF(SRTP_PROTECTION_PROFILE) *srvr;
     unsigned int ct, mki_len, id;
@@ -427,9 +457,8 @@ int tls_parse_ctos_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
     /* Pull off the length of the cipher suite list  and check it is even */
     if (!PACKET_get_net_2(pkt, &ct) || (ct & 1) != 0
             || !PACKET_get_sub_packet(pkt, &subpkt, ct)) {
-        SSLerr(SSL_F_TLS_PARSE_CTOS_USE_SRTP,
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP,
                SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
-        *al = SSL_AD_DECODE_ERROR;
         return 0;
     }
 
@@ -440,9 +469,8 @@ int tls_parse_ctos_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
 
     while (PACKET_remaining(&subpkt)) {
         if (!PACKET_get_net_2(&subpkt, &id)) {
-            SSLerr(SSL_F_TLS_PARSE_CTOS_USE_SRTP,
-                   SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
-            *al = SSL_AD_DECODE_ERROR;
+            SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP,
+                     SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
             return 0;
         }
 
@@ -466,16 +494,15 @@ int tls_parse_ctos_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
 
     /* Now extract the MKI value as a sanity check, but discard it for now */
     if (!PACKET_get_1(pkt, &mki_len)) {
-        SSLerr(SSL_F_TLS_PARSE_CTOS_USE_SRTP,
-               SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP,
+                 SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
         return 0;
     }
 
     if (!PACKET_forward(pkt, mki_len)
         || PACKET_remaining(pkt)) {
-        SSLerr(SSL_F_TLS_PARSE_CTOS_USE_SRTP, SSL_R_BAD_SRTP_MKI_VALUE);
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP,
+                 SSL_R_BAD_SRTP_MKI_VALUE);
         return 0;
     }
 
@@ -484,7 +511,7 @@ int tls_parse_ctos_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
 #endif
 
 int tls_parse_ctos_etm(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                       size_t chainidx, int *al)
+                       size_t chainidx)
 {
     if (!(s->options & SSL_OP_NO_ENCRYPT_THEN_MAC))
         s->ext.use_etm = 1;
@@ -495,10 +522,9 @@ int tls_parse_ctos_etm(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
 /*
  * Process a psk_kex_modes extension received in the ClientHello. |pkt| contains
  * the raw PACKET data for the extension. Returns 1 on success or 0 on failure.
- * If a failure occurs then |*al| is set to an appropriate alert value.
  */
 int tls_parse_ctos_psk_kex_modes(SSL *s, PACKET *pkt, unsigned int context,
-                                 X509 *x, size_t chainidx, int *al)
+                                 X509 *x, size_t chainidx)
 {
 #ifndef OPENSSL_NO_TLS1_3
     PACKET psk_kex_modes;
@@ -506,7 +532,8 @@ int tls_parse_ctos_psk_kex_modes(SSL *s, PACKET *pkt, unsigned int context,
 
     if (!PACKET_as_length_prefixed_1(pkt, &psk_kex_modes)
             || PACKET_remaining(&psk_kex_modes) == 0) {
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES,
+                 SSL_R_BAD_EXTENSION);
         return 0;
     }
 
@@ -525,10 +552,9 @@ int tls_parse_ctos_psk_kex_modes(SSL *s, PACKET *pkt, unsigned int context,
 /*
  * Process a key_share extension received in the ClientHello. |pkt| contains
  * the raw PACKET data for the extension. Returns 1 on success or 0 on failure.
- * If a failure occurs then |*al| is set to an appropriate alert value.
  */
 int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                             size_t chainidx, int *al)
+                             size_t chainidx)
 {
 #ifndef OPENSSL_NO_TLS1_3
     unsigned int group_id;
@@ -542,14 +568,14 @@ int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
 
     /* Sanity check */
     if (s->s3->peer_tmp != NULL) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
     if (!PACKET_as_length_prefixed_2(pkt, &key_share_list)) {
-        *al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_LENGTH_MISMATCH);
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
+                 SSL_R_LENGTH_MISMATCH);
         return 0;
     }
 
@@ -563,9 +589,8 @@ int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
          * because we verify that the length is non-zero when we process that
          * extension.
          */
-        *al = SSL_AD_MISSING_EXTENSION;
-        SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
-               SSL_R_MISSING_SUPPORTED_GROUPS_EXTENSION);
+        SSLfatal(s, SSL_AD_MISSING_EXTENSION, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
+                 SSL_R_MISSING_SUPPORTED_GROUPS_EXTENSION);
         return 0;
     }
 
@@ -573,9 +598,8 @@ int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
         if (!PACKET_get_net_2(&key_share_list, &group_id)
                 || !PACKET_get_length_prefixed_2(&key_share_list, &encoded_pt)
                 || PACKET_remaining(&encoded_pt) == 0) {
-            *al = SSL_AD_DECODE_ERROR;
-            SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
-                   SSL_R_LENGTH_MISMATCH);
+            SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
+                     SSL_R_LENGTH_MISMATCH);
             return 0;
         }
 
@@ -588,8 +612,8 @@ int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
 
         /* Check if this share is in supported_groups sent from client */
         if (!check_in_list(s, group_id, clntgroups, clnt_num_groups, 0)) {
-            *al = SSL_AD_ILLEGAL_PARAMETER;
-            SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_KEY_SHARE);
+            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+                     SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_KEY_SHARE);
             return 0;
         }
 
@@ -600,8 +624,7 @@ int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
         }
 
         if ((s->s3->peer_tmp = ssl_generate_param_group(group_id)) == NULL) {
-            *al = SSL_AD_INTERNAL_ERROR;
-            SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
                    SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
             return 0;
         }
@@ -611,8 +634,8 @@ int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
         if (!EVP_PKEY_set1_tls_encodedpoint(s->s3->peer_tmp,
                 PACKET_data(&encoded_pt),
                 PACKET_remaining(&encoded_pt))) {
-            *al = SSL_AD_ILLEGAL_PARAMETER;
-            SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_ECPOINT);
+            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+                     SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_ECPOINT);
             return 0;
         }
 
@@ -625,7 +648,7 @@ int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
 
 #ifndef OPENSSL_NO_EC
 int tls_parse_ctos_supported_groups(SSL *s, PACKET *pkt, unsigned int context,
-                                    X509 *x, size_t chainidx, int *al)
+                                    X509 *x, size_t chainidx)
 {
     PACKET supported_groups_list;
 
@@ -633,7 +656,8 @@ int tls_parse_ctos_supported_groups(SSL *s, PACKET *pkt, unsigned int context,
     if (!PACKET_as_length_prefixed_2(pkt, &supported_groups_list)
             || PACKET_remaining(&supported_groups_list) == 0
             || (PACKET_remaining(&supported_groups_list) % 2) != 0) {
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR,
+                 SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS, SSL_R_BAD_EXTENSION);
         return 0;
     }
 
@@ -644,7 +668,9 @@ int tls_parse_ctos_supported_groups(SSL *s, PACKET *pkt, unsigned int context,
         if (!tls1_save_u16(&supported_groups_list,
                            &s->session->ext.supportedgroups,
                            &s->session->ext.supportedgroups_len)) {
-            *al = SSL_AD_INTERNAL_ERROR;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS,
+                     ERR_R_INTERNAL_ERROR);
             return 0;
         }
     }
@@ -654,11 +680,12 @@ int tls_parse_ctos_supported_groups(SSL *s, PACKET *pkt, unsigned int context,
 #endif
 
 int tls_parse_ctos_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                       size_t chainidx, int *al)
+                       size_t chainidx)
 {
     /* The extension must always be empty */
     if (PACKET_remaining(pkt) != 0) {
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR,
+                 SSL_F_TLS_PARSE_CTOS_EMS, SSL_R_BAD_EXTENSION);
         return 0;
     }
 
@@ -669,15 +696,17 @@ int tls_parse_ctos_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
 
 
 int tls_parse_ctos_early_data(SSL *s, PACKET *pkt, unsigned int context,
-                              X509 *x, size_t chainidx, int *al)
+                              X509 *x, size_t chainidx)
 {
     if (PACKET_remaining(pkt) != 0) {
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR,
+                 SSL_F_TLS_PARSE_CTOS_EARLY_DATA, SSL_R_BAD_EXTENSION);
         return 0;
     }
 
     if (s->hello_retry_request) {
-        *al = SSL_AD_ILLEGAL_PARAMETER;
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+                 SSL_F_TLS_PARSE_CTOS_EARLY_DATA, SSL_R_BAD_EXTENSION);
         return 0;
     }
 
@@ -685,7 +714,7 @@ int tls_parse_ctos_early_data(SSL *s, PACKET *pkt, unsigned int context,
 }
 
 int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                       size_t chainidx, int *al)
+                       size_t chainidx)
 {
     PACKET identities, binders, binder;
     size_t binderoffset, hashsize;
@@ -702,7 +731,8 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
         return 1;
 
     if (!PACKET_get_length_prefixed_2(pkt, &identities)) {
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR,
+                 SSL_F_TLS_PARSE_CTOS_PSK, SSL_R_BAD_EXTENSION);
         return 0;
     }
 
@@ -712,7 +742,8 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
 
         if (!PACKET_get_length_prefixed_2(&identities, &identity)
                 || !PACKET_get_net_4(&identities, &ticket_agel)) {
-            *al = SSL_AD_DECODE_ERROR;
+            SSLfatal(s, SSL_AD_DECODE_ERROR,
+                     SSL_F_TLS_PARSE_CTOS_PSK, SSL_R_BAD_EXTENSION);
             return 0;
         }
 
@@ -720,7 +751,8 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
                 && !s->psk_find_session_cb(s, PACKET_data(&identity),
                                            PACKET_remaining(&identity),
                                            &sess)) {
-            *al = SSL_AD_INTERNAL_ERROR;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_PARSE_CTOS_PSK, SSL_R_BAD_EXTENSION);
             return 0;
         }
 
@@ -729,7 +761,8 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
             SSL_SESSION *sesstmp = ssl_session_dup(sess, 0);
 
             if (sesstmp == NULL) {
-                *al = SSL_AD_INTERNAL_ERROR;
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_TLS_PARSE_CTOS_PSK, ERR_R_INTERNAL_ERROR);
                 return 0;
             }
             SSL_SESSION_free(sess);
@@ -752,7 +785,8 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
 
             if (ret == TICKET_FATAL_ERR_MALLOC
                     || ret == TICKET_FATAL_ERR_OTHER) {
-                *al = SSL_AD_INTERNAL_ERROR;
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_TLS_PARSE_CTOS_PSK, ERR_R_INTERNAL_ERROR);
                 return 0;
             }
             if (ret == TICKET_NO_DECRYPT)
@@ -803,13 +837,15 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
     hashsize = EVP_MD_size(md);
 
     if (!PACKET_get_length_prefixed_2(pkt, &binders)) {
-        *al = SSL_AD_DECODE_ERROR;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
+                 SSL_R_BAD_EXTENSION);
         goto err;
     }
 
     for (i = 0; i <= id; i++) {
         if (!PACKET_get_length_prefixed_1(&binders, &binder)) {
-            *al = SSL_AD_DECODE_ERROR;
+            SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
+                     SSL_R_BAD_EXTENSION);
             goto err;
         }
     }
@@ -819,8 +855,7 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
                                  (const unsigned char *)s->init_buf->data,
                                  binderoffset, PACKET_data(&binder), NULL,
                                  sess, 0, ext) != 1) {
-        *al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PARSE_CTOS_PSK, ERR_R_INTERNAL_ERROR);
+        /* SSLfatal() already called */
         goto err;
     }
 
@@ -839,7 +874,7 @@ err:
  */
 EXT_RETURN tls_construct_stoc_renegotiate(SSL *s, WPACKET *pkt,
                                           unsigned int context, X509 *x,
-                                          size_t chainidx, int *al)
+                                          size_t chainidx)
 {
     if (!s->s3->send_connection_binding)
         return EXT_RETURN_NOT_SENT;
@@ -854,7 +889,8 @@ EXT_RETURN tls_construct_stoc_renegotiate(SSL *s, WPACKET *pkt,
                                s->s3->previous_server_finished_len)
             || !WPACKET_close(pkt)
             || !WPACKET_close(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_STOC_RENEGOTIATE, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_RENEGOTIATE,
+                 ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -863,7 +899,7 @@ EXT_RETURN tls_construct_stoc_renegotiate(SSL *s, WPACKET *pkt,
 
 EXT_RETURN tls_construct_stoc_server_name(SSL *s, WPACKET *pkt,
                                           unsigned int context, X509 *x,
-                                          size_t chainidx, int *al)
+                                          size_t chainidx)
 {
     if (s->hit || s->servername_done != 1
             || s->session->ext.hostname == NULL)
@@ -871,7 +907,8 @@ EXT_RETURN tls_construct_stoc_server_name(SSL *s, WPACKET *pkt,
 
     if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_server_name)
             || !WPACKET_put_bytes_u16(pkt, 0)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_STOC_SERVER_NAME, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_SERVER_NAME,
+                 ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -881,7 +918,7 @@ EXT_RETURN tls_construct_stoc_server_name(SSL *s, WPACKET *pkt,
 /* Add/include the server's max fragment len extension into ServerHello */
 EXT_RETURN tls_construct_stoc_maxfragmentlen(SSL *s, WPACKET *pkt,
                                              unsigned int context, X509 *x,
-                                             size_t chainidx, int *al)
+                                             size_t chainidx)
 {
     if (!USE_MAX_FRAGMENT_LENGTH_EXT(s->session))
         return EXT_RETURN_NOT_SENT;
@@ -894,7 +931,8 @@ EXT_RETURN tls_construct_stoc_maxfragmentlen(SSL *s, WPACKET *pkt,
         || !WPACKET_start_sub_packet_u16(pkt)
         || !WPACKET_put_bytes_u8(pkt, s->session->ext.max_fragment_len_mode)
         || !WPACKET_close(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_STOC_MAXFRAGMENTLEN, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_STOC_MAXFRAGMENTLEN, ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -904,7 +942,7 @@ EXT_RETURN tls_construct_stoc_maxfragmentlen(SSL *s, WPACKET *pkt,
 #ifndef OPENSSL_NO_EC
 EXT_RETURN tls_construct_stoc_ec_pt_formats(SSL *s, WPACKET *pkt,
                                             unsigned int context, X509 *x,
-                                            size_t chainidx, int *al)
+                                            size_t chainidx)
 {
     unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
     unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth;
@@ -921,7 +959,8 @@ EXT_RETURN tls_construct_stoc_ec_pt_formats(SSL *s, WPACKET *pkt,
             || !WPACKET_start_sub_packet_u16(pkt)
             || !WPACKET_sub_memcpy_u8(pkt, plist, plistlen)
             || !WPACKET_close(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_STOC_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_STOC_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -932,7 +971,7 @@ EXT_RETURN tls_construct_stoc_ec_pt_formats(SSL *s, WPACKET *pkt,
 #ifndef OPENSSL_NO_EC
 EXT_RETURN tls_construct_stoc_supported_groups(SSL *s, WPACKET *pkt,
                                                unsigned int context, X509 *x,
-                                               size_t chainidx, int *al)
+                                               size_t chainidx)
 {
     const uint16_t *groups;
     size_t numgroups, i, first = 1;
@@ -944,7 +983,8 @@ EXT_RETURN tls_construct_stoc_supported_groups(SSL *s, WPACKET *pkt,
     /* Get our list of supported groups */
     tls1_get_supported_groups(s, &groups, &numgroups);
     if (numgroups == 0) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS, ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -966,23 +1006,27 @@ EXT_RETURN tls_construct_stoc_supported_groups(SSL *s, WPACKET *pkt,
                            /* Sub-packet for supported_groups extension */
                         || !WPACKET_start_sub_packet_u16(pkt)
                         || !WPACKET_start_sub_packet_u16(pkt)) {
-                    SSLerr(SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS,
-                           ERR_R_INTERNAL_ERROR);
+                    SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                             SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS,
+                             ERR_R_INTERNAL_ERROR);
                     return EXT_RETURN_FAIL;
                 }
 
                 first = 0;
             }
             if (!WPACKET_put_bytes_u16(pkt, group)) {
-                    SSLerr(SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS,
-                           ERR_R_INTERNAL_ERROR);
+                    SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                             SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS,
+                             ERR_R_INTERNAL_ERROR);
                     return EXT_RETURN_FAIL;
                 }
         }
     }
 
     if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS,
+                 ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -992,7 +1036,7 @@ EXT_RETURN tls_construct_stoc_supported_groups(SSL *s, WPACKET *pkt,
 
 EXT_RETURN tls_construct_stoc_session_ticket(SSL *s, WPACKET *pkt,
                                              unsigned int context, X509 *x,
-                                             size_t chainidx, int *al)
+                                             size_t chainidx)
 {
     if (!s->ext.ticket_expected || !tls_use_ticket(s)) {
         s->ext.ticket_expected = 0;
@@ -1001,7 +1045,8 @@ EXT_RETURN tls_construct_stoc_session_ticket(SSL *s, WPACKET *pkt,
 
     if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_session_ticket)
             || !WPACKET_put_bytes_u16(pkt, 0)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_STOC_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_STOC_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -1011,7 +1056,7 @@ EXT_RETURN tls_construct_stoc_session_ticket(SSL *s, WPACKET *pkt,
 #ifndef OPENSSL_NO_OCSP
 EXT_RETURN tls_construct_stoc_status_request(SSL *s, WPACKET *pkt,
                                              unsigned int context, X509 *x,
-                                             size_t chainidx, int *al)
+                                             size_t chainidx)
 {
     if (!s->ext.status_expected)
         return EXT_RETURN_NOT_SENT;
@@ -1021,7 +1066,8 @@ EXT_RETURN tls_construct_stoc_status_request(SSL *s, WPACKET *pkt,
 
     if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_status_request)
             || !WPACKET_start_sub_packet_u16(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -1030,9 +1076,13 @@ EXT_RETURN tls_construct_stoc_status_request(SSL *s, WPACKET *pkt,
      * send back an empty extension, with the certificate status appearing as a
      * separate message
      */
-    if ((SSL_IS_TLS13(s) && !tls_construct_cert_status_body(s, pkt))
-            || !WPACKET_close(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
+    if (SSL_IS_TLS13(s) && !tls_construct_cert_status_body(s, pkt)) {
+       /* SSLfatal() already called */
+       return EXT_RETURN_FAIL; 
+    }
+    if (!WPACKET_close(pkt)) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -1043,7 +1093,7 @@ EXT_RETURN tls_construct_stoc_status_request(SSL *s, WPACKET *pkt,
 #ifndef OPENSSL_NO_NEXTPROTONEG
 EXT_RETURN tls_construct_stoc_next_proto_neg(SSL *s, WPACKET *pkt,
                                              unsigned int context, X509 *x,
-                                             size_t chainidx, int *al)
+                                             size_t chainidx)
 {
     const unsigned char *npa;
     unsigned int npalen;
@@ -1059,8 +1109,9 @@ EXT_RETURN tls_construct_stoc_next_proto_neg(SSL *s, WPACKET *pkt,
     if (ret == SSL_TLSEXT_ERR_OK) {
         if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_next_proto_neg)
                 || !WPACKET_sub_memcpy_u16(pkt, npa, npalen)) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_STOC_NEXT_PROTO_NEG,
-                   ERR_R_INTERNAL_ERROR);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_STOC_NEXT_PROTO_NEG,
+                     ERR_R_INTERNAL_ERROR);
             return EXT_RETURN_FAIL;
         }
         s->s3->npn_seen = 1;
@@ -1071,7 +1122,7 @@ EXT_RETURN tls_construct_stoc_next_proto_neg(SSL *s, WPACKET *pkt,
 #endif
 
 EXT_RETURN tls_construct_stoc_alpn(SSL *s, WPACKET *pkt, unsigned int context,
-                                   X509 *x, size_t chainidx, int *al)
+                                   X509 *x, size_t chainidx)
 {
     if (s->s3->alpn_selected == NULL)
         return EXT_RETURN_NOT_SENT;
@@ -1084,7 +1135,8 @@ EXT_RETURN tls_construct_stoc_alpn(SSL *s, WPACKET *pkt, unsigned int context,
                                       s->s3->alpn_selected_len)
             || !WPACKET_close(pkt)
             || !WPACKET_close(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_STOC_ALPN, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_STOC_ALPN, ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -1094,7 +1146,7 @@ EXT_RETURN tls_construct_stoc_alpn(SSL *s, WPACKET *pkt, unsigned int context,
 #ifndef OPENSSL_NO_SRTP
 EXT_RETURN tls_construct_stoc_use_srtp(SSL *s, WPACKET *pkt,
                                        unsigned int context, X509 *x,
-                                       size_t chainidx, int *al)
+                                       size_t chainidx)
 {
     if (s->srtp_profile == NULL)
         return EXT_RETURN_NOT_SENT;
@@ -1105,7 +1157,8 @@ EXT_RETURN tls_construct_stoc_use_srtp(SSL *s, WPACKET *pkt,
             || !WPACKET_put_bytes_u16(pkt, s->srtp_profile->id)
             || !WPACKET_put_bytes_u8(pkt, 0)
             || !WPACKET_close(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_STOC_USE_SRTP, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_USE_SRTP,
+                 ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -1114,7 +1167,7 @@ EXT_RETURN tls_construct_stoc_use_srtp(SSL *s, WPACKET *pkt,
 #endif
 
 EXT_RETURN tls_construct_stoc_etm(SSL *s, WPACKET *pkt, unsigned int context,
-                                  X509 *x, size_t chainidx, int *al)
+                                  X509 *x, size_t chainidx)
 {
     if (!s->ext.use_etm)
         return EXT_RETURN_NOT_SENT;
@@ -1133,7 +1186,8 @@ EXT_RETURN tls_construct_stoc_etm(SSL *s, WPACKET *pkt, unsigned int context,
 
     if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_encrypt_then_mac)
             || !WPACKET_put_bytes_u16(pkt, 0)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_STOC_ETM, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_ETM,
+                 ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -1141,14 +1195,15 @@ EXT_RETURN tls_construct_stoc_etm(SSL *s, WPACKET *pkt, unsigned int context,
 }
 
 EXT_RETURN tls_construct_stoc_ems(SSL *s, WPACKET *pkt, unsigned int context,
-                                  X509 *x, size_t chainidx, int *al)
+                                  X509 *x, size_t chainidx)
 {
     if ((s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) == 0)
         return EXT_RETURN_NOT_SENT;
 
     if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_extended_master_secret)
             || !WPACKET_put_bytes_u16(pkt, 0)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_STOC_EMS, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_EMS,
+                 ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -1157,7 +1212,7 @@ EXT_RETURN tls_construct_stoc_ems(SSL *s, WPACKET *pkt, unsigned int context,
 
 EXT_RETURN tls_construct_stoc_key_share(SSL *s, WPACKET *pkt,
                                         unsigned int context, X509 *x,
-                                        size_t chainidx, int *al)
+                                        size_t chainidx)
 {
 #ifndef OPENSSL_NO_TLS1_3
     unsigned char *encodedPoint;
@@ -1171,8 +1226,9 @@ EXT_RETURN tls_construct_stoc_key_share(SSL *s, WPACKET *pkt,
                     || !WPACKET_start_sub_packet_u16(pkt)
                     || !WPACKET_put_bytes_u16(pkt, s->s3->group_id)
                     || !WPACKET_close(pkt)) {
-                SSLerr(SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
-                       ERR_R_INTERNAL_ERROR);
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
+                         ERR_R_INTERNAL_ERROR);
                 return EXT_RETURN_FAIL;
             }
 
@@ -1181,8 +1237,8 @@ EXT_RETURN tls_construct_stoc_key_share(SSL *s, WPACKET *pkt,
 
         /* Must be resuming. */
         if (!s->hit || !tls13_generate_handshake_secret(s, NULL, 0)) {
-            *al = SSL_AD_INTERNAL_ERROR;
-            SSLerr(SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR);
             return EXT_RETURN_FAIL;
         }
         return EXT_RETURN_NOT_SENT;
@@ -1191,27 +1247,31 @@ EXT_RETURN tls_construct_stoc_key_share(SSL *s, WPACKET *pkt,
     if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share)
             || !WPACKET_start_sub_packet_u16(pkt)
             || !WPACKET_put_bytes_u16(pkt, s->s3->group_id)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
     skey = ssl_generate_pkey(ckey);
     if (skey == NULL) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE, ERR_R_MALLOC_FAILURE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
+                 ERR_R_MALLOC_FAILURE);
         return EXT_RETURN_FAIL;
     }
 
     /* Generate encoding of server key */
     encoded_pt_len = EVP_PKEY_get1_tls_encodedpoint(skey, &encodedPoint);
     if (encoded_pt_len == 0) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE, ERR_R_EC_LIB);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
+                 ERR_R_EC_LIB);
         EVP_PKEY_free(skey);
         return EXT_RETURN_FAIL;
     }
 
     if (!WPACKET_sub_memcpy_u16(pkt, encodedPoint, encoded_pt_len)
             || !WPACKET_close(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
+                 ERR_R_INTERNAL_ERROR);
         EVP_PKEY_free(skey);
         OPENSSL_free(encodedPoint);
         return EXT_RETURN_FAIL;
@@ -1221,7 +1281,7 @@ EXT_RETURN tls_construct_stoc_key_share(SSL *s, WPACKET *pkt,
     /* This causes the crypto state to be updated based on the derived keys */
     s->s3->tmp.pkey = skey;
     if (ssl_derive(s, skey, ckey, 1) == 0) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR);
+        /* SSLfatal() already called */
         return EXT_RETURN_FAIL;
     }
 #endif
@@ -1231,7 +1291,7 @@ EXT_RETURN tls_construct_stoc_key_share(SSL *s, WPACKET *pkt,
 
 EXT_RETURN tls_construct_stoc_cryptopro_bug(SSL *s, WPACKET *pkt,
                                             unsigned int context, X509 *x,
-                                            size_t chainidx, int *al)
+                                            size_t chainidx)
 {
     const unsigned char cryptopro_ext[36] = {
         0xfd, 0xe8,         /* 65000 */
@@ -1248,7 +1308,8 @@ EXT_RETURN tls_construct_stoc_cryptopro_bug(SSL *s, WPACKET *pkt,
         return EXT_RETURN_NOT_SENT;
 
     if (!WPACKET_memcpy(pkt, cryptopro_ext, sizeof(cryptopro_ext))) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_STOC_CRYPTOPRO_BUG, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_STOC_CRYPTOPRO_BUG, ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -1257,7 +1318,7 @@ EXT_RETURN tls_construct_stoc_cryptopro_bug(SSL *s, WPACKET *pkt,
 
 EXT_RETURN tls_construct_stoc_early_data(SSL *s, WPACKET *pkt,
                                          unsigned int context, X509 *x,
-                                         size_t chainidx, int *al)
+                                         size_t chainidx)
 {
     if (context == SSL_EXT_TLS1_3_NEW_SESSION_TICKET) {
         if (s->max_early_data == 0)
@@ -1267,7 +1328,8 @@ EXT_RETURN tls_construct_stoc_early_data(SSL *s, WPACKET *pkt,
                 || !WPACKET_start_sub_packet_u16(pkt)
                 || !WPACKET_put_bytes_u32(pkt, s->max_early_data)
                 || !WPACKET_close(pkt)) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA, ERR_R_INTERNAL_ERROR);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA, ERR_R_INTERNAL_ERROR);
             return EXT_RETURN_FAIL;
         }
 
@@ -1280,7 +1342,8 @@ EXT_RETURN tls_construct_stoc_early_data(SSL *s, WPACKET *pkt,
     if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data)
             || !WPACKET_start_sub_packet_u16(pkt)
             || !WPACKET_close(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA,
+                 ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
@@ -1288,7 +1351,7 @@ EXT_RETURN tls_construct_stoc_early_data(SSL *s, WPACKET *pkt,
 }
 
 EXT_RETURN tls_construct_stoc_psk(SSL *s, WPACKET *pkt, unsigned int context,
-                                  X509 *x, size_t chainidx, int *al)
+                                  X509 *x, size_t chainidx)
 {
     if (!s->hit)
         return EXT_RETURN_NOT_SENT;
@@ -1297,7 +1360,8 @@ EXT_RETURN tls_construct_stoc_psk(SSL *s, WPACKET *pkt, unsigned int context,
             || !WPACKET_start_sub_packet_u16(pkt)
             || !WPACKET_put_bytes_u16(pkt, s->session->ext.tick_identity)
             || !WPACKET_close(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_STOC_PSK, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_STOC_PSK, ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
diff --git a/ssl/statem/statem.c b/ssl/statem/statem.c
index 0f34522..0cacc4a 100644
--- a/ssl/statem/statem.c
+++ b/ssl/statem/statem.c
@@ -11,6 +11,7 @@
 #include <openssl/rand.h>
 #include "../ssl_locl.h"
 #include "statem_locl.h"
+#include <assert.h>
 
 /*
  * This file implements the SSL/TLS/DTLS state machines.
@@ -111,15 +112,35 @@ void ossl_statem_set_renegotiate(SSL *s)
 }
 
 /*
- * Put the state machine into an error state. This is a permanent error for
- * the current connection.
+ * Put the state machine into an error state and send an alert if appropriate.
+ * This is a permanent error for the current connection.
  */
-void ossl_statem_set_error(SSL *s)
+void ossl_statem_fatal(SSL *s, int al, int func, int reason, const char *file,
+                       int line)
 {
+    /* We shouldn't call SSLfatal() twice. Once is enough */
+    assert(s->statem.state != MSG_FLOW_ERROR);
+    s->statem.in_init = 1;
     s->statem.state = MSG_FLOW_ERROR;
+    ERR_put_error(ERR_LIB_SSL, func, reason, file, line);
+    if (al != SSL_AD_NO_ALERT)
+        ssl3_send_alert(s, SSL3_AL_FATAL, al);
 }
 
 /*
+ * This macro should only be called if we are already expecting to be in
+ * a fatal error state. We verify that we are, and set it if not (this would
+ * indicate a bug).
+ */
+#define check_fatal(s, f) \
+    do { \
+        if (!ossl_assert((s)->statem.in_init \
+                         || (s)->statem.state != MSG_FLOW_ERROR)) \
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, (f), \
+                     SSL_R_MISSING_FATAL); \
+    } while (0)
+
+/*
  * Discover whether the current connection is in the error state.
  *
  * Valid return values are:
@@ -316,29 +337,42 @@ static int state_machine(SSL *s, int server)
         if (cb != NULL)
             cb(s, SSL_CB_HANDSHAKE_START, 1);
 
+        /*
+         * Fatal errors in this block don't send an alert because we have
+         * failed to even initialise properly. Sending an alert is probably
+         * doomed to failure.
+         */
+
         if (SSL_IS_DTLS(s)) {
             if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00) &&
                 (server || (s->version & 0xff00) != (DTLS1_BAD_VER & 0xff00))) {
-                SSLerr(SSL_F_STATE_MACHINE, ERR_R_INTERNAL_ERROR);
+                SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
+                         ERR_R_INTERNAL_ERROR);
                 goto end;
             }
         } else {
             if ((s->version >> 8) != SSL3_VERSION_MAJOR) {
-                SSLerr(SSL_F_STATE_MACHINE, ERR_R_INTERNAL_ERROR);
+                SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
+                         ERR_R_INTERNAL_ERROR);
                 goto end;
             }
         }
 
         if (!ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL)) {
-            SSLerr(SSL_F_STATE_MACHINE, SSL_R_VERSION_TOO_LOW);
+            SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
+                     ERR_R_INTERNAL_ERROR);
             goto end;
         }
 
         if (s->init_buf == NULL) {
             if ((buf = BUF_MEM_new()) == NULL) {
+                SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
+                         ERR_R_INTERNAL_ERROR);
                 goto end;
             }
             if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
+                SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
+                         ERR_R_INTERNAL_ERROR);
                 goto end;
             }
             s->init_buf = buf;
@@ -346,6 +380,8 @@ static int state_machine(SSL *s, int server)
         }
 
         if (!ssl3_setup_buffers(s)) {
+            SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
+                     ERR_R_INTERNAL_ERROR);
             goto end;
         }
         s->init_num = 0;
@@ -363,13 +399,15 @@ static int state_machine(SSL *s, int server)
         if (!SSL_IS_DTLS(s) || !BIO_dgram_is_sctp(SSL_get_wbio(s)))
 #endif
             if (!ssl_init_wbio_buffer(s)) {
+                SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
+                         ERR_R_INTERNAL_ERROR);
                 goto end;
             }
 
         if ((SSL_in_before(s))
                 || s->renegotiate) {
             if (!tls_setup_handshake(s)) {
-                ossl_statem_set_error(s);
+                /* SSLfatal() already called */
                 goto end;
             }
 
@@ -404,7 +442,8 @@ static int state_machine(SSL *s, int server)
             }
         } else {
             /* Error */
-            ossl_statem_set_error(s);
+            check_fatal(s, SSL_F_STATE_MACHINE);
+            SSLerr(SSL_F_STATE_MACHINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
             goto end;
         }
     }
@@ -547,13 +586,13 @@ static SUB_STATE_RETURN read_state_machine(SSL *s)
              * to that state if so
              */
             if (!transition(s, mt)) {
-                ossl_statem_set_error(s);
+                check_fatal(s, SSL_F_READ_STATE_MACHINE);
                 return SUB_STATE_ERROR;
             }
 
             if (s->s3->tmp.message_size > max_message_size(s)) {
-                ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
-                SSLerr(SSL_F_READ_STATE_MACHINE, SSL_R_EXCESSIVE_MESSAGE_SIZE);
+                SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_READ_STATE_MACHINE,
+                         SSL_R_EXCESSIVE_MESSAGE_SIZE);
                 return SUB_STATE_ERROR;
             }
 
@@ -562,8 +601,8 @@ static SUB_STATE_RETURN read_state_machine(SSL *s)
                     && s->s3->tmp.message_size > 0
                     && !grow_init_buf(s, s->s3->tmp.message_size
                                          + SSL3_HM_HEADER_LENGTH)) {
-                ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-                SSLerr(SSL_F_READ_STATE_MACHINE, ERR_R_BUF_LIB);
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE,
+                         ERR_R_BUF_LIB);
                 return SUB_STATE_ERROR;
             }
 
@@ -582,8 +621,8 @@ static SUB_STATE_RETURN read_state_machine(SSL *s)
 
             s->first_packet = 0;
             if (!PACKET_buf_init(&pkt, s->init_msg, len)) {
-                ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-                SSLerr(SSL_F_READ_STATE_MACHINE, ERR_R_INTERNAL_ERROR);
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE,
+                         ERR_R_INTERNAL_ERROR);
                 return SUB_STATE_ERROR;
             }
             ret = process_message(s, &pkt);
@@ -593,6 +632,7 @@ static SUB_STATE_RETURN read_state_machine(SSL *s)
 
             switch (ret) {
             case MSG_PROCESS_ERROR:
+                check_fatal(s, SSL_F_READ_STATE_MACHINE);
                 return SUB_STATE_ERROR;
 
             case MSG_PROCESS_FINISHED_READING:
@@ -616,6 +656,8 @@ static SUB_STATE_RETURN read_state_machine(SSL *s)
             st->read_state_work = post_process_message(s, st->read_state_work);
             switch (st->read_state_work) {
             case WORK_ERROR:
+                check_fatal(s, SSL_F_READ_STATE_MACHINE);
+                /* Fall through */
             case WORK_MORE_A:
             case WORK_MORE_B:
             case WORK_MORE_C:
@@ -635,9 +677,8 @@ static SUB_STATE_RETURN read_state_machine(SSL *s)
 
         default:
             /* Shouldn't happen */
-            ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-            SSLerr(SSL_F_READ_STATE_MACHINE, ERR_R_INTERNAL_ERROR);
-            ossl_statem_set_error(s);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE,
+                     ERR_R_INTERNAL_ERROR);
             return SUB_STATE_ERROR;
         }
     }
@@ -752,6 +793,7 @@ static SUB_STATE_RETURN write_state_machine(SSL *s)
                 break;
 
             case WRITE_TRAN_ERROR:
+                check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
                 return SUB_STATE_ERROR;
             }
             break;
@@ -759,6 +801,8 @@ static SUB_STATE_RETURN write_state_machine(SSL *s)
         case WRITE_STATE_PRE_WORK:
             switch (st->write_state_work = pre_work(s, st->write_state_work)) {
             case WORK_ERROR:
+                check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
+                /* Fall through */
             case WORK_MORE_A:
             case WORK_MORE_B:
             case WORK_MORE_C:
@@ -772,7 +816,7 @@ static SUB_STATE_RETURN write_state_machine(SSL *s)
                 return SUB_STATE_END_HANDSHAKE;
             }
             if (!get_construct_message_f(s, &pkt, &confunc, &mt)) {
-                ossl_statem_set_error(s);
+                /* SSLfatal() already called */
                 return SUB_STATE_ERROR;
             }
             if (mt == SSL3_MT_DUMMY) {
@@ -782,12 +826,22 @@ static SUB_STATE_RETURN write_state_machine(SSL *s)
                 break;
             }
             if (!WPACKET_init(&pkt, s->init_buf)
-                    || !ssl_set_handshake_header(s, &pkt, mt)
-                    || (confunc != NULL && !confunc(s, &pkt))
-                    || !ssl_close_construct_packet(s, &pkt, mt)
+                    || !ssl_set_handshake_header(s, &pkt, mt)) {
+                WPACKET_cleanup(&pkt);
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE,
+                         ERR_R_INTERNAL_ERROR);
+                return SUB_STATE_ERROR;
+            }
+            if (confunc != NULL && !confunc(s, &pkt)) {
+                WPACKET_cleanup(&pkt);
+                check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
+                return SUB_STATE_ERROR;
+            }
+            if (!ssl_close_construct_packet(s, &pkt, mt)
                     || !WPACKET_finish(&pkt)) {
                 WPACKET_cleanup(&pkt);
-                ossl_statem_set_error(s);
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE,
+                         ERR_R_INTERNAL_ERROR);
                 return SUB_STATE_ERROR;
             }
 
@@ -808,6 +862,8 @@ static SUB_STATE_RETURN write_state_machine(SSL *s)
         case WRITE_STATE_POST_WORK:
             switch (st->write_state_work = post_work(s, st->write_state_work)) {
             case WORK_ERROR:
+                check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
+                /* Fall through */
             case WORK_MORE_A:
             case WORK_MORE_B:
             case WORK_MORE_C:
@@ -823,6 +879,8 @@ static SUB_STATE_RETURN write_state_machine(SSL *s)
             break;
 
         default:
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE,
+                     ERR_R_INTERNAL_ERROR);
             return SUB_STATE_ERROR;
         }
     }
diff --git a/ssl/statem/statem.h b/ssl/statem/statem.h
index 98c8291..83bebe7 100644
--- a/ssl/statem/statem.h
+++ b/ssl/statem/statem.h
@@ -114,7 +114,16 @@ __owur int ossl_statem_accept(SSL *s);
 __owur int ossl_statem_connect(SSL *s);
 void ossl_statem_clear(SSL *s);
 void ossl_statem_set_renegotiate(SSL *s);
-void ossl_statem_set_error(SSL *s);
+void ossl_statem_fatal(SSL *s, int al, int func, int reason, const char *file,
+                       int line);
+# define SSL_AD_NO_ALERT    -1
+# ifndef OPENSSL_NO_ERR
+#  define SSLfatal(s, al, f, r)  ossl_statem_fatal((s), (al), (f), (r), \
+                                                   OPENSSL_FILE, OPENSSL_LINE)
+# else
+#  define SSLfatal(s, al, f, r)  ossl_statem_fatal((s), (al), (f), (r), NULL, 0)
+# endif
+
 int ossl_statem_in_error(const SSL *s);
 void ossl_statem_set_in_init(SSL *s, int init);
 int ossl_statem_get_in_handshake(SSL *s);
diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c
index 0a68264..e1dcf37 100644
--- a/ssl/statem/statem_clnt.c
+++ b/ssl/statem/statem_clnt.c
@@ -363,8 +363,9 @@ int ossl_statem_client_read_transition(SSL *s, int mt)
 
  err:
     /* No valid transition found */
-    ssl3_send_alert(s, SSL3_AL_FATAL, SSL3_AD_UNEXPECTED_MESSAGE);
-    SSLerr(SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION, SSL_R_UNEXPECTED_MESSAGE);
+    SSLfatal(s, SSL3_AD_UNEXPECTED_MESSAGE,
+             SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION,
+             SSL_R_UNEXPECTED_MESSAGE);
     return 0;
 }
 
@@ -385,6 +386,9 @@ static WRITE_TRAN ossl_statem_client13_write_transition(SSL *s)
     switch (st->hand_state) {
     default:
         /* Shouldn't happen */
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_OSSL_STATEM_CLIENT13_WRITE_TRANSITION,
+                 ERR_R_INTERNAL_ERROR);
         return WRITE_TRAN_ERROR;
 
     case TLS_ST_CW_CLNT_HELLO:
@@ -465,6 +469,9 @@ WRITE_TRAN ossl_statem_client_write_transition(SSL *s)
     switch (st->hand_state) {
     default:
         /* Shouldn't happen */
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_OSSL_STATEM_CLIENT_WRITE_TRANSITION,
+                 ERR_R_INTERNAL_ERROR);
         return WRITE_TRAN_ERROR;
 
     case TLS_ST_OK:
@@ -585,7 +592,7 @@ WRITE_TRAN ossl_statem_client_write_transition(SSL *s)
          */
         if (ssl3_renegotiate_check(s, 1)) {
             if (!tls_setup_handshake(s)) {
-                ossl_statem_set_error(s);
+                /* SSLfatal() already called */
                 return WRITE_TRAN_ERROR;
             }
             st->hand_state = TLS_ST_CW_CLNT_HELLO;
@@ -614,7 +621,7 @@ WORK_STATE ossl_statem_client_pre_work(SSL *s, WORK_STATE wst)
         if (SSL_IS_DTLS(s)) {
             /* every DTLS ClientHello resets Finished MAC */
             if (!ssl3_init_finished_mac(s)) {
-                ossl_statem_set_error(s);
+                /* SSLfatal() already called */
                 return WORK_ERROR;
             }
         }
@@ -630,8 +637,10 @@ WORK_STATE ossl_statem_client_pre_work(SSL *s, WORK_STATE wst)
                 st->use_timer = 0;
             }
 #ifndef OPENSSL_NO_SCTP
-            if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
+            if (BIO_dgram_is_sctp(SSL_get_wbio(s))) {
+                /* Calls SSLfatal() as required */
                 return dtls_wait_for_dry(s);
+            }
 #endif
         }
         break;
@@ -649,6 +658,7 @@ WORK_STATE ossl_statem_client_pre_work(SSL *s, WORK_STATE wst)
 
     case TLS_ST_EARLY_DATA:
     case TLS_ST_OK:
+        /* Calls SSLfatal() as required */
         return tls_finish_handshake(s, wst, 1);
     }
 
@@ -687,8 +697,10 @@ WORK_STATE ossl_statem_client_post_work(SSL *s, WORK_STATE wst)
              * we call tls13_change_cipher_state() directly.
              */
             if (!tls13_change_cipher_state(s,
-                        SSL3_CC_EARLY | SSL3_CHANGE_CIPHER_CLIENT_WRITE))
+                        SSL3_CC_EARLY | SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
+                /* SSLfatal() already called */
                 return WORK_ERROR;
+            }
         }
         break;
 
@@ -702,8 +714,10 @@ WORK_STATE ossl_statem_client_post_work(SSL *s, WORK_STATE wst)
         break;
 
     case TLS_ST_CW_KEY_EXCH:
-        if (tls_client_key_exchange_post_work(s) == 0)
+        if (tls_client_key_exchange_post_work(s) == 0) {
+            /* SSLfatal() already called */
             return WORK_ERROR;
+        }
         break;
 
     case TLS_ST_CW_CHANGE:
@@ -716,12 +730,16 @@ WORK_STATE ossl_statem_client_post_work(SSL *s, WORK_STATE wst)
         else
             s->session->compress_meth = s->s3->tmp.new_compression->id;
 #endif
-        if (!s->method->ssl3_enc->setup_key_block(s))
+        if (!s->method->ssl3_enc->setup_key_block(s)) {
+            /* SSLfatal() already called */
             return WORK_ERROR;
+        }
 
         if (!s->method->ssl3_enc->change_cipher_state(s,
-                                                      SSL3_CHANGE_CIPHER_CLIENT_WRITE))
+                                          SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
+            /* SSLfatal() already called */
             return WORK_ERROR;
+        }
 
         if (SSL_IS_DTLS(s)) {
 #ifndef OPENSSL_NO_SCTP
@@ -755,16 +773,20 @@ WORK_STATE ossl_statem_client_post_work(SSL *s, WORK_STATE wst)
 
         if (SSL_IS_TLS13(s)) {
             if (!s->method->ssl3_enc->change_cipher_state(s,
-                        SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_CLIENT_WRITE))
-            return WORK_ERROR;
+                        SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
+                /* SSLfatal() already called */
+                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))
+        if (!tls13_update_key(s, 1)) {
+            /* SSLfatal() already called */
             return WORK_ERROR;
+        }
         break;
     }
 
@@ -787,6 +809,9 @@ int ossl_statem_client_construct_message(SSL *s, WPACKET *pkt,
     switch (st->hand_state) {
     default:
         /* Shouldn't happen */
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_OSSL_STATEM_CLIENT_CONSTRUCT_MESSAGE,
+                 SSL_R_BAD_HANDSHAKE_STATE);
         return 0;
 
     case TLS_ST_CW_CHANGE:
@@ -921,6 +946,9 @@ MSG_PROCESS_RETURN ossl_statem_client_process_message(SSL *s, PACKET *pkt)
     switch (st->hand_state) {
     default:
         /* Shouldn't happen */
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_OSSL_STATEM_CLIENT_PROCESS_MESSAGE,
+                 ERR_R_INTERNAL_ERROR);
         return MSG_PROCESS_ERROR;
 
     case TLS_ST_CR_SRVR_HELLO:
@@ -981,6 +1009,9 @@ WORK_STATE ossl_statem_client_post_process_message(SSL *s, WORK_STATE wst)
     switch (st->hand_state) {
     default:
         /* Shouldn't happen */
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_OSSL_STATEM_CLIENT_POST_PROCESS_MESSAGE,
+                 ERR_R_INTERNAL_ERROR);
         return WORK_ERROR;
 
     case TLS_ST_CR_CERT_REQ:
@@ -993,7 +1024,6 @@ int tls_construct_client_hello(SSL *s, WPACKET *pkt)
     unsigned char *p;
     size_t sess_id_len;
     int i, protverr;
-    int al = SSL_AD_HANDSHAKE_FAILURE;
 #ifndef OPENSSL_NO_COMP
     SSL_COMP *comp;
 #endif
@@ -1001,22 +1031,26 @@ int tls_construct_client_hello(SSL *s, WPACKET *pkt)
 
     if (!WPACKET_set_max_size(pkt, SSL3_RT_MAX_PLAIN_LENGTH)) {
         /* Should not happen */
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
     /* Work out what SSL/TLS/DTLS version to use */
     protverr = ssl_set_client_hello_version(s);
     if (protverr != 0) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, protverr);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
+                 protverr);
         return 0;
     }
 
     if (sess == NULL
             || !ssl_version_supported(s, sess->ssl_version)
             || !SSL_SESSION_is_resumable(sess)) {
-        if (!ssl_get_new_session(s, 0))
+        if (!ssl_get_new_session(s, 0)) {
+            /* SSLfatal() already called */
             return 0;
+        }
     }
     /* else use the pre-loaded session */
 
@@ -1040,8 +1074,11 @@ int tls_construct_client_hello(SSL *s, WPACKET *pkt)
     }
 
     if (i && ssl_fill_hello_random(s, 0, p, sizeof(s->s3->client_random),
-                                   DOWNGRADE_NONE) <= 0)
+                                   DOWNGRADE_NONE) <= 0) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
+    }
 
     /*-
      * version indicates the negotiated version: for example from
@@ -1078,7 +1115,8 @@ int tls_construct_client_hello(SSL *s, WPACKET *pkt)
      */
     if (!WPACKET_put_bytes_u16(pkt, s->client_version)
             || !WPACKET_memcpy(pkt, s->s3->client_random, SSL3_RANDOM_SIZE)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
@@ -1092,7 +1130,8 @@ int tls_construct_client_hello(SSL *s, WPACKET *pkt)
             || (sess_id_len != 0 && !WPACKET_memcpy(pkt, s->session->session_id,
                                                     sess_id_len))
             || !WPACKET_close(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
@@ -1101,27 +1140,33 @@ int tls_construct_client_hello(SSL *s, WPACKET *pkt)
         if (s->d1->cookie_len > sizeof(s->d1->cookie)
                 || !WPACKET_sub_memcpy_u8(pkt, s->d1->cookie,
                                           s->d1->cookie_len)) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
+                     ERR_R_INTERNAL_ERROR);
             return 0;
         }
     }
 
     /* Ciphers supported */
     if (!WPACKET_start_sub_packet_u16(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
     }
-    /* ssl_cipher_list_to_bytes() raises SSLerr if appropriate */
-    if (!ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), pkt))
+
+    if (!ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), pkt)) {
+        /* SSLfatal() already called */
         return 0;
+    }
     if (!WPACKET_close(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
     /* COMPRESSION */
     if (!WPACKET_start_sub_packet_u8(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
     }
 #ifndef OPENSSL_NO_COMP
@@ -1132,7 +1177,9 @@ int tls_construct_client_hello(SSL *s, WPACKET *pkt)
         for (i = 0; i < compnum; i++) {
             comp = sk_SSL_COMP_value(s->ctx->comp_methods, i);
             if (!WPACKET_put_bytes_u8(pkt, comp->id)) {
-                SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
+                         ERR_R_INTERNAL_ERROR);
                 return 0;
             }
         }
@@ -1140,13 +1187,14 @@ int tls_construct_client_hello(SSL *s, WPACKET *pkt)
 #endif
     /* Add the NULL method */
     if (!WPACKET_put_bytes_u8(pkt, 0) || !WPACKET_close(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
     /* TLS extensions */
-    if (!tls_construct_extensions(s, pkt, SSL_EXT_CLIENT_HELLO, NULL, 0, &al)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+    if (!tls_construct_extensions(s, pkt, SSL_EXT_CLIENT_HELLO, NULL, 0)) {
+        /* SSLfatal() already called */
         return 0;
     }
 
@@ -1155,36 +1203,31 @@ int tls_construct_client_hello(SSL *s, WPACKET *pkt)
 
 MSG_PROCESS_RETURN dtls_process_hello_verify(SSL *s, PACKET *pkt)
 {
-    int al;
     size_t cookie_len;
     PACKET cookiepkt;
 
     if (!PACKET_forward(pkt, 2)
         || !PACKET_get_length_prefixed_1(pkt, &cookiepkt)) {
-        al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_DTLS_PROCESS_HELLO_VERIFY, SSL_R_LENGTH_MISMATCH);
-        goto f_err;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_DTLS_PROCESS_HELLO_VERIFY,
+                 SSL_R_LENGTH_MISMATCH);
+        return MSG_PROCESS_ERROR;
     }
 
     cookie_len = PACKET_remaining(&cookiepkt);
     if (cookie_len > sizeof(s->d1->cookie)) {
-        al = SSL_AD_ILLEGAL_PARAMETER;
-        SSLerr(SSL_F_DTLS_PROCESS_HELLO_VERIFY, SSL_R_LENGTH_TOO_LONG);
-        goto f_err;
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_DTLS_PROCESS_HELLO_VERIFY,
+                 SSL_R_LENGTH_TOO_LONG);
+        return MSG_PROCESS_ERROR;
     }
 
     if (!PACKET_copy_bytes(&cookiepkt, s->d1->cookie, cookie_len)) {
-        al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_DTLS_PROCESS_HELLO_VERIFY, SSL_R_LENGTH_MISMATCH);
-        goto f_err;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_DTLS_PROCESS_HELLO_VERIFY,
+                 SSL_R_LENGTH_MISMATCH);
+        return MSG_PROCESS_ERROR;
     }
     s->d1->cookie_len = cookie_len;
 
     return MSG_PROCESS_FINISHED_READING;
- f_err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, al);
-    ossl_statem_set_error(s);
-    return MSG_PROCESS_ERROR;
 }
 
 static int set_client_ciphersuite(SSL *s, const unsigned char *cipherchars)
@@ -1196,7 +1239,8 @@ static int set_client_ciphersuite(SSL *s, const unsigned char *cipherchars)
     c = ssl_get_cipher_by_char(s, cipherchars, 0);
     if (c == NULL) {
         /* unknown cipher */
-        SSLerr(SSL_F_SET_CLIENT_CIPHERSUITE, SSL_R_UNKNOWN_CIPHER_RETURNED);
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE,
+                 SSL_R_UNKNOWN_CIPHER_RETURNED);
         return 0;
     }
     /*
@@ -1204,7 +1248,8 @@ static int set_client_ciphersuite(SSL *s, const unsigned char *cipherchars)
      * or it's not allowed for the selected protocol. So we return an error.
      */
     if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_CHECK, 1)) {
-        SSLerr(SSL_F_SET_CLIENT_CIPHERSUITE, SSL_R_WRONG_CIPHER_RETURNED);
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE,
+                 SSL_R_WRONG_CIPHER_RETURNED);
         return 0;
     }
 
@@ -1212,14 +1257,16 @@ static int set_client_ciphersuite(SSL *s, const unsigned char *cipherchars)
     i = sk_SSL_CIPHER_find(sk, c);
     if (i < 0) {
         /* we did not say we would use this cipher */
-        SSLerr(SSL_F_SET_CLIENT_CIPHERSUITE, SSL_R_WRONG_CIPHER_RETURNED);
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE,
+                 SSL_R_WRONG_CIPHER_RETURNED);
         return 0;
     }
 
     if (SSL_IS_TLS13(s) && s->s3->tmp.new_cipher != NULL
             && s->s3->tmp.new_cipher->id != c->id) {
         /* ServerHello selected a different ciphersuite to that in the HRR */
-        SSLerr(SSL_F_SET_CLIENT_CIPHERSUITE, SSL_R_WRONG_CIPHER_RETURNED);
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE,
+                 SSL_R_WRONG_CIPHER_RETURNED);
         return 0;
     }
 
@@ -1238,8 +1285,9 @@ static int set_client_ciphersuite(SSL *s, const unsigned char *cipherchars)
              */
             if (ssl_md(c->algorithm2)
                     != ssl_md(s->session->cipher->algorithm2)) {
-                SSLerr(SSL_F_SET_CLIENT_CIPHERSUITE,
-                       SSL_R_CIPHERSUITE_DIGEST_HAS_CHANGED);
+                SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+                         SSL_F_SET_CLIENT_CIPHERSUITE,
+                         SSL_R_CIPHERSUITE_DIGEST_HAS_CHANGED);
                 return 0;
             }
         } else {
@@ -1247,8 +1295,8 @@ static int set_client_ciphersuite(SSL *s, const unsigned char *cipherchars)
              * Prior to TLSv1.3 resuming a session always meant using the same
              * ciphersuite.
              */
-            SSLerr(SSL_F_SET_CLIENT_CIPHERSUITE,
-                   SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED);
+            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE,
+                     SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED);
             return 0;
         }
     }
@@ -1262,27 +1310,26 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
     PACKET session_id, extpkt;
     size_t session_id_len;
     const unsigned char *cipherchars;
-    int al = SSL_AD_INTERNAL_ERROR;
     unsigned int compression;
     unsigned int sversion;
     unsigned int context;
-    int protverr, discard;
+    int discard;
     RAW_EXTENSION *extensions = NULL;
 #ifndef OPENSSL_NO_COMP
     SSL_COMP *comp;
 #endif
 
     if (!PACKET_get_net_2(pkt, &sversion)) {
-        al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
-        goto f_err;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
+                 SSL_R_LENGTH_MISMATCH);
+        goto err;
     }
 
     /* load the server random */
     if (!PACKET_copy_bytes(pkt, s->s3->server_random, SSL3_RANDOM_SIZE)) {
-        al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
-        goto f_err;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
+                 SSL_R_LENGTH_MISMATCH);
+        goto err;
     }
 
     /*
@@ -1290,10 +1337,9 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
      * Must be done after reading the random data so we can check for the
      * TLSv1.3 downgrade sentinels
      */
-    protverr = ssl_choose_client_version(s, sversion, 1, &al);
-    if (protverr != 0) {
-        SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, protverr);
-        goto f_err;
+    if (!ssl_choose_client_version(s, sversion, 1)) {
+        /* SSLfatal() already called */
+        goto err;
     }
 
     /*
@@ -1301,25 +1347,25 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
      * message must be on a record boundary.
      */
     if (SSL_IS_TLS13(s) && RECORD_LAYER_processed_read_pending(&s->rlayer)) {
-        al = SSL_AD_UNEXPECTED_MESSAGE;
-        SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_NOT_ON_RECORD_BOUNDARY);
-        goto f_err;
+        SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_SERVER_HELLO,
+                 SSL_R_NOT_ON_RECORD_BOUNDARY);
+        goto err;
     }
 
     /* Get the session-id. */
     if (!SSL_IS_TLS13(s)) {
         if (!PACKET_get_length_prefixed_1(pkt, &session_id)) {
-            al = SSL_AD_DECODE_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
-            goto f_err;
+            SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
+                     SSL_R_LENGTH_MISMATCH);
+            goto err;
         }
         session_id_len = PACKET_remaining(&session_id);
         if (session_id_len > sizeof s->session->session_id
             || session_id_len > SSL3_SESSION_ID_SIZE) {
-            al = SSL_AD_ILLEGAL_PARAMETER;
-            SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO,
-                   SSL_R_SSL3_SESSION_ID_TOO_LONG);
-            goto f_err;
+            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+                     SSL_F_TLS_PROCESS_SERVER_HELLO,
+                     SSL_R_SSL3_SESSION_ID_TOO_LONG);
+            goto err;
         }
     } else {
         PACKET_null_init(&session_id);
@@ -1327,16 +1373,16 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
     }
 
     if (!PACKET_get_bytes(pkt, &cipherchars, TLS_CIPHER_LEN)) {
-        SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
-        al = SSL_AD_DECODE_ERROR;
-        goto f_err;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
+                 SSL_R_LENGTH_MISMATCH);
+        goto err;
     }
 
     if (!SSL_IS_TLS13(s)) {
         if (!PACKET_get_1(pkt, &compression)) {
-            SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
-            al = SSL_AD_DECODE_ERROR;
-            goto f_err;
+            SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
+                     SSL_R_LENGTH_MISMATCH);
+            goto err;
         }
     } else {
         compression = 0;
@@ -1347,15 +1393,17 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
         PACKET_null_init(&extpkt);
     } else if (!PACKET_as_length_prefixed_2(pkt, &extpkt)
                || PACKET_remaining(pkt) != 0) {
-        al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_BAD_LENGTH);
-        goto f_err;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
+                 SSL_R_BAD_LENGTH);
+        goto err;
     }
 
     context = SSL_IS_TLS13(s) ? SSL_EXT_TLS1_3_SERVER_HELLO
                               : SSL_EXT_TLS1_2_SERVER_HELLO;
-    if (!tls_collect_extensions(s, &extpkt, context, &extensions, &al, NULL, 1))
-        goto f_err;
+    if (!tls_collect_extensions(s, &extpkt, context, &extensions, NULL, 1)) {
+        /* SSLfatal() already called */
+        goto err;
+    }
 
     s->hit = 0;
 
@@ -1363,8 +1411,10 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
         /* This will set s->hit if we are resuming */
         if (!tls_parse_extension(s, TLSEXT_IDX_psk,
                                  SSL_EXT_TLS1_3_SERVER_HELLO,
-                                 extensions, NULL, 0, &al))
-            goto f_err;
+                                 extensions, NULL, 0l)) {
+            /* SSLfatal() already called */
+            goto err;
+        }
     } else {
         /*
          * Check if we can resume the session based on external pre-shared
@@ -1396,9 +1446,9 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
                 s->session->cipher = pref_cipher ?
                     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;
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_TLS_PROCESS_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
+                goto err;
             }
         }
 
@@ -1413,10 +1463,10 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
         if (s->sid_ctx_length != s->session->sid_ctx_length
                 || memcmp(s->session->sid_ctx, s->sid_ctx, s->sid_ctx_length)) {
             /* actually a client application bug */
-            al = SSL_AD_ILLEGAL_PARAMETER;
-            SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO,
-                   SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
-            goto f_err;
+            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+                     SSL_F_TLS_PROCESS_SERVER_HELLO,
+                     SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
+            goto err;
         }
     } else {
         /*
@@ -1433,7 +1483,8 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
             CRYPTO_atomic_add(&s->session_ctx->stats.sess_miss, 1, &discard,
                               s->session_ctx->lock);
             if (!ssl_get_new_session(s, 0)) {
-                goto f_err;
+                /* SSLfatal() already called */
+                goto err;
             }
         }
 
@@ -1447,11 +1498,9 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
 
     /* Session version and negotiated protocol version should match */
     if (s->version != s->session->ssl_version) {
-        al = SSL_AD_PROTOCOL_VERSION;
-
-        SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO,
-               SSL_R_SSL_SESSION_VERSION_MISMATCH);
-        goto f_err;
+        SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_TLS_PROCESS_SERVER_HELLO,
+                 SSL_R_SSL_SESSION_VERSION_MISMATCH);
+        goto err;
     }
     /*
      * Now that we know the version, update the check to see if it's an allowed
@@ -1461,54 +1510,54 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
     s->s3->tmp.max_ver = s->version;
 
     if (!set_client_ciphersuite(s, cipherchars)) {
-        al = SSL_AD_ILLEGAL_PARAMETER;
-        goto f_err;
+        /* SSLfatal() already called */
+        goto err;
     }
 
 #ifdef OPENSSL_NO_COMP
     if (compression != 0) {
-        al = SSL_AD_ILLEGAL_PARAMETER;
-        SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO,
-               SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
-        goto f_err;
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
+                 SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
+        goto err;
     }
     /*
      * If compression is disabled we'd better not try to resume a session
      * using compression.
      */
     if (s->session->compress_meth != 0) {
-        SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_INCONSISTENT_COMPRESSION);
-        goto f_err;
+        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PROCESS_SERVER_HELLO,
+                 SSL_R_INCONSISTENT_COMPRESSION);
+        goto err;
     }
 #else
     if (s->hit && compression != s->session->compress_meth) {
-        al = SSL_AD_ILLEGAL_PARAMETER;
-        SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO,
-               SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED);
-        goto f_err;
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
+                 SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED);
+        goto err;
     }
     if (compression == 0)
         comp = NULL;
     else if (!ssl_allow_compression(s)) {
-        al = SSL_AD_ILLEGAL_PARAMETER;
-        SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_COMPRESSION_DISABLED);
-        goto f_err;
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
+                 SSL_R_COMPRESSION_DISABLED);
+        goto err;
     } else {
         comp = ssl3_comp_find(s->ctx->comp_methods, compression);
     }
 
     if (compression != 0 && comp == NULL) {
-        al = SSL_AD_ILLEGAL_PARAMETER;
-        SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO,
-               SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
-        goto f_err;
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
+                 SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
+        goto err;
     } else {
         s->s3->tmp.new_compression = comp;
     }
 #endif
 
-    if (!tls_parse_all_extensions(s, context, extensions, NULL, 0, &al, 1))
-        goto f_err;
+    if (!tls_parse_all_extensions(s, context, extensions, NULL, 0, 1)) {
+        /* SSLfatal() already called */
+        goto err;
+    }
 
 #ifndef OPENSSL_NO_SCTP
     if (SSL_IS_DTLS(s) && s->hit) {
@@ -1525,8 +1574,11 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
         if (SSL_export_keying_material(s, sctpauthkey,
                                        sizeof(sctpauthkey),
                                        labelbuffer,
-                                       sizeof(labelbuffer), NULL, 0, 0) <= 0)
-            goto f_err;
+                                       sizeof(labelbuffer), NULL, 0, 0) <= 0) {
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
+                     ERR_R_INTERNAL_ERROR);
+            goto err;
+        }
 
         BIO_ctrl(SSL_get_wbio(s),
                  BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
@@ -1542,16 +1594,13 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
             && (!s->method->ssl3_enc->setup_key_block(s)
                 || !s->method->ssl3_enc->change_cipher_state(s,
                     SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_READ))) {
-        al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_CANNOT_CHANGE_CIPHER);
-        goto f_err;
+        /* SSLfatal() already called */
+        goto err;
     }
 
     OPENSSL_free(extensions);
     return MSG_PROCESS_CONTINUE_READING;
- f_err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, al);
-    ossl_statem_set_error(s);
+ err:
     OPENSSL_free(extensions);
     return MSG_PROCESS_ERROR;
 }
@@ -1561,20 +1610,20 @@ static MSG_PROCESS_RETURN tls_process_hello_retry_request(SSL *s, PACKET *pkt)
     unsigned int sversion;
     const unsigned char *cipherchars;
     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;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST,
+                 SSL_R_LENGTH_MISMATCH);
+        goto err;
     }
 
     /* TODO(TLS1.3): Remove the TLS1_3_VERSION_DRAFT clause before release */
     if (sversion != TLS1_3_VERSION && sversion != TLS1_3_VERSION_DRAFT) {
-        SSLerr(SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST, SSL_R_WRONG_SSL_VERSION);
-        al = SSL_AD_PROTOCOL_VERSION;
-        goto f_err;
+        SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
+                 SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST,
+                 SSL_R_WRONG_SSL_VERSION);
+        goto err;
     }
 
     s->hello_retry_request = 1;
@@ -1587,14 +1636,14 @@ static MSG_PROCESS_RETURN tls_process_hello_retry_request(SSL *s, PACKET *pkt)
     s->enc_write_ctx = NULL;
 
     if (!PACKET_get_bytes(pkt, &cipherchars, TLS_CIPHER_LEN)) {
-        SSLerr(SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST, SSL_R_LENGTH_MISMATCH);
-        al = SSL_AD_DECODE_ERROR;
-        goto f_err;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST,
+                 SSL_R_LENGTH_MISMATCH);
+        goto err;
     }
 
     if (!set_client_ciphersuite(s, cipherchars)) {
-        al = SSL_AD_ILLEGAL_PARAMETER;
-        goto f_err;
+        /* SSLfatal() already called */
+        goto err;
     }
 
     if (!PACKET_as_length_prefixed_2(pkt, &extpkt)
@@ -1602,16 +1651,18 @@ static MSG_PROCESS_RETURN tls_process_hello_retry_request(SSL *s, PACKET *pkt)
             || PACKET_remaining(&extpkt) == 0
                /* Must be no trailing data after extensions */
             || PACKET_remaining(pkt) != 0) {
-        al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST, SSL_R_BAD_LENGTH);
-        goto f_err;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST,
+                 SSL_R_BAD_LENGTH);
+        goto err;
     }
 
     if (!tls_collect_extensions(s, &extpkt, SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST,
-                                &extensions, &al, NULL, 1)
+                                &extensions, NULL, 1)
             || !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST,
-                                         extensions, NULL, 0, &al, 1))
-        goto f_err;
+                                         extensions, NULL, 0, 1)) {
+        /* SSLfatal() already called */
+        goto err;
+    }
 
     OPENSSL_free(extensions);
     extensions = NULL;
@@ -1625,10 +1676,10 @@ static MSG_PROCESS_RETURN tls_process_hello_retry_request(SSL *s, PACKET *pkt)
          * We didn't receive a cookie or a new key_share so the next
          * ClientHello will not change
          */
-        al = SSL_AD_ILLEGAL_PARAMETER;
-        SSLerr(SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST,
-               SSL_R_NO_CHANGE_FOLLOWING_HRR);
-        goto f_err;
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+                 SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST,
+                  SSL_R_NO_CHANGE_FOLLOWING_HRR);
+        goto err;
     }
 
     /*
@@ -1636,8 +1687,8 @@ static MSG_PROCESS_RETURN tls_process_hello_retry_request(SSL *s, PACKET *pkt)
      * a synthetic message_hash in place of ClientHello1.
      */
     if (!create_synthetic_message_hash(s)) {
-        al = SSL_AD_INTERNAL_ERROR;
-        goto f_err;
+        /* SSLfatal() already called */
+        goto err;
     }
 
     /*
@@ -1648,22 +1699,19 @@ static MSG_PROCESS_RETURN tls_process_hello_retry_request(SSL *s, PACKET *pkt)
      */
     if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
                                 s->init_num + SSL3_HM_HEADER_LENGTH)) {
-        al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST, ERR_R_INTERNAL_ERROR);
-        goto f_err;
+        /* SSLfatal() already called */
+        goto err;
     }
 
     return MSG_PROCESS_FINISHED_READING;
- f_err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, al);
-    ossl_statem_set_error(s);
+ err:
     OPENSSL_free(extensions);
     return MSG_PROCESS_ERROR;
 }
 
 MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
 {
-    int al, i;
+    int i;
     MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR;
     unsigned long cert_list_len, cert_len;
     X509 *x = NULL;
@@ -1675,7 +1723,8 @@ MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
     const SSL_CERT_LOOKUP *clu;
 
     if ((sk = sk_X509_new_null()) == NULL) {
-        SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, ERR_R_MALLOC_FAILURE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
+                 ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
@@ -1684,31 +1733,31 @@ MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
             || !PACKET_get_net_3(pkt, &cert_list_len)
             || PACKET_remaining(pkt) != cert_list_len
             || PACKET_remaining(pkt) == 0) {
-        al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, SSL_R_LENGTH_MISMATCH);
-        goto f_err;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
+                 SSL_R_LENGTH_MISMATCH);
+        goto err;
     }
     for (chainidx = 0; PACKET_remaining(pkt); chainidx++) {
         if (!PACKET_get_net_3(pkt, &cert_len)
             || !PACKET_get_bytes(pkt, &certbytes, cert_len)) {
-            al = SSL_AD_DECODE_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
-                   SSL_R_CERT_LENGTH_MISMATCH);
-            goto f_err;
+            SSLfatal(s, SSL_AD_DECODE_ERROR,
+                     SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
+                     SSL_R_CERT_LENGTH_MISMATCH);
+            goto err;
         }
 
         certstart = certbytes;
         x = d2i_X509(NULL, (const unsigned char **)&certbytes, cert_len);
         if (x == NULL) {
-            al = SSL_AD_BAD_CERTIFICATE;
-            SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, ERR_R_ASN1_LIB);
-            goto f_err;
+            SSLfatal(s, SSL_AD_BAD_CERTIFICATE,
+                     SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, ERR_R_ASN1_LIB);
+            goto err;
         }
         if (certbytes != (certstart + cert_len)) {
-            al = SSL_AD_DECODE_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
-                   SSL_R_CERT_LENGTH_MISMATCH);
-            goto f_err;
+            SSLfatal(s, SSL_AD_DECODE_ERROR,
+                     SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
+                     SSL_R_CERT_LENGTH_MISMATCH);
+            goto err;
         }
 
         if (SSL_IS_TLS13(s)) {
@@ -1716,24 +1765,28 @@ MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
             PACKET extensions;
 
             if (!PACKET_get_length_prefixed_2(pkt, &extensions)) {
-                al = SSL_AD_DECODE_ERROR;
-                SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, SSL_R_BAD_LENGTH);
-                goto f_err;
+                SSLfatal(s, SSL_AD_DECODE_ERROR,
+                         SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
+                         SSL_R_BAD_LENGTH);
+                goto err;
             }
             if (!tls_collect_extensions(s, &extensions,
                                         SSL_EXT_TLS1_3_CERTIFICATE, &rawexts,
-                                        &al, NULL, chainidx == 0)
+                                        NULL, chainidx == 0)
                 || !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_CERTIFICATE,
-                                             rawexts, x, chainidx, &al,
+                                             rawexts, x, chainidx,
                                              PACKET_remaining(pkt) == 0)) {
                 OPENSSL_free(rawexts);
-                goto f_err;
+                /* SSLfatal already called */
+                goto err;
             }
             OPENSSL_free(rawexts);
         }
 
         if (!sk_X509_push(sk, x)) {
-            SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, ERR_R_MALLOC_FAILURE);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
+                     ERR_R_MALLOC_FAILURE);
             goto err;
         }
         x = NULL;
@@ -1755,16 +1808,16 @@ MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
      * set. The *documented* interface remains the same.
      */
     if (s->verify_mode != SSL_VERIFY_NONE && i <= 0) {
-        al = ssl_verify_alarm_type(s->verify_result);
-        SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
-               SSL_R_CERTIFICATE_VERIFY_FAILED);
-        goto f_err;
+        SSLfatal(s, ssl_verify_alarm_type(s->verify_result),
+                 SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
+                 SSL_R_CERTIFICATE_VERIFY_FAILED);
+        goto err;
     }
     ERR_clear_error();          /* but we keep s->verify_result */
     if (i > 1) {
-        SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, i);
-        al = SSL_AD_HANDSHAKE_FAILURE;
-        goto f_err;
+        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+                 SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, i);
+        goto err;
     }
 
     s->session->peer_chain = sk;
@@ -1779,18 +1832,17 @@ MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
 
     if (pkey == NULL || EVP_PKEY_missing_parameters(pkey)) {
         x = NULL;
-        al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
-               SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS);
-        goto f_err;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
+                 SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS);
+        goto err;
     }
 
     if ((clu = ssl_cert_lookup_by_pkey(pkey, &certidx)) == NULL) {
         x = NULL;
-        al = SSL3_AL_FATAL;
-        SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
-               SSL_R_UNKNOWN_CERTIFICATE_TYPE);
-        goto f_err;
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+                 SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
+                 SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+        goto err;
     }
     /*
      * Check certificate type is consistent with ciphersuite. For TLS 1.3
@@ -1800,10 +1852,10 @@ MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
     if (!SSL_IS_TLS13(s)) {
         if ((clu->amask & s->s3->tmp.new_cipher->algorithm_auth) == 0) {
             x = NULL;
-            al = SSL_AD_ILLEGAL_PARAMETER;
-            SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
-                   SSL_R_WRONG_CERTIFICATE_TYPE);
-            goto f_err;
+            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+                     SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
+                     SSL_R_WRONG_CERTIFICATE_TYPE);
+            goto err;
         }
     }
     s->session->peer_type = certidx;
@@ -1819,25 +1871,19 @@ MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
             && !ssl_handshake_hash(s, s->cert_verify_hash,
                                    sizeof(s->cert_verify_hash),
                                    &s->cert_verify_hash_len)) {
-        al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR);
-        goto f_err;
+        /* SSLfatal() already called */;
+        goto err;
     }
 
     ret = MSG_PROCESS_CONTINUE_READING;
-    goto done;
 
- f_err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, al);
  err:
-    ossl_statem_set_error(s);
- done:
     X509_free(x);
     sk_X509_pop_free(sk, X509_free);
     return ret;
 }
 
-static int tls_process_ske_psk_preamble(SSL *s, PACKET *pkt, int *al)
+static int tls_process_ske_psk_preamble(SSL *s, PACKET *pkt)
 {
 #ifndef OPENSSL_NO_PSK
     PACKET psk_identity_hint;
@@ -1845,8 +1891,8 @@ static int tls_process_ske_psk_preamble(SSL *s, PACKET *pkt, int *al)
     /* PSK ciphersuites are preceded by an identity hint */
 
     if (!PACKET_get_length_prefixed_2(pkt, &psk_identity_hint)) {
-        *al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE, SSL_R_LENGTH_MISMATCH);
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE,
+                 SSL_R_LENGTH_MISMATCH);
         return 0;
     }
 
@@ -1857,8 +1903,9 @@ static int tls_process_ske_psk_preamble(SSL *s, PACKET *pkt, int *al)
      * identity.
      */
     if (PACKET_remaining(&psk_identity_hint) > PSK_MAX_IDENTITY_LEN) {
-        *al = SSL_AD_HANDSHAKE_FAILURE;
-        SSLerr(SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE, SSL_R_DATA_LENGTH_TOO_LONG);
+        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+                 SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE,
+                 SSL_R_DATA_LENGTH_TOO_LONG);
         return 0;
     }
 
@@ -1867,19 +1914,20 @@ static int tls_process_ske_psk_preamble(SSL *s, PACKET *pkt, int *al)
         s->session->psk_identity_hint = NULL;
     } else if (!PACKET_strndup(&psk_identity_hint,
                                &s->session->psk_identity_hint)) {
-        *al = SSL_AD_INTERNAL_ERROR;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
     return 1;
 #else
-    SSLerr(SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
-    *al = SSL_AD_INTERNAL_ERROR;
+    SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE,
+             ERR_R_INTERNAL_ERROR);
     return 0;
 #endif
 }
 
-static int tls_process_ske_srp(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
+static int tls_process_ske_srp(SSL *s, PACKET *pkt, EVP_PKEY **pkey)
 {
 #ifndef OPENSSL_NO_SRP
     PACKET prime, generator, salt, server_pub;
@@ -1888,8 +1936,8 @@ static int tls_process_ske_srp(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
         || !PACKET_get_length_prefixed_2(pkt, &generator)
         || !PACKET_get_length_prefixed_1(pkt, &salt)
         || !PACKET_get_length_prefixed_2(pkt, &server_pub)) {
-        *al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_SKE_SRP, SSL_R_LENGTH_MISMATCH);
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_SRP,
+                 SSL_R_LENGTH_MISMATCH);
         return 0;
     }
 
@@ -1906,13 +1954,13 @@ static int tls_process_ske_srp(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
         || (s->srp_ctx.B =
             BN_bin2bn(PACKET_data(&server_pub),
                       (int)PACKET_remaining(&server_pub), NULL)) == NULL) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_SKE_SRP, ERR_R_BN_LIB);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_SRP,
+                 ERR_R_BN_LIB);
         return 0;
     }
 
-    if (!srp_verify_server_param(s, al)) {
-        SSLerr(SSL_F_TLS_PROCESS_SKE_SRP, SSL_R_BAD_SRP_PARAMETERS);
+    if (!srp_verify_server_param(s)) {
+        /* SSLfatal() already called */
         return 0;
     }
 
@@ -1922,13 +1970,13 @@ static int tls_process_ske_srp(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
 
     return 1;
 #else
-    SSLerr(SSL_F_TLS_PROCESS_SKE_SRP, ERR_R_INTERNAL_ERROR);
-    *al = SSL_AD_INTERNAL_ERROR;
+    SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_SRP,
+             ERR_R_INTERNAL_ERROR);
     return 0;
 #endif
 }
 
-static int tls_process_ske_dhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
+static int tls_process_ske_dhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey)
 {
 #ifndef OPENSSL_NO_DH
     PACKET prime, generator, pub_key;
@@ -1942,8 +1990,8 @@ static int tls_process_ske_dhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
     if (!PACKET_get_length_prefixed_2(pkt, &prime)
         || !PACKET_get_length_prefixed_2(pkt, &generator)
         || !PACKET_get_length_prefixed_2(pkt, &pub_key)) {
-        *al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_SKE_DHE, SSL_R_LENGTH_MISMATCH);
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
+                 SSL_R_LENGTH_MISMATCH);
         return 0;
     }
 
@@ -1951,8 +1999,8 @@ static int tls_process_ske_dhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
     dh = DH_new();
 
     if (peer_tmp == NULL || dh == NULL) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_SKE_DHE, ERR_R_MALLOC_FAILURE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
+                 ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
@@ -1963,47 +2011,47 @@ static int tls_process_ske_dhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
     bnpub_key = BN_bin2bn(PACKET_data(&pub_key),
                           (int)PACKET_remaining(&pub_key), NULL);
     if (p == NULL || g == NULL || bnpub_key == NULL) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_SKE_DHE, ERR_R_BN_LIB);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
+                 ERR_R_BN_LIB);
         goto err;
     }
 
     /* test non-zero pubkey */
     if (BN_is_zero(bnpub_key)) {
-        *al = SSL_AD_ILLEGAL_PARAMETER;
-        SSLerr(SSL_F_TLS_PROCESS_SKE_DHE, SSL_R_BAD_DH_VALUE);
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_DHE,
+                 SSL_R_BAD_DH_VALUE);
         goto err;
     }
 
     if (!DH_set0_pqg(dh, p, NULL, g)) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_SKE_DHE, ERR_R_BN_LIB);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
+                 ERR_R_BN_LIB);
         goto err;
     }
     p = g = NULL;
 
     if (DH_check_params(dh, &check_bits) == 0 || check_bits != 0) {
-        *al = SSL_AD_ILLEGAL_PARAMETER;
-        SSLerr(SSL_F_TLS_PROCESS_SKE_DHE, SSL_R_BAD_DH_VALUE);
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_DHE,
+                 SSL_R_BAD_DH_VALUE);
         goto err;
     }
 
     if (!DH_set0_key(dh, bnpub_key, NULL)) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_SKE_DHE, ERR_R_BN_LIB);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
+                 ERR_R_BN_LIB);
         goto err;
     }
     bnpub_key = NULL;
 
     if (!ssl_security(s, SSL_SECOP_TMP_DH, DH_security_bits(dh), 0, dh)) {
-        *al = SSL_AD_HANDSHAKE_FAILURE;
-        SSLerr(SSL_F_TLS_PROCESS_SKE_DHE, SSL_R_DH_KEY_TOO_SMALL);
+        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PROCESS_SKE_DHE,
+                 SSL_R_DH_KEY_TOO_SMALL);
         goto err;
     }
 
     if (EVP_PKEY_assign_DH(peer_tmp, dh) == 0) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_SKE_DHE, ERR_R_EVP_LIB);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
+                 ERR_R_EVP_LIB);
         goto err;
     }
 
@@ -2028,13 +2076,13 @@ static int tls_process_ske_dhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
 
     return 0;
 #else
-    SSLerr(SSL_F_TLS_PROCESS_SKE_DHE, ERR_R_INTERNAL_ERROR);
-    *al = SSL_AD_INTERNAL_ERROR;
+    SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
+             ERR_R_INTERNAL_ERROR);
     return 0;
 #endif
 }
 
-static int tls_process_ske_ecdhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
+static int tls_process_ske_ecdhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey)
 {
 #ifndef OPENSSL_NO_EC
     PACKET encoded_pt;
@@ -2046,8 +2094,8 @@ static int tls_process_ske_ecdhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
      * ECParameters in this case is just three bytes.
      */
     if (!PACKET_get_1(pkt, &curve_type) || !PACKET_get_net_2(pkt, &curve_id)) {
-        *al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_SKE_ECDHE, SSL_R_LENGTH_TOO_SHORT);
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE,
+                 SSL_R_LENGTH_TOO_SHORT);
         return 0;
     }
     /*
@@ -2055,29 +2103,28 @@ static int tls_process_ske_ecdhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
      * server has sent an invalid curve.
      */
     if (curve_type != NAMED_CURVE_TYPE || !tls1_check_group_id(s, curve_id)) {
-        *al = SSL_AD_ILLEGAL_PARAMETER;
-        SSLerr(SSL_F_TLS_PROCESS_SKE_ECDHE, SSL_R_WRONG_CURVE);
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_ECDHE,
+                 SSL_R_WRONG_CURVE);
         return 0;
     }
 
     if ((s->s3->peer_tmp = ssl_generate_param_group(curve_id)) == NULL) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_SKE_ECDHE,
-               SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE,
+                 SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
         return 0;
     }
 
     if (!PACKET_get_length_prefixed_1(pkt, &encoded_pt)) {
-        *al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_SKE_ECDHE, SSL_R_LENGTH_MISMATCH);
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE,
+                 SSL_R_LENGTH_MISMATCH);
         return 0;
     }
 
     if (!EVP_PKEY_set1_tls_encodedpoint(s->s3->peer_tmp,
                                         PACKET_data(&encoded_pt),
                                         PACKET_remaining(&encoded_pt))) {
-        *al = SSL_AD_ILLEGAL_PARAMETER;
-        SSLerr(SSL_F_TLS_PROCESS_SKE_ECDHE, SSL_R_BAD_ECPOINT);
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_ECDHE,
+                 SSL_R_BAD_ECPOINT);
         return 0;
     }
 
@@ -2094,15 +2141,14 @@ static int tls_process_ske_ecdhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
 
     return 1;
 #else
-    SSLerr(SSL_F_TLS_PROCESS_SKE_ECDHE, ERR_R_INTERNAL_ERROR);
-    *al = SSL_AD_INTERNAL_ERROR;
+    SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE,
+             ERR_R_INTERNAL_ERROR);
     return 0;
 #endif
 }
 
 MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
 {
-    int al = -1;
     long alg_k;
     EVP_PKEY *pkey = NULL;
     EVP_MD_CTX *md_ctx = NULL;
@@ -2119,24 +2165,32 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
 #endif
 
     if (alg_k & SSL_PSK) {
-        if (!tls_process_ske_psk_preamble(s, pkt, &al))
+        if (!tls_process_ske_psk_preamble(s, pkt)) {
+            /* SSLfatal() already called */
             goto err;
+        }
     }
 
     /* Nothing else to do for plain PSK or RSAPSK */
     if (alg_k & (SSL_kPSK | SSL_kRSAPSK)) {
     } else if (alg_k & SSL_kSRP) {
-        if (!tls_process_ske_srp(s, pkt, &pkey, &al))
+        if (!tls_process_ske_srp(s, pkt, &pkey)) {
+            /* SSLfatal() already called */
             goto err;
+        }
     } else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
-        if (!tls_process_ske_dhe(s, pkt, &pkey, &al))
+        if (!tls_process_ske_dhe(s, pkt, &pkey)) {
+            /* SSLfatal() already called */
             goto err;
+        }
     } else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
-        if (!tls_process_ske_ecdhe(s, pkt, &pkey, &al))
+        if (!tls_process_ske_ecdhe(s, pkt, &pkey)) {
+            /* SSLfatal() already called */
             goto err;
+        }
     } else if (alg_k) {
-        al = SSL_AD_UNEXPECTED_MESSAGE;
-        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_UNEXPECTED_MESSAGE);
+        SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
+                 SSL_R_UNEXPECTED_MESSAGE);
         goto err;
     }
 
@@ -2156,8 +2210,8 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
         if (!PACKET_get_sub_packet(&save_param_start, &params,
                                    PACKET_remaining(&save_param_start) -
                                    PACKET_remaining(pkt))) {
-            al = SSL_AD_DECODE_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+            SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
+                     ERR_R_INTERNAL_ERROR);
             goto err;
         }
 
@@ -2165,41 +2219,39 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
             unsigned int sigalg;
 
             if (!PACKET_get_net_2(pkt, &sigalg)) {
-                al = SSL_AD_DECODE_ERROR;
-                SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
+                SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
+                         SSL_R_LENGTH_TOO_SHORT);
                 goto err;
             }
-            rv = tls12_check_peer_sigalg(s, sigalg, pkey);
-            if (rv == -1) {
-                al = SSL_AD_INTERNAL_ERROR;
-                goto err;
-            } else if (rv == 0) {
-                al = SSL_AD_DECODE_ERROR;
+            if (tls12_check_peer_sigalg(s, sigalg, pkey) <=0) {
+                /* SSLfatal() already called */
                 goto err;
             }
 #ifdef SSL_DEBUG
             fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));
 #endif
         } else if (!tls1_set_peer_legacy_sigalg(s, pkey)) {
-            al = SSL_AD_INTERNAL_ERROR;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
+                     ERR_R_INTERNAL_ERROR);
             goto err;
         }
 
         if (!tls1_lookup_md(s->s3->tmp.peer_sigalg, &md)) {
-            al = SSL_AD_INTERNAL_ERROR;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
+                     ERR_R_INTERNAL_ERROR);
             goto err;
         }
 
         if (!PACKET_get_length_prefixed_2(pkt, &signature)
             || PACKET_remaining(pkt) != 0) {
-            al = SSL_AD_DECODE_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
+            SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
+                     SSL_R_LENGTH_MISMATCH);
             goto err;
         }
         maxsig = EVP_PKEY_size(pkey);
         if (maxsig < 0) {
-            al = SSL_AD_INTERNAL_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
+                     ERR_R_INTERNAL_ERROR);
             goto err;
         }
 
@@ -2208,38 +2260,36 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
          */
         if (PACKET_remaining(&signature) > (size_t)maxsig) {
             /* wrong packet length */
-            al = SSL_AD_DECODE_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE,
+            SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
                    SSL_R_WRONG_SIGNATURE_LENGTH);
             goto err;
         }
 
         md_ctx = EVP_MD_CTX_new();
         if (md_ctx == NULL) {
-            al = SSL_AD_INTERNAL_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
+                     ERR_R_MALLOC_FAILURE);
             goto err;
         }
 
         if (EVP_DigestVerifyInit(md_ctx, &pctx, md, NULL, pkey) <= 0) {
-            al = SSL_AD_INTERNAL_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_EVP_LIB);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
+                     ERR_R_EVP_LIB);
             goto err;
         }
         if (SSL_USE_PSS(s)) {
             if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0
                 || EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx,
                                                 RSA_PSS_SALTLEN_DIGEST) <= 0) {
-                al = SSL_AD_INTERNAL_ERROR;
-                SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_EVP_LIB);
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_EVP_LIB);
                 goto err;
             }
         }
         tbslen = construct_key_exchange_tbs(s, &tbs, PACKET_data(&params),
                                             PACKET_remaining(&params));
         if (tbslen == 0) {
-            al = SSL_AD_INTERNAL_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
+            /* SSLfatal() already called */
             goto err;
         }
 
@@ -2247,8 +2297,8 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
                               PACKET_remaining(&signature), tbs, tbslen);
         OPENSSL_free(tbs);
         if (rv <= 0) {
-            al = SSL_AD_DECRYPT_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_BAD_SIGNATURE);
+            SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
+                     SSL_R_BAD_SIGNATURE);
             goto err;
         }
         EVP_MD_CTX_free(md_ctx);
@@ -2259,35 +2309,28 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
             && !(alg_k & SSL_PSK)) {
             /* Might be wrong key type, check it */
             if (ssl3_check_cert_and_algorithm(s)) {
-                /* Otherwise this shouldn't happen */
-                al = SSL_AD_INTERNAL_ERROR;
-                SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
-            } else {
-                al = SSL_AD_DECODE_ERROR;
+                SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
+                         SSL_R_BAD_DATA);
             }
+            /* else this shouldn't happen, SSLfatal() already called */
             goto err;
         }
         /* still data left over */
         if (PACKET_remaining(pkt) != 0) {
-            al = SSL_AD_DECODE_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_EXTRA_DATA_IN_MESSAGE);
+            SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
+                     SSL_R_EXTRA_DATA_IN_MESSAGE);
             goto err;
         }
     }
 
     return MSG_PROCESS_CONTINUE_READING;
  err:
-    if (al != -1)
-        ssl3_send_alert(s, SSL3_AL_FATAL, al);
-    ossl_statem_set_error(s);
     EVP_MD_CTX_free(md_ctx);
     return MSG_PROCESS_ERROR;
 }
 
 MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt)
 {
-    MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR;
-    int al = SSL_AD_DECODE_ERROR;
     size_t i;
 
     /* Clear certificate validity flags */
@@ -2305,92 +2348,98 @@ MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt)
 
         /* TODO(TLS1.3) need to process request context, for now ignore */
         if (!PACKET_get_length_prefixed_1(pkt, &reqctx)) {
-            SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
-                   SSL_R_LENGTH_MISMATCH);
-            goto err;
+            SSLfatal(s, SSL_AD_DECODE_ERROR,
+                     SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
+                     SSL_R_LENGTH_MISMATCH);
+            return MSG_PROCESS_ERROR;
         }
 
         if (!PACKET_get_length_prefixed_2(pkt, &extensions)) {
-                SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, SSL_R_BAD_LENGTH);
-                goto err;
+            SSLfatal(s, SSL_AD_DECODE_ERROR,
+                     SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
+                     SSL_R_BAD_LENGTH);
+            return MSG_PROCESS_ERROR;
         }
         if (!tls_collect_extensions(s, &extensions,
                                     SSL_EXT_TLS1_3_CERTIFICATE_REQUEST,
-                                    &rawexts, &al, NULL, 1)
+                                    &rawexts, NULL, 1)
             || !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_CERTIFICATE_REQUEST,
-                                         rawexts, NULL, 0, &al, 1)) {
+                                         rawexts, NULL, 0, 1)) {
+            /* SSLfatal() already called */
             OPENSSL_free(rawexts);
-            goto err;
+            return MSG_PROCESS_ERROR;
         }
         OPENSSL_free(rawexts);
         if (!tls1_process_sigalgs(s)) {
-            al = SSL_AD_INTERNAL_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, ERR_R_MALLOC_FAILURE);
-            goto err;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
+                     SSL_R_BAD_LENGTH);
+            return MSG_PROCESS_ERROR;
         }
     } else {
         PACKET ctypes;
 
         /* get the certificate types */
         if (!PACKET_get_length_prefixed_1(pkt, &ctypes)) {
-            SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
-                   SSL_R_LENGTH_MISMATCH);
-            goto err;
+            SSLfatal(s, SSL_AD_DECODE_ERROR,
+                     SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
+                     SSL_R_LENGTH_MISMATCH);
+            return MSG_PROCESS_ERROR;
         }
 
         if (!PACKET_memdup(&ctypes, &s->s3->tmp.ctype, &s->s3->tmp.ctype_len)) {
-            al = SSL_AD_INTERNAL_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, ERR_R_INTERNAL_ERROR);
-            goto err;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
+                     ERR_R_INTERNAL_ERROR);
+            return MSG_PROCESS_ERROR;
         }
 
         if (SSL_USE_SIGALGS(s)) {
             PACKET sigalgs;
 
             if (!PACKET_get_length_prefixed_2(pkt, &sigalgs)) {
-                SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
-                       SSL_R_LENGTH_MISMATCH);
-                goto err;
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
+                         SSL_R_LENGTH_MISMATCH);
+                return MSG_PROCESS_ERROR;
             }
 
             if (!tls1_save_sigalgs(s, &sigalgs)) {
-                SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
-                       SSL_R_SIGNATURE_ALGORITHMS_ERROR);
-                goto err;
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
+                         SSL_R_SIGNATURE_ALGORITHMS_ERROR);
+                return MSG_PROCESS_ERROR;
             }
             if (!tls1_process_sigalgs(s)) {
-                al = SSL_AD_INTERNAL_ERROR;
-                SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
-                       ERR_R_MALLOC_FAILURE);
-                goto err;
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
+                         ERR_R_MALLOC_FAILURE);
+                return MSG_PROCESS_ERROR;
             }
         }
 
         /* get the CA RDNs */
-        if (!parse_ca_names(s, pkt, &al))
-            goto err;
+        if (!parse_ca_names(s, pkt)) {
+            /* SSLfatal() already called */
+            return MSG_PROCESS_ERROR;
+        }
     }
 
     if (PACKET_remaining(pkt) != 0) {
-        SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, SSL_R_LENGTH_MISMATCH);
-        goto err;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
+                 SSL_R_LENGTH_MISMATCH);
+        return MSG_PROCESS_ERROR;
     }
 
     /* we should setup a certificate to return.... */
     s->s3->tmp.cert_req = 1;
 
-    ret = MSG_PROCESS_CONTINUE_PROCESSING;
-    goto done;
- err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, al);
-    ossl_statem_set_error(s);
- done:
-    return ret;
+    return MSG_PROCESS_CONTINUE_PROCESSING;
 }
 
 MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt)
 {
-    int al = SSL_AD_DECODE_ERROR;
     unsigned int ticklen;
     unsigned long ticket_lifetime_hint, age_add = 0;
     unsigned int sess_len;
@@ -2407,8 +2456,9 @@ MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt)
         || (!SSL_IS_TLS13(s) && PACKET_remaining(pkt) != ticklen)
         || (SSL_IS_TLS13(s)
             && (ticklen == 0 || PACKET_remaining(pkt) < ticklen))) {
-        SSLerr(SSL_F_TLS_PROCESS_NEW_SESSION_TICKET, SSL_R_LENGTH_MISMATCH);
-        goto f_err;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
+                 SSL_R_LENGTH_MISMATCH);
+        goto err;
     }
 
     /*
@@ -2435,9 +2485,10 @@ MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt)
          * one
          */
         if ((new_sess = ssl_session_dup(s->session, 0)) == 0) {
-            al = SSL_AD_INTERNAL_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
-            goto f_err;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
+                     ERR_R_MALLOC_FAILURE);
+            goto err;
         }
 
         if (i & SSL_SESS_CACHE_CLIENT) {
@@ -2463,13 +2514,14 @@ MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt)
 
     s->session->ext.tick = OPENSSL_malloc(ticklen);
     if (s->session->ext.tick == NULL) {
-        SSLerr(SSL_F_TLS_PROCESS_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
+                 ERR_R_MALLOC_FAILURE);
         goto err;
     }
     if (!PACKET_copy_bytes(pkt, s->session->ext.tick, ticklen)) {
-        al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_NEW_SESSION_TICKET, SSL_R_LENGTH_MISMATCH);
-        goto f_err;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
+                 SSL_R_LENGTH_MISMATCH);
+        goto err;
     }
 
     s->session->ext.tick_lifetime_hint = ticket_lifetime_hint;
@@ -2483,12 +2535,12 @@ MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt)
                 || PACKET_remaining(pkt) != 0
                 || !tls_collect_extensions(s, &extpkt,
                                            SSL_EXT_TLS1_3_NEW_SESSION_TICKET,
-                                           &exts, &al, NULL, 1)
+                                           &exts, NULL, 1)
                 || !tls_parse_all_extensions(s,
                                              SSL_EXT_TLS1_3_NEW_SESSION_TICKET,
-                                             exts, NULL, 0, &al, 1)) {
-            SSLerr(SSL_F_TLS_PROCESS_NEW_SESSION_TICKET, SSL_R_BAD_EXTENSION);
-            goto f_err;
+                                             exts, NULL, 0, 1)) {
+            /* SSLfatal() already called */
+            goto err;
         }
     }
 
@@ -2510,7 +2562,8 @@ MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt)
     if (!EVP_Digest(s->session->ext.tick, ticklen,
                     s->session->session_id, &sess_len,
                     EVP_sha256(), NULL)) {
-        SSLerr(SSL_F_TLS_PROCESS_NEW_SESSION_TICKET, ERR_R_EVP_LIB);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
+                 ERR_R_EVP_LIB);
         goto err;
     }
     s->session->session_id_length = sess_len;
@@ -2523,46 +2576,41 @@ MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt)
     }
 
     return MSG_PROCESS_CONTINUE_READING;
- f_err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, al);
  err:
-    ossl_statem_set_error(s);
     OPENSSL_free(exts);
     return MSG_PROCESS_ERROR;
 }
 
 /*
  * In TLSv1.3 this is called from the extensions code, otherwise it is used to
- * parse a separate message. Returns 1 on success or 0 on failure. On failure
- * |*al| is populated with a suitable alert code.
+ * parse a separate message. Returns 1 on success or 0 on failure
  */
-int tls_process_cert_status_body(SSL *s, PACKET *pkt, int *al)
+int tls_process_cert_status_body(SSL *s, PACKET *pkt)
 {
     size_t resplen;
     unsigned int type;
 
     if (!PACKET_get_1(pkt, &type)
         || type != TLSEXT_STATUSTYPE_ocsp) {
-        *al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CERT_STATUS_BODY,
-               SSL_R_UNSUPPORTED_STATUS_TYPE);
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY,
+                 SSL_R_UNSUPPORTED_STATUS_TYPE);
         return 0;
     }
     if (!PACKET_get_net_3_len(pkt, &resplen)
         || PACKET_remaining(pkt) != resplen) {
-        *al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CERT_STATUS_BODY, SSL_R_LENGTH_MISMATCH);
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY,
+                 SSL_R_LENGTH_MISMATCH);
         return 0;
     }
     s->ext.ocsp.resp = OPENSSL_malloc(resplen);
     if (s->ext.ocsp.resp == NULL) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CERT_STATUS_BODY, ERR_R_MALLOC_FAILURE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY,
+                 ERR_R_MALLOC_FAILURE);
         return 0;
     }
     if (!PACKET_copy_bytes(pkt, s->ext.ocsp.resp, resplen)) {
-        *al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CERT_STATUS_BODY, SSL_R_LENGTH_MISMATCH);
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY,
+                 SSL_R_LENGTH_MISMATCH);
         return 0;
     }
     s->ext.ocsp.resp_len = resplen;
@@ -2573,11 +2621,8 @@ int tls_process_cert_status_body(SSL *s, PACKET *pkt, int *al)
 
 MSG_PROCESS_RETURN tls_process_cert_status(SSL *s, PACKET *pkt)
 {
-    int al;
-
-    if (!tls_process_cert_status_body(s, pkt, &al)) {
-        ssl3_send_alert(s, SSL3_AL_FATAL, al);
-        ossl_statem_set_error(s);
+    if (!tls_process_cert_status_body(s, pkt)) {
+        /* SSLfatal() already called */
         return MSG_PROCESS_ERROR;
     }
 
@@ -2590,14 +2635,14 @@ MSG_PROCESS_RETURN tls_process_cert_status(SSL *s, PACKET *pkt)
  * In <=TLS1.2 this is after the ServerDone message. Returns 1 on success or 0
  * on failure.
  */
-int tls_process_initial_server_flight(SSL *s, int *al)
+int tls_process_initial_server_flight(SSL *s)
 {
     /*
      * at this point we check that we have the required stuff from
      * the server
      */
     if (!ssl3_check_cert_and_algorithm(s)) {
-        *al = SSL_AD_HANDSHAKE_FAILURE;
+        /* SSLfatal() already called */
         return 0;
     }
 
@@ -2611,15 +2656,15 @@ int tls_process_initial_server_flight(SSL *s, int *al)
         int ret = s->ctx->ext.status_cb(s, s->ctx->ext.status_arg);
 
         if (ret == 0) {
-            *al = SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE;
-            SSLerr(SSL_F_TLS_PROCESS_INITIAL_SERVER_FLIGHT,
-                   SSL_R_INVALID_STATUS_RESPONSE);
+            SSLfatal(s, SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE,
+                     SSL_F_TLS_PROCESS_INITIAL_SERVER_FLIGHT,
+                     SSL_R_INVALID_STATUS_RESPONSE);
             return 0;
         }
         if (ret < 0) {
-            *al = SSL_AD_INTERNAL_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_INITIAL_SERVER_FLIGHT,
-                   ERR_R_MALLOC_FAILURE);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_PROCESS_INITIAL_SERVER_FLIGHT,
+                     ERR_R_MALLOC_FAILURE);
             return 0;
         }
     }
@@ -2627,7 +2672,7 @@ int tls_process_initial_server_flight(SSL *s, int *al)
     if (s->ct_validation_callback != NULL) {
         /* Note we validate the SCTs whether or not we abort on error */
         if (!ssl_validate_ct(s) && (s->verify_mode & SSL_VERIFY_PEER)) {
-            *al = SSL_AD_HANDSHAKE_FAILURE;
+            /* SSLfatal() already called */
             return 0;
         }
     }
@@ -2638,38 +2683,31 @@ int tls_process_initial_server_flight(SSL *s, int *al)
 
 MSG_PROCESS_RETURN tls_process_server_done(SSL *s, PACKET *pkt)
 {
-    int al = SSL_AD_INTERNAL_ERROR;
-
     if (PACKET_remaining(pkt) > 0) {
         /* should contain no data */
-        al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_SERVER_DONE, SSL_R_LENGTH_MISMATCH);
-        goto err;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_DONE,
+                 SSL_R_LENGTH_MISMATCH);
+        return MSG_PROCESS_ERROR;
     }
 #ifndef OPENSSL_NO_SRP
     if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) {
         if (SRP_Calc_A_param(s) <= 0) {
-            SSLerr(SSL_F_TLS_PROCESS_SERVER_DONE, SSL_R_SRP_A_CALC);
-            goto err;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_DONE,
+                     SSL_R_SRP_A_CALC);
+            return MSG_PROCESS_ERROR;
         }
     }
 #endif
 
-    /*
-     * Error queue messages are generated directly by this function
-     */
-    if (!tls_process_initial_server_flight(s, &al))
-        goto err;
+    if (!tls_process_initial_server_flight(s)) {
+        /* SSLfatal() already called */
+        return MSG_PROCESS_ERROR;
+    }
 
     return MSG_PROCESS_FINISHED_READING;
-
- err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, al);
-    ossl_statem_set_error(s);
-    return MSG_PROCESS_ERROR;
 }
 
-static int tls_construct_cke_psk_preamble(SSL *s, WPACKET *pkt, int *al)
+static int tls_construct_cke_psk_preamble(SSL *s, WPACKET *pkt)
 {
 #ifndef OPENSSL_NO_PSK
     int ret = 0;
@@ -2686,8 +2724,8 @@ static int tls_construct_cke_psk_preamble(SSL *s, WPACKET *pkt, int *al)
     size_t psklen = 0;
 
     if (s->psk_client_callback == NULL) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, SSL_R_PSK_NO_CLIENT_CB);
-        *al = SSL_AD_INTERNAL_ERROR;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
+                 SSL_R_PSK_NO_CLIENT_CB);
         goto err;
     }
 
@@ -2698,28 +2736,28 @@ static int tls_construct_cke_psk_preamble(SSL *s, WPACKET *pkt, int *al)
                                     psk, sizeof(psk));
 
     if (psklen > PSK_MAX_PSK_LEN) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
-        *al = SSL_AD_HANDSHAKE_FAILURE;
+        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+                 SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
         goto err;
     } else if (psklen == 0) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
-               SSL_R_PSK_IDENTITY_NOT_FOUND);
-        *al = SSL_AD_HANDSHAKE_FAILURE;
+        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+                 SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
+                 SSL_R_PSK_IDENTITY_NOT_FOUND);
         goto err;
     }
 
     identitylen = strlen(identity);
     if (identitylen > PSK_MAX_IDENTITY_LEN) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
-        *al = SSL_AD_INTERNAL_ERROR;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
     }
 
     tmppsk = OPENSSL_memdup(psk, psklen);
     tmpidentity = OPENSSL_strdup(identity);
     if (tmppsk == NULL || tmpidentity == NULL) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, ERR_R_MALLOC_FAILURE);
-        *al = SSL_AD_INTERNAL_ERROR;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
+                 ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
@@ -2732,8 +2770,8 @@ static int tls_construct_cke_psk_preamble(SSL *s, WPACKET *pkt, int *al)
     tmpidentity = NULL;
 
     if (!WPACKET_sub_memcpy_u16(pkt, identity, identitylen))  {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
-        *al = SSL_AD_INTERNAL_ERROR;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
     }
 
@@ -2747,13 +2785,13 @@ static int tls_construct_cke_psk_preamble(SSL *s, WPACKET *pkt, int *al)
 
     return ret;
 #else
-    SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
-    *al = SSL_AD_INTERNAL_ERROR;
+    SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
+             ERR_R_INTERNAL_ERROR);
     return 0;
 #endif
 }
 
-static int tls_construct_cke_rsa(SSL *s, WPACKET *pkt, int *al)
+static int tls_construct_cke_rsa(SSL *s, WPACKET *pkt)
 {
 #ifndef OPENSSL_NO_RSA
     unsigned char *encdata = NULL;
@@ -2767,21 +2805,23 @@ static int tls_construct_cke_rsa(SSL *s, WPACKET *pkt, int *al)
         /*
          * We should always have a server certificate with SSL_kRSA.
          */
-        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_RSA, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
     pkey = X509_get0_pubkey(s->session->peer);
     if (EVP_PKEY_get0_RSA(pkey) == NULL) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_RSA, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
     pmslen = SSL_MAX_MASTER_KEY_LENGTH;
     pms = OPENSSL_malloc(pmslen);
     if (pms == NULL) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_RSA, ERR_R_MALLOC_FAILURE);
-        *al = SSL_AD_INTERNAL_ERROR;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
+                 ERR_R_MALLOC_FAILURE);
         return 0;
     }
 
@@ -2789,23 +2829,28 @@ static int tls_construct_cke_rsa(SSL *s, WPACKET *pkt, int *al)
     pms[1] = s->client_version & 0xff;
     /* TODO(size_t): Convert this function */
     if (ssl_randbytes(s, pms + 2, (int)(pmslen - 2)) <= 0) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
+                 ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
     /* Fix buf for TLS and beyond */
     if (s->version > SSL3_VERSION && !WPACKET_start_sub_packet_u16(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_RSA, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
     }
     pctx = EVP_PKEY_CTX_new(pkey, NULL);
     if (pctx == NULL || EVP_PKEY_encrypt_init(pctx) <= 0
         || EVP_PKEY_encrypt(pctx, NULL, &enclen, pms, pmslen) <= 0) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_RSA, ERR_R_EVP_LIB);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
+                 ERR_R_EVP_LIB);
         goto err;
     }
     if (!WPACKET_allocate_bytes(pkt, enclen, &encdata)
             || EVP_PKEY_encrypt(pctx, encdata, &enclen, pms, pmslen) <= 0) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_RSA, SSL_R_BAD_RSA_ENCRYPT);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
+                 SSL_R_BAD_RSA_ENCRYPT);
         goto err;
     }
     EVP_PKEY_CTX_free(pctx);
@@ -2813,13 +2858,16 @@ static int tls_construct_cke_rsa(SSL *s, WPACKET *pkt, int *al)
 
     /* Fix buf for TLS and beyond */
     if (s->version > SSL3_VERSION && !WPACKET_close(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_RSA, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
     }
 
     /* Log the premaster secret, if logging is enabled. */
-    if (!ssl_log_rsa_client_key_exchange(s, encdata, enclen, pms, pmslen))
+    if (!ssl_log_rsa_client_key_exchange(s, encdata, enclen, pms, pmslen)) {
+        /* SSLfatal() already called */
         goto err;
+    }
 
     s->s3->tmp.pms = pms;
     s->s3->tmp.pmslen = pmslen;
@@ -2831,13 +2879,13 @@ static int tls_construct_cke_rsa(SSL *s, WPACKET *pkt, int *al)
 
     return 0;
 #else
-    SSLerr(SSL_F_TLS_CONSTRUCT_CKE_RSA, ERR_R_INTERNAL_ERROR);
-    *al = SSL_AD_INTERNAL_ERROR;
+    SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
+             ERR_R_INTERNAL_ERROR);
     return 0;
 #endif
 }
 
-static int tls_construct_cke_dhe(SSL *s, WPACKET *pkt, int *al)
+static int tls_construct_cke_dhe(SSL *s, WPACKET *pkt)
 {
 #ifndef OPENSSL_NO_DH
     DH *dh_clnt = NULL;
@@ -2846,22 +2894,40 @@ static int tls_construct_cke_dhe(SSL *s, WPACKET *pkt, int *al)
     unsigned char *keybytes = NULL;
 
     skey = s->s3->peer_tmp;
-    if (skey == NULL)
+    if (skey == NULL) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
+    }
 
     ckey = ssl_generate_pkey(skey);
-    if (ckey == NULL)
+    if (ckey == NULL) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
+    }
 
     dh_clnt = EVP_PKEY_get0_DH(ckey);
 
-    if (dh_clnt == NULL || ssl_derive(s, ckey, skey, 0) == 0)
+    if (dh_clnt == NULL) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
+                 ERR_R_INTERNAL_ERROR);
+        goto err;
+    }
+
+    if (ssl_derive(s, ckey, skey, 0) == 0) {
+        /* SSLfatal() already called */
         goto err;
+    }
 
     /* send off the data */
     DH_get0_key(dh_clnt, &pub_key, NULL);
-    if (!WPACKET_sub_allocate_bytes_u16(pkt, BN_num_bytes(pub_key), &keybytes))
+    if (!WPACKET_sub_allocate_bytes_u16(pkt, BN_num_bytes(pub_key),
+                                        &keybytes)) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
+    }
 
     BN_bn2bin(pub_key, keybytes);
     EVP_PKEY_free(ckey);
@@ -2869,13 +2935,15 @@ static int tls_construct_cke_dhe(SSL *s, WPACKET *pkt, int *al)
     return 1;
  err:
     EVP_PKEY_free(ckey);
-#endif
-    SSLerr(SSL_F_TLS_CONSTRUCT_CKE_DHE, ERR_R_INTERNAL_ERROR);
-    *al = SSL_AD_INTERNAL_ERROR;
     return 0;
+#else
+    SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
+             ERR_R_INTERNAL_ERROR);
+    return 0;
+#endif
 }
 
-static int tls_construct_cke_ecdhe(SSL *s, WPACKET *pkt, int *al)
+static int tls_construct_cke_ecdhe(SSL *s, WPACKET *pkt)
 {
 #ifndef OPENSSL_NO_EC
     unsigned char *encodedPoint = NULL;
@@ -2885,18 +2953,20 @@ static int tls_construct_cke_ecdhe(SSL *s, WPACKET *pkt, int *al)
 
     skey = s->s3->peer_tmp;
     if (skey == NULL) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_ECDHE, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
     ckey = ssl_generate_pkey(skey);
     if (ckey == NULL) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_ECDHE, ERR_R_MALLOC_FAILURE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
+                 ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
     if (ssl_derive(s, ckey, skey, 0) == 0) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_ECDHE, ERR_R_EVP_LIB);
+        /* SSLfatal() already called */
         goto err;
     }
 
@@ -2904,12 +2974,14 @@ static int tls_construct_cke_ecdhe(SSL *s, WPACKET *pkt, int *al)
     encoded_pt_len = EVP_PKEY_get1_tls_encodedpoint(ckey, &encodedPoint);
 
     if (encoded_pt_len == 0) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_ECDHE, ERR_R_EC_LIB);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
+                 ERR_R_EC_LIB);
         goto err;
     }
 
     if (!WPACKET_sub_memcpy_u8(pkt, encodedPoint, encoded_pt_len)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_ECDHE, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
     }
 
@@ -2919,13 +2991,13 @@ static int tls_construct_cke_ecdhe(SSL *s, WPACKET *pkt, int *al)
     EVP_PKEY_free(ckey);
     return ret;
 #else
-    SSLerr(SSL_F_TLS_CONSTRUCT_CKE_ECDHE, ERR_R_INTERNAL_ERROR);
-    *al = SSL_AD_INTERNAL_ERROR;
+    SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
+             ERR_R_INTERNAL_ERROR);
     return 0;
 #endif
 }
 
-static int tls_construct_cke_gost(SSL *s, WPACKET *pkt, int *al)
+static int tls_construct_cke_gost(SSL *s, WPACKET *pkt)
 {
 #ifndef OPENSSL_NO_GOST
     /* GOST key exchange message creation */
@@ -2947,16 +3019,15 @@ static int tls_construct_cke_gost(SSL *s, WPACKET *pkt, int *al)
      */
     peer_cert = s->session->peer;
     if (!peer_cert) {
-        *al = SSL_AD_HANDSHAKE_FAILURE;
-        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST,
+        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_CONSTRUCT_CKE_GOST,
                SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);
         return 0;
     }
 
     pkey_ctx = EVP_PKEY_CTX_new(X509_get0_pubkey(peer_cert), NULL);
     if (pkey_ctx == NULL) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, ERR_R_MALLOC_FAILURE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
+                 ERR_R_MALLOC_FAILURE);
         return 0;
     }
     /*
@@ -2969,8 +3040,8 @@ static int tls_construct_cke_gost(SSL *s, WPACKET *pkt, int *al)
     pmslen = 32;
     pms = OPENSSL_malloc(pmslen);
     if (pms == NULL) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, ERR_R_MALLOC_FAILURE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
+                 ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
@@ -2979,8 +3050,8 @@ static int tls_construct_cke_gost(SSL *s, WPACKET *pkt, int *al)
          * TODO(size_t): Convert this function
          */
         || ssl_randbytes(s, pms, (int)pmslen) <= 0) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
     };
     /*
@@ -2995,16 +3066,16 @@ static int tls_construct_cke_gost(SSL *s, WPACKET *pkt, int *al)
         || EVP_DigestUpdate(ukm_hash, s->s3->server_random,
                             SSL3_RANDOM_SIZE) <= 0
         || EVP_DigestFinal_ex(ukm_hash, shared_ukm, &md_len) <= 0) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
     }
     EVP_MD_CTX_free(ukm_hash);
     ukm_hash = NULL;
     if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT,
                           EVP_PKEY_CTRL_SET_IV, 8, shared_ukm) < 0) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, SSL_R_LIBRARY_BUG);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
+                 SSL_R_LIBRARY_BUG);
         goto err;
     }
     /* Make GOST keytransport blob message */
@@ -3013,16 +3084,16 @@ static int tls_construct_cke_gost(SSL *s, WPACKET *pkt, int *al)
      */
     msglen = 255;
     if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, pms, pmslen) <= 0) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, SSL_R_LIBRARY_BUG);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
+                 SSL_R_LIBRARY_BUG);
         goto err;
     }
 
     if (!WPACKET_put_bytes_u8(pkt, V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED)
             || (msglen >= 0x80 && !WPACKET_put_bytes_u8(pkt, 0x81))
             || !WPACKET_sub_memcpy_u8(pkt, tmp, msglen)) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
     }
 
@@ -3037,13 +3108,13 @@ static int tls_construct_cke_gost(SSL *s, WPACKET *pkt, int *al)
     EVP_MD_CTX_free(ukm_hash);
     return 0;
 #else
-    SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, ERR_R_INTERNAL_ERROR);
-    *al = SSL_AD_INTERNAL_ERROR;
+    SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
+             ERR_R_INTERNAL_ERROR);
     return 0;
 #endif
 }
 
-static int tls_construct_cke_srp(SSL *s, WPACKET *pkt, int *al)
+static int tls_construct_cke_srp(SSL *s, WPACKET *pkt)
 {
 #ifndef OPENSSL_NO_SRP
     unsigned char *abytes = NULL;
@@ -3051,7 +3122,8 @@ static int tls_construct_cke_srp(SSL *s, WPACKET *pkt, int *al)
     if (s->srp_ctx.A == NULL
             || !WPACKET_sub_allocate_bytes_u16(pkt, BN_num_bytes(s->srp_ctx.A),
                                                &abytes)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_SRP, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_SRP,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
     }
     BN_bn2bin(s->srp_ctx.A, abytes);
@@ -3059,14 +3131,15 @@ static int tls_construct_cke_srp(SSL *s, WPACKET *pkt, int *al)
     OPENSSL_free(s->session->srp_username);
     s->session->srp_username = OPENSSL_strdup(s->srp_ctx.login);
     if (s->session->srp_username == NULL) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CKE_SRP, ERR_R_MALLOC_FAILURE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_SRP,
+                 ERR_R_MALLOC_FAILURE);
         return 0;
     }
 
     return 1;
 #else
-    SSLerr(SSL_F_TLS_CONSTRUCT_CKE_SRP, ERR_R_INTERNAL_ERROR);
-    *al = SSL_AD_INTERNAL_ERROR;
+    SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_SRP,
+             ERR_R_INTERNAL_ERROR);
     return 0;
 #endif
 }
@@ -3074,39 +3147,40 @@ static int tls_construct_cke_srp(SSL *s, WPACKET *pkt, int *al)
 int tls_construct_client_key_exchange(SSL *s, WPACKET *pkt)
 {
     unsigned long alg_k;
-    int al = -1;
 
     alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
 
+    /*
+     * All of the construct functions below call SSLfatal() if necessary so
+     * no need to do so here.
+     */
     if ((alg_k & SSL_PSK)
-        && !tls_construct_cke_psk_preamble(s, pkt, &al))
+        && !tls_construct_cke_psk_preamble(s, pkt))
         goto err;
 
     if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) {
-        if (!tls_construct_cke_rsa(s, pkt, &al))
+        if (!tls_construct_cke_rsa(s, pkt))
             goto err;
     } else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
-        if (!tls_construct_cke_dhe(s, pkt, &al))
+        if (!tls_construct_cke_dhe(s, pkt))
             goto err;
     } else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
-        if (!tls_construct_cke_ecdhe(s, pkt, &al))
+        if (!tls_construct_cke_ecdhe(s, pkt))
             goto err;
     } else if (alg_k & SSL_kGOST) {
-        if (!tls_construct_cke_gost(s, pkt, &al))
+        if (!tls_construct_cke_gost(s, pkt))
             goto err;
     } else if (alg_k & SSL_kSRP) {
-        if (!tls_construct_cke_srp(s, pkt, &al))
+        if (!tls_construct_cke_srp(s, pkt))
             goto err;
     } else if (!(alg_k & SSL_kPSK)) {
-        ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
         goto err;
     }
 
     return 1;
  err:
-    if (al != -1)
-        ssl3_send_alert(s, SSL3_AL_FATAL, al);
     OPENSSL_clear_free(s->s3->tmp.pms, s->s3->tmp.pmslen);
     s->s3->tmp.pms = NULL;
 #ifndef OPENSSL_NO_PSK
@@ -3128,8 +3202,7 @@ int tls_client_key_exchange_post_work(SSL *s)
     /* Check for SRP */
     if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) {
         if (!srp_generate_client_master_secret(s)) {
-            SSLerr(SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK,
-                   ERR_R_INTERNAL_ERROR);
+            /* SSLfatal() already called */
             goto err;
         }
         return 1;
@@ -3137,13 +3210,12 @@ int tls_client_key_exchange_post_work(SSL *s)
 #endif
 
     if (pms == NULL && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) {
-        ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-        SSLerr(SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK, ERR_R_MALLOC_FAILURE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK, ERR_R_MALLOC_FAILURE);
         goto err;
     }
     if (!ssl_generate_master_secret(s, pms, pmslen, 1)) {
-        ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-        SSLerr(SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK, ERR_R_INTERNAL_ERROR);
+        /* SSLfatal() already called */
         /* ssl_generate_master_secret frees the pms even on error */
         pms = NULL;
         pmslen = 0;
@@ -3166,8 +3238,12 @@ int tls_client_key_exchange_post_work(SSL *s)
 
         if (SSL_export_keying_material(s, sctpauthkey,
                                        sizeof(sctpauthkey), labelbuffer,
-                                       sizeof(labelbuffer), NULL, 0, 0) <= 0)
+                                       sizeof(labelbuffer), NULL, 0, 0) <= 0) {
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK,
+                     ERR_R_INTERNAL_ERROR);
             goto err;
+        }
 
         BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
                  sizeof(sctpauthkey), sctpauthkey);
@@ -3189,7 +3265,7 @@ int tls_client_key_exchange_post_work(SSL *s)
 static int ssl3_check_client_certificate(SSL *s)
 {
     /* If no suitable signature algorithm can't use certificate */
-    if (!tls_choose_sigalg(s, NULL) || s->s3->tmp.sigalg == NULL)
+    if (!tls_choose_sigalg(s, 0) || s->s3->tmp.sigalg == NULL)
         return 0;
     /*
      * If strict mode check suitability of chain before using it. This also
@@ -3216,8 +3292,9 @@ WORK_STATE tls_prepare_client_certificate(SSL *s, WORK_STATE wst)
                 return WORK_MORE_A;
             }
             if (i == 0) {
-                ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-                ossl_statem_set_error(s);
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE,
+                         SSL_R_CALLBACK_FAILED);
                 return WORK_ERROR;
             }
             s->rwstate = SSL_NOTHING;
@@ -3262,8 +3339,7 @@ WORK_STATE tls_prepare_client_certificate(SSL *s, WORK_STATE wst)
             } else {
                 s->s3->tmp.cert_req = 2;
                 if (!ssl3_digest_cached_records(s, 0)) {
-                    ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-                    ossl_statem_set_error(s);
+                    /* SSLfatal() already called */
                     return WORK_ERROR;
                 }
             }
@@ -3273,44 +3349,43 @@ WORK_STATE tls_prepare_client_certificate(SSL *s, WORK_STATE wst)
     }
 
     /* Shouldn't ever get here */
+    SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE,
+             ERR_R_INTERNAL_ERROR);
     return WORK_ERROR;
 }
 
 int tls_construct_client_certificate(SSL *s, WPACKET *pkt)
 {
-    int al = SSL_AD_INTERNAL_ERROR;
-
     /*
      * TODO(TLS1.3): For now we must put an empty context. Needs to be filled in
      * later
      */
-    if ((SSL_IS_TLS13(s) && !WPACKET_put_bytes_u8(pkt, 0))
-            || !ssl3_output_cert_chain(s, pkt,
-                               (s->s3->tmp.cert_req == 2) ? NULL
-                                                          : s->cert->key,
-                                &al)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR);
-        goto err;
+    if (SSL_IS_TLS13(s) && !WPACKET_put_bytes_u8(pkt, 0)) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+    if (!ssl3_output_cert_chain(s, pkt,
+                                (s->s3->tmp.cert_req == 2) ? NULL
+                                                           : s->cert->key)) {
+        /* SSLfatal() already called */
+        return 0;
     }
 
     if (SSL_IS_TLS13(s)
             && SSL_IS_FIRST_HANDSHAKE(s)
             && (!s->method->ssl3_enc->change_cipher_state(s,
                     SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_WRITE))) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE,
-               SSL_R_CANNOT_CHANGE_CIPHER);
         /*
-         * This is a fatal error, which leaves
-         * enc_write_ctx in an inconsistent state
-         * and thus ssl3_send_alert may crash.
+         * This is a fatal error, which leaves enc_write_ctx in an inconsistent
+         * state and thus ssl3_send_alert may crash.
          */
+        SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE,
+                 SSL_R_CANNOT_CHANGE_CIPHER);
         return 0;
     }
 
     return 1;
- err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, al);
-    return 0;
 }
 
 int ssl3_check_cert_and_algorithm(SSL *s)
@@ -3318,7 +3393,6 @@ int ssl3_check_cert_and_algorithm(SSL *s)
     const SSL_CERT_LOOKUP *clu;
     size_t idx;
     long alg_k, alg_a;
-    int al = SSL_AD_HANDSHAKE_FAILURE;
 
     alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
     alg_a = s->s3->tmp.new_cipher->algorithm_auth;
@@ -3332,37 +3406,38 @@ int ssl3_check_cert_and_algorithm(SSL *s)
 
     /* Check certificate is recognised and suitable for cipher */
     if (clu == NULL || (alg_a & clu->amask) == 0) {
-        SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_MISSING_SIGNING_CERT);
-        goto f_err;
+        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+                 SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
+                 SSL_R_MISSING_SIGNING_CERT);
+        return 0;
     }
 
 #ifndef OPENSSL_NO_EC
     if (clu->amask & SSL_aECDSA) {
         if (ssl_check_srvr_ecc_cert_and_alg(s->session->peer, s))
             return 1;
-        SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_BAD_ECC_CERT);
-        goto f_err;
+        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+                 SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_BAD_ECC_CERT);
+        return 0;
     }
 #endif
 #ifndef OPENSSL_NO_RSA
     if (alg_k & (SSL_kRSA | SSL_kRSAPSK) && idx != SSL_PKEY_RSA) {
-        SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
-               SSL_R_MISSING_RSA_ENCRYPTING_CERT);
-        goto f_err;
+        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+                 SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
+                 SSL_R_MISSING_RSA_ENCRYPTING_CERT);
+        return 0;
     }
 #endif
 #ifndef OPENSSL_NO_DH
     if ((alg_k & SSL_kDHE) && (s->s3->peer_tmp == NULL)) {
-        al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, ERR_R_INTERNAL_ERROR);
-        goto f_err;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
+                 ERR_R_INTERNAL_ERROR);
+        return 0;
     }
 #endif
 
     return 1;
- f_err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, al);
-    return 0;
 }
 
 #ifndef OPENSSL_NO_NEXTPROTONEG
@@ -3376,16 +3451,14 @@ int tls_construct_next_proto(SSL *s, WPACKET *pkt)
 
     if (!WPACKET_sub_memcpy_u8(pkt, s->ext.npn, len)
             || !WPACKET_sub_allocate_bytes_u8(pkt, padding_len, &padding)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_NEXT_PROTO, ERR_R_INTERNAL_ERROR);
-        goto err;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_NEXT_PROTO,
+                 ERR_R_INTERNAL_ERROR);
+        return 0;
     }
 
     memset(padding, 0, padding_len);
 
     return 1;
- err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-    return 0;
 }
 #endif
 
@@ -3393,9 +3466,8 @@ MSG_PROCESS_RETURN tls_process_hello_req(SSL *s, PACKET *pkt)
 {
     if (PACKET_remaining(pkt) > 0) {
         /* should contain no data */
-        SSLerr(SSL_F_TLS_PROCESS_HELLO_REQ, SSL_R_LENGTH_MISMATCH);
-        ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
-        ossl_statem_set_error(s);
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_HELLO_REQ,
+                 SSL_R_LENGTH_MISMATCH);
         return MSG_PROCESS_ERROR;
     }
 
@@ -3421,30 +3493,29 @@ MSG_PROCESS_RETURN tls_process_hello_req(SSL *s, PACKET *pkt)
 
 static MSG_PROCESS_RETURN tls_process_encrypted_extensions(SSL *s, PACKET *pkt)
 {
-    int al = SSL_AD_INTERNAL_ERROR;
     PACKET extensions;
     RAW_EXTENSION *rawexts = NULL;
 
     if (!PACKET_as_length_prefixed_2(pkt, &extensions)
             || PACKET_remaining(pkt) != 0) {
-        al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_ENCRYPTED_EXTENSIONS, SSL_R_LENGTH_MISMATCH);
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_ENCRYPTED_EXTENSIONS,
+                 SSL_R_LENGTH_MISMATCH);
         goto err;
     }
 
     if (!tls_collect_extensions(s, &extensions,
                                 SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS, &rawexts,
-                                &al, NULL, 1)
+                                NULL, 1)
             || !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
-                                         rawexts, NULL, 0, &al, 1))
+                                         rawexts, NULL, 0, 1)) {
+        /* SSLfatal() already called */
         goto err;
+    }
 
     OPENSSL_free(rawexts);
     return MSG_PROCESS_CONTINUE_READING;
 
  err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, al);
-    ossl_statem_set_error(s);
     OPENSSL_free(rawexts);
     return MSG_PROCESS_ERROR;
 }
@@ -3474,8 +3545,11 @@ int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, WPACKET *pkt)
     /* Set disabled masks for this session */
     ssl_set_client_disabled(s);
 
-    if (sk == NULL)
+    if (sk == NULL) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CIPHER_LIST_TO_BYTES,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
+    }
 
 #ifdef OPENSSL_MAX_TLS1_2_CIPHER_LENGTH
 # if OPENSSL_MAX_TLS1_2_CIPHER_LENGTH < 6
@@ -3507,7 +3581,8 @@ int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, WPACKET *pkt)
             continue;
 
         if (!s->method->put_cipher_by_char(c, pkt, &len)) {
-            SSLerr(SSL_F_SSL_CIPHER_LIST_TO_BYTES, ERR_R_INTERNAL_ERROR);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CIPHER_LIST_TO_BYTES,
+                     ERR_R_INTERNAL_ERROR);
             return 0;
         }
 
@@ -3528,7 +3603,8 @@ int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, WPACKET *pkt)
     }
 
     if (totlen == 0 || !maxverok) {
-        SSLerr(SSL_F_SSL_CIPHER_LIST_TO_BYTES, SSL_R_NO_CIPHERS_AVAILABLE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CIPHER_LIST_TO_BYTES,
+                 SSL_R_NO_CIPHERS_AVAILABLE);
 
         if (!maxverok)
             ERR_add_error_data(1, "No ciphers enabled for max supported "
@@ -3543,7 +3619,8 @@ int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, WPACKET *pkt)
                 0, NULL, NULL, SSL3_CK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0
             };
             if (!s->method->put_cipher_by_char(&scsv, pkt, &len)) {
-                SSLerr(SSL_F_SSL_CIPHER_LIST_TO_BYTES, ERR_R_INTERNAL_ERROR);
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_SSL_CIPHER_LIST_TO_BYTES, ERR_R_INTERNAL_ERROR);
                 return 0;
             }
         }
@@ -3552,7 +3629,8 @@ int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, WPACKET *pkt)
                 0, NULL, NULL, SSL3_CK_FALLBACK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0
             };
             if (!s->method->put_cipher_by_char(&scsv, pkt, &len)) {
-                SSLerr(SSL_F_SSL_CIPHER_LIST_TO_BYTES, ERR_R_INTERNAL_ERROR);
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_SSL_CIPHER_LIST_TO_BYTES, ERR_R_INTERNAL_ERROR);
                 return 0;
             }
         }
@@ -3565,8 +3643,9 @@ int tls_construct_end_of_early_data(SSL *s, WPACKET *pkt)
 {
     if (s->early_data_state != SSL_EARLY_DATA_WRITE_RETRY
             && s->early_data_state != SSL_EARLY_DATA_FINISHED_WRITING) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_END_OF_EARLY_DATA,
-               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_END_OF_EARLY_DATA,
+                 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
         return 0;
     }
 
diff --git a/ssl/statem/statem_dtls.c b/ssl/statem/statem_dtls.c
index 7fb6cdb..d19fe0a 100644
--- a/ssl/statem/statem_dtls.c
+++ b/ssl/statem/statem_dtls.c
@@ -415,8 +415,9 @@ static int dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr)
     /* sanity checking */
     if ((frag_off + frag_len) > msg_len
             || msg_len > dtls1_max_handshake_message_len(s)) {
-        SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT, SSL_R_EXCESSIVE_MESSAGE_SIZE);
-        return SSL_AD_ILLEGAL_PARAMETER;
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_DTLS1_PREPROCESS_FRAGMENT,
+                 SSL_R_EXCESSIVE_MESSAGE_SIZE);
+        return 0;
     }
 
     if (s->d1->r_msg_hdr.frag_off == 0) { /* first fragment */
@@ -425,8 +426,9 @@ static int dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr)
          * dtls_max_handshake_message_len(s) above
          */
         if (!BUF_MEM_grow_clean(s->init_buf, msg_len + DTLS1_HM_HEADER_LENGTH)) {
-            SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT, ERR_R_BUF_LIB);
-            return SSL_AD_INTERNAL_ERROR;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_PREPROCESS_FRAGMENT,
+                     ERR_R_BUF_LIB);
+            return 0;
         }
 
         s->s3->tmp.message_size = msg_len;
@@ -439,13 +441,18 @@ static int dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr)
          * They must be playing with us! BTW, failure to enforce upper limit
          * would open possibility for buffer overrun.
          */
-        SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT, SSL_R_EXCESSIVE_MESSAGE_SIZE);
-        return SSL_AD_ILLEGAL_PARAMETER;
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_DTLS1_PREPROCESS_FRAGMENT,
+                 SSL_R_EXCESSIVE_MESSAGE_SIZE);
+        return 0;
     }
 
-    return 0;                   /* no error */
+    return 1;
 }
 
+/*
+ * Returns 1 if there is a buffered fragment available, 0 if not, or -1 on a
+ * fatal error.
+ */
 static int dtls1_retrieve_buffered_fragment(SSL *s, size_t *len)
 {
     /*-
@@ -456,7 +463,7 @@ static int dtls1_retrieve_buffered_fragment(SSL *s, size_t *len)
      */
     pitem *item;
     hm_fragment *frag;
-    int al;
+    int ret;
 
     do {
         item = pqueue_peek(s->d1->buffered_messages);
@@ -483,9 +490,10 @@ static int dtls1_retrieve_buffered_fragment(SSL *s, size_t *len)
         size_t frag_len = frag->msg_header.frag_len;
         pqueue_pop(s->d1->buffered_messages);
 
-        al = dtls1_preprocess_fragment(s, &frag->msg_header);
+        /* Calls SSLfatal() as required */
+        ret = dtls1_preprocess_fragment(s, &frag->msg_header);
 
-        if (al == 0) {          /* no alert */
+        if (ret) {
             unsigned char *p =
                 (unsigned char *)s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
             memcpy(&p[frag->msg_header.frag_off], frag->fragment,
@@ -495,14 +503,14 @@ static int dtls1_retrieve_buffered_fragment(SSL *s, size_t *len)
         dtls1_hm_fragment_free(frag);
         pitem_free(item);
 
-        if (al == 0) {
+        if (ret) {
             *len = frag_len;
             return 1;
         }
 
-        ssl3_send_alert(s, SSL3_AL_FATAL, al);
+        /* Fatal error */
         s->init_num = 0;
-        return 0;
+        return -1;
     } else {
         return 0;
     }
@@ -719,7 +727,7 @@ static int dtls_get_reassembled_message(SSL *s, int *errtype, size_t *len)
 {
     unsigned char wire[DTLS1_HM_HEADER_LENGTH];
     size_t mlen, frag_off, frag_len;
-    int i, al, recvd_type;
+    int i, ret, recvd_type;
     struct hm_header_st msg_hdr;
     size_t readbytes;
 
@@ -727,7 +735,12 @@ static int dtls_get_reassembled_message(SSL *s, int *errtype, size_t *len)
 
  redo:
     /* see if we have the required fragment already */
-    if (dtls1_retrieve_buffered_fragment(s, &frag_len)) {
+    ret = dtls1_retrieve_buffered_fragment(s, &frag_len);
+    if (ret < 0) {
+        /* SSLfatal() already called */
+        return 0;
+    }
+    if (ret > 0) {
         s->init_num = frag_len;
         *len = frag_len;
         return 1;
@@ -743,9 +756,9 @@ static int dtls_get_reassembled_message(SSL *s, int *errtype, size_t *len)
     }
     if (recvd_type == SSL3_RT_CHANGE_CIPHER_SPEC) {
         if (wire[0] != SSL3_MT_CCS) {
-            al = SSL_AD_UNEXPECTED_MESSAGE;
-            SSLerr(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE,
-                   SSL_R_BAD_CHANGE_CIPHER_SPEC);
+            SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
+                     SSL_F_DTLS_GET_REASSEMBLED_MESSAGE,
+                     SSL_R_BAD_CHANGE_CIPHER_SPEC);
             goto f_err;
         }
 
@@ -760,8 +773,8 @@ static int dtls_get_reassembled_message(SSL *s, int *errtype, size_t *len)
 
     /* Handshake fails if message header is incomplete */
     if (readbytes != DTLS1_HM_HEADER_LENGTH) {
-        al = SSL_AD_UNEXPECTED_MESSAGE;
-        SSLerr(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
+        SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
+                 SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
         goto f_err;
     }
 
@@ -777,8 +790,8 @@ static int dtls_get_reassembled_message(SSL *s, int *errtype, size_t *len)
      * Fragments must not span records.
      */
     if (frag_len > RECORD_LAYER_get_rrec_length(&s->rlayer)) {
-        al = SSL_AD_ILLEGAL_PARAMETER;
-        SSLerr(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_BAD_LENGTH);
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+                 SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_BAD_LENGTH);
         goto f_err;
     }
 
@@ -817,15 +830,17 @@ static int dtls_get_reassembled_message(SSL *s, int *errtype, size_t *len)
             goto redo;
         } else {                /* Incorrectly formatted Hello request */
 
-            al = SSL_AD_UNEXPECTED_MESSAGE;
-            SSLerr(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE,
-                   SSL_R_UNEXPECTED_MESSAGE);
+            SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
+                     SSL_F_DTLS_GET_REASSEMBLED_MESSAGE,
+                     SSL_R_UNEXPECTED_MESSAGE);
             goto f_err;
         }
     }
 
-    if ((al = dtls1_preprocess_fragment(s, &msg_hdr)))
+    if (!dtls1_preprocess_fragment(s, &msg_hdr)) {
+        /* SSLfatal() already called */
         goto f_err;
+    }
 
     if (frag_len > 0) {
         unsigned char *p =
@@ -852,8 +867,8 @@ static int dtls_get_reassembled_message(SSL *s, int *errtype, size_t *len)
      * to fail
      */
     if (readbytes != frag_len) {
-        al = SSL_AD_ILLEGAL_PARAMETER;
-        SSLerr(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_BAD_LENGTH);
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+                 SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_BAD_LENGTH);
         goto f_err;
     }
 
@@ -867,7 +882,6 @@ static int dtls_get_reassembled_message(SSL *s, int *errtype, size_t *len)
     return 1;
 
  f_err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, al);
     s->init_num = 0;
     *len = 0;
     return 0;
@@ -888,8 +902,10 @@ int dtls_construct_change_cipher_spec(SSL *s, WPACKET *pkt)
         s->d1->next_handshake_write_seq++;
 
         if (!WPACKET_put_bytes_u16(pkt, s->d1->handshake_write_seq)) {
-            SSLerr(SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR);
-            ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC,
+                     ERR_R_INTERNAL_ERROR);
+            return 0;
         }
     }
 
@@ -903,8 +919,11 @@ WORK_STATE dtls_wait_for_dry(SSL *s)
 
     /* read app data until dry event */
     ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s));
-    if (ret < 0)
+    if (ret < 0) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS_WAIT_FOR_DRY,
+                 ERR_R_INTERNAL_ERROR);
         return WORK_ERROR;
+    }
 
     if (ret == 0) {
         s->s3->in_read_app_data = 2;
@@ -920,8 +939,9 @@ WORK_STATE dtls_wait_for_dry(SSL *s)
 int dtls1_read_failed(SSL *s, int code)
 {
     if (code > 0) {
-        SSLerr(SSL_F_DTLS1_READ_FAILED, ERR_R_INTERNAL_ERROR);
-        return 1;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_DTLS1_READ_FAILED, ERR_R_INTERNAL_ERROR);
+        return 0;
     }
 
     if (!dtls1_is_timer_expired(s)) {
@@ -1062,7 +1082,8 @@ int dtls1_retransmit_message(SSL *s, unsigned short seq, int *found)
 
     item = pqueue_find(s->d1->sent_messages, seq64be);
     if (item == NULL) {
-        SSLerr(SSL_F_DTLS1_RETRANSMIT_MESSAGE, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_RETRANSMIT_MESSAGE,
+                 ERR_R_INTERNAL_ERROR);
         *found = 0;
         return 0;
     }
diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c
index cb1fb7d..b8e094b 100644
--- a/ssl/statem/statem_lib.c
+++ b/ssl/statem/statem_lib.c
@@ -70,8 +70,10 @@ int tls_close_construct_packet(SSL *s, WPACKET *pkt, int htype)
 
 int tls_setup_handshake(SSL *s)
 {
-    if (!ssl3_init_finished_mac(s))
+    if (!ssl3_init_finished_mac(s)) {
+        /* SSLfatal() already called */
         return 0;
+    }
 
     /* Reset any extension flags */
     memset(s->ext.extflags, 0, sizeof(s->ext.extflags));
@@ -86,8 +88,8 @@ int tls_setup_handshake(SSL *s)
          * ClientHello.
          */
         if (ssl_get_min_max_version(s, &ver_min, &ver_max) != 0) {
-            SSLerr(SSL_F_TLS_SETUP_HANDSHAKE, ERR_R_INTERNAL_ERROR);
-            ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_SETUP_HANDSHAKE,
+                     ERR_R_INTERNAL_ERROR);
             return 0;
         }
         for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
@@ -104,10 +106,10 @@ int tls_setup_handshake(SSL *s)
                 break;
         }
         if (!ok) {
-            SSLerr(SSL_F_TLS_SETUP_HANDSHAKE, SSL_R_NO_CIPHERS_AVAILABLE);
+            SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_SETUP_HANDSHAKE,
+                     SSL_R_NO_CIPHERS_AVAILABLE);
             ERR_add_error_data(1, "No ciphers enabled for max supported "
                                   "SSL/TLS version");
-            ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
             return 0;
         }
         if (SSL_IS_FIRST_HANDSHAKE(s)) {
@@ -125,9 +127,8 @@ int tls_setup_handshake(SSL *s)
              * Server attempting to renegotiate with client that doesn't
              * support secure renegotiation.
              */
-            SSLerr(SSL_F_TLS_SETUP_HANDSHAKE,
-                   SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
-            ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+            SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_SETUP_HANDSHAKE,
+                     SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
             return 0;
         } else {
             /* N.B. s->ctx may not equal s->session_ctx */
@@ -195,6 +196,7 @@ static int get_cert_verify_tbs_data(SSL *s, unsigned char *tls13tbs,
             hashlen = s->cert_verify_hash_len;
         } else if (!ssl_handshake_hash(s, tls13tbs + TLS13_TBS_PREAMBLE_SIZE,
                                        EVP_MAX_MD_SIZE, &hashlen)) {
+            /* SSLfatal() already called */
             return 0;
         }
 
@@ -204,8 +206,11 @@ static int get_cert_verify_tbs_data(SSL *s, unsigned char *tls13tbs,
         size_t retlen;
 
         retlen = BIO_get_mem_data(s->s3->handshake_buffer, hdata);
-        if (retlen <= 0)
+        if (retlen <= 0) {
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_GET_CERT_VERIFY_TBS_DATA,
+                     ERR_R_INTERNAL_ERROR);
             return 0;
+        }
         *hdatalen = retlen;
     }
 
@@ -225,41 +230,47 @@ int tls_construct_cert_verify(SSL *s, WPACKET *pkt)
     const SIGALG_LOOKUP *lu = s->s3->tmp.sigalg;
 
     if (lu == NULL || s->s3->tmp.cert == NULL) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CERT_VERIFY, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
     }
     pkey = s->s3->tmp.cert->privatekey;
 
     if (pkey == NULL || !tls1_lookup_md(lu, &md)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CERT_VERIFY, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
     }
 
     mctx = EVP_MD_CTX_new();
     if (mctx == NULL) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CERT_VERIFY, ERR_R_MALLOC_FAILURE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
+                 ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
     /* Get the data to be signed */
     if (!get_cert_verify_tbs_data(s, tls13tbs, &hdata, &hdatalen)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CERT_VERIFY, ERR_R_INTERNAL_ERROR);
+        /* SSLfatal() already called */
         goto err;
     }
 
     if (SSL_USE_SIGALGS(s) && !WPACKET_put_bytes_u16(pkt, lu->sigalg)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CERT_VERIFY, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
     }
     siglen = EVP_PKEY_size(pkey);
     sig = OPENSSL_malloc(siglen);
     if (sig == NULL) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CERT_VERIFY, ERR_R_MALLOC_FAILURE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
+                 ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
     if (EVP_DigestSignInit(mctx, &pctx, md, NULL, pkey) <= 0) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CERT_VERIFY, ERR_R_EVP_LIB);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
+                 ERR_R_EVP_LIB);
         goto err;
     }
 
@@ -267,7 +278,8 @@ int tls_construct_cert_verify(SSL *s, WPACKET *pkt)
         if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0
             || EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx,
                                                 RSA_PSS_SALTLEN_DIGEST) <= 0) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_CERT_VERIFY, ERR_R_EVP_LIB);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
+                     ERR_R_EVP_LIB);
             goto err;
         }
     }
@@ -278,11 +290,13 @@ int tls_construct_cert_verify(SSL *s, WPACKET *pkt)
                                 s->session->master_key)
             || EVP_DigestSignFinal(mctx, sig, &siglen) <= 0) {
 
-            SSLerr(SSL_F_TLS_CONSTRUCT_CERT_VERIFY, ERR_R_EVP_LIB);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
+                     ERR_R_EVP_LIB);
             goto err;
         }
     } else if (EVP_DigestSign(mctx, sig, &siglen, hdata, hdatalen) <= 0) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CERT_VERIFY, ERR_R_EVP_LIB);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
+                 ERR_R_EVP_LIB);
         goto err;
     }
 
@@ -298,13 +312,16 @@ int tls_construct_cert_verify(SSL *s, WPACKET *pkt)
 #endif
 
     if (!WPACKET_sub_memcpy_u16(pkt, sig, siglen)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CERT_VERIFY, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
     }
 
     /* Digest cached records and discard handshake buffer */
-    if (!ssl3_digest_cached_records(s, 0))
+    if (!ssl3_digest_cached_records(s, 0)) {
+        /* SSLfatal() already called */
         goto err;
+    }
 
     OPENSSL_free(sig);
     EVP_MD_CTX_free(mctx);
@@ -312,7 +329,6 @@ int tls_construct_cert_verify(SSL *s, WPACKET *pkt)
  err:
     OPENSSL_free(sig);
     EVP_MD_CTX_free(mctx);
-    ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
     return 0;
 }
 
@@ -323,7 +339,6 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
 #ifndef OPENSSL_NO_GOST
     unsigned char *gost_data = NULL;
 #endif
-    int al = SSL_AD_INTERNAL_ERROR;
     MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR;
     int j;
     unsigned int len;
@@ -336,49 +351,50 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
     EVP_PKEY_CTX *pctx = NULL;
 
     if (mctx == NULL) {
-        SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_MALLOC_FAILURE);
-        goto f_err;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
+                 ERR_R_MALLOC_FAILURE);
+        goto err;
     }
 
     peer = s->session->peer;
     pkey = X509_get0_pubkey(peer);
-    if (pkey == NULL)
-        goto f_err;
+    if (pkey == NULL) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
+                 ERR_R_INTERNAL_ERROR);
+        goto err;
+    }
 
     if (ssl_cert_lookup_by_pkey(pkey, NULL) == NULL) {
-        SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY,
-               SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE);
-        al = SSL_AD_ILLEGAL_PARAMETER;
-        goto f_err;
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_CERT_VERIFY,
+                 SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE);
+        goto err;
     }
 
     if (SSL_USE_SIGALGS(s)) {
-        int rv;
         unsigned int sigalg;
 
         if (!PACKET_get_net_2(pkt, &sigalg)) {
-            al = SSL_AD_DECODE_ERROR;
-            goto f_err;
+            SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
+                     SSL_R_BAD_PACKET);
+            goto err;
         }
-        rv = tls12_check_peer_sigalg(s, sigalg, pkey);
-        if (rv == -1) {
-            goto f_err;
-        } else if (rv == 0) {
-            al = SSL_AD_DECODE_ERROR;
-            goto f_err;
+        if (tls12_check_peer_sigalg(s, sigalg, pkey) <= 0) {
+            /* SSLfatal() already called */
+            goto err;
         }
 #ifdef SSL_DEBUG
         fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));
 #endif
     } else if (!tls1_set_peer_legacy_sigalg(s, pkey)) {
-            al = SSL_AD_INTERNAL_ERROR;
-            goto f_err;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
+                     ERR_R_INTERNAL_ERROR);
+            goto err;
     }
 
     if (!tls1_lookup_md(s->s3->tmp.peer_sigalg, &md)) {
-        SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_INTERNAL_ERROR);
-        al = SSL_AD_INTERNAL_ERROR;
-        goto f_err;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
+                 ERR_R_INTERNAL_ERROR);
+        goto err;
     }
 
     /* Check for broken implementations of GOST ciphersuites */
@@ -397,35 +413,36 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
     } else
 #endif
     if (!PACKET_get_net_2(pkt, &len)) {
-        SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_LENGTH_MISMATCH);
-        al = SSL_AD_DECODE_ERROR;
-        goto f_err;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
+                 SSL_R_LENGTH_MISMATCH);
+        goto err;
     }
 
     j = EVP_PKEY_size(pkey);
     if (((int)len > j) || ((int)PACKET_remaining(pkt) > j)
         || (PACKET_remaining(pkt) == 0)) {
-        SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_WRONG_SIGNATURE_SIZE);
-        al = SSL_AD_DECODE_ERROR;
-        goto f_err;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
+                 SSL_R_WRONG_SIGNATURE_SIZE);
+        goto err;
     }
     if (!PACKET_get_bytes(pkt, &data, len)) {
-        SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_LENGTH_MISMATCH);
-        al = SSL_AD_DECODE_ERROR;
-        goto f_err;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
+                 SSL_R_LENGTH_MISMATCH);
+        goto err;
     }
 
     if (!get_cert_verify_tbs_data(s, tls13tbs, &hdata, &hdatalen)) {
-        SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_INTERNAL_ERROR);
-        goto f_err;
+        /* SSLfatal() already called */
+        goto err;
     }
 
 #ifdef SSL_DEBUG
     fprintf(stderr, "Using client verify alg %s\n", EVP_MD_name(md));
 #endif
     if (EVP_DigestVerifyInit(mctx, &pctx, md, NULL, pkey) <= 0) {
-        SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_EVP_LIB);
-        goto f_err;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
+                 ERR_R_EVP_LIB);
+        goto err;
     }
 #ifndef OPENSSL_NO_GOST
     {
@@ -434,8 +451,9 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
             || pktype == NID_id_GostR3410_2012_256
             || pktype == NID_id_GostR3410_2012_512) {
             if ((gost_data = OPENSSL_malloc(len)) == NULL) {
-                SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_MALLOC_FAILURE);
-                goto f_err;
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_MALLOC_FAILURE);
+                goto err;
             }
             BUF_reverse(gost_data, data, len);
             data = gost_data;
@@ -447,8 +465,9 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
         if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0
             || EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx,
                                                 RSA_PSS_SALTLEN_DIGEST) <= 0) {
-            SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_EVP_LIB);
-            goto f_err;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
+                     ERR_R_EVP_LIB);
+            goto err;
         }
     }
     if (s->version == SSL3_VERSION) {
@@ -456,29 +475,26 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
                 || !EVP_MD_CTX_ctrl(mctx, EVP_CTRL_SSL3_MASTER_SECRET,
                                     (int)s->session->master_key_length,
                                     s->session->master_key)) {
-            SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_EVP_LIB);
-            goto f_err;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
+                     ERR_R_EVP_LIB);
+            goto err;
         }
         if (EVP_DigestVerifyFinal(mctx, data, len) <= 0) {
-            al = SSL_AD_DECRYPT_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_BAD_SIGNATURE);
-            goto f_err;
+            SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
+                     SSL_R_BAD_SIGNATURE);
+            goto err;
         }
     } else {
         j = EVP_DigestVerify(mctx, data, len, hdata, hdatalen);
         if (j <= 0) {
-            al = SSL_AD_DECRYPT_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_BAD_SIGNATURE);
-            goto f_err;
+            SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
+                     SSL_R_BAD_SIGNATURE);
+            goto err;
         }
     }
 
     ret = MSG_PROCESS_CONTINUE_READING;
-    if (0) {
- f_err:
-        ssl3_send_alert(s, SSL3_AL_FATAL, al);
-        ossl_statem_set_error(s);
-    }
+ err:
     BIO_free(s->s3->handshake_buffer);
     s->s3->handshake_buffer = NULL;
     EVP_MD_CTX_free(mctx);
@@ -506,13 +522,8 @@ int tls_construct_finished(SSL *s, WPACKET *pkt)
             && !s->server
             && s->s3->tmp.cert_req == 0
             && (!s->method->ssl3_enc->change_cipher_state(s,
-                    SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_WRITE))) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_FINISHED, SSL_R_CANNOT_CHANGE_CIPHER);
-        /*
-         * This is a fatal error, which leaves
-         * enc_write_ctx in an inconsistent state
-         * and thus ssl3_send_alert may crash.
-         */
+                    SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_WRITE))) {;
+        /* SSLfatal() already called */
         return 0;
     }
 
@@ -528,15 +539,16 @@ int tls_construct_finished(SSL *s, WPACKET *pkt)
                                                           sender, slen,
                                                           s->s3->tmp.finish_md);
     if (finish_md_len == 0) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_FINISHED, ERR_R_INTERNAL_ERROR);
-        goto err;
+        /* SSLfatal() already called */
+        return 0;
     }
 
     s->s3->tmp.finish_md_len = finish_md_len;
 
     if (!WPACKET_memcpy(pkt, s->s3->tmp.finish_md, finish_md_len)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_FINISHED, ERR_R_INTERNAL_ERROR);
-        goto err;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_FINISHED,
+                 ERR_R_INTERNAL_ERROR);
+        return 0;
     }
 
     /*
@@ -546,16 +558,17 @@ int tls_construct_finished(SSL *s, WPACKET *pkt)
     if (!SSL_IS_TLS13(s) && !ssl_log_secret(s, MASTER_SECRET_LABEL,
                                             s->session->master_key,
                                             s->session->master_key_length)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_FINISHED, ERR_R_INTERNAL_ERROR);
-        goto err;
+        /* SSLfatal() already called */
+        return 0;
     }
 
     /*
      * Copy the finished so we can use it for renegotiation checks
      */
     if (!ossl_assert(finish_md_len <= EVP_MAX_MD_SIZE)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_FINISHED, ERR_R_INTERNAL_ERROR);
-        goto err;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_FINISHED,
+                 ERR_R_INTERNAL_ERROR);
+        return 0;
     }
     if (!s->server) {
         memcpy(s->s3->previous_client_finished, s->s3->tmp.finish_md,
@@ -568,36 +581,29 @@ int tls_construct_finished(SSL *s, WPACKET *pkt)
     }
 
     return 1;
- err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-    return 0;
 }
 
 int tls_construct_key_update(SSL *s, WPACKET *pkt)
 {
     if (!WPACKET_put_bytes_u8(pkt, s->key_update)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_KEY_UPDATE, ERR_R_INTERNAL_ERROR);
-        goto err;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_KEY_UPDATE,
+                 ERR_R_INTERNAL_ERROR);
+        return 0;
     }
 
     s->key_update = SSL_KEY_UPDATE_NONE;
     return 1;
-
- err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-    return 0;
 }
 
 MSG_PROCESS_RETURN tls_process_key_update(SSL *s, PACKET *pkt)
 {
-    int al;
     unsigned int updatetype;
 
     s->key_update_count++;
     if (s->key_update_count > MAX_KEY_UPDATE_MESSAGES) {
-        al = SSL_AD_ILLEGAL_PARAMETER;
-        SSLerr(SSL_F_TLS_PROCESS_KEY_UPDATE, SSL_R_TOO_MANY_KEY_UPDATES);
-        goto err;
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_KEY_UPDATE,
+                 SSL_R_TOO_MANY_KEY_UPDATES);
+        return MSG_PROCESS_ERROR;
     }
 
     /*
@@ -605,16 +611,16 @@ MSG_PROCESS_RETURN tls_process_key_update(SSL *s, PACKET *pkt)
      * be on a record boundary.
      */
     if (RECORD_LAYER_processed_read_pending(&s->rlayer)) {
-        al = SSL_AD_UNEXPECTED_MESSAGE;
-        SSLerr(SSL_F_TLS_PROCESS_KEY_UPDATE, SSL_R_NOT_ON_RECORD_BOUNDARY);
-        goto err;
+        SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_KEY_UPDATE,
+                 SSL_R_NOT_ON_RECORD_BOUNDARY);
+        return MSG_PROCESS_ERROR;
     }
 
     if (!PACKET_get_1(pkt, &updatetype)
             || PACKET_remaining(pkt) != 0) {
-        al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_KEY_UPDATE, SSL_R_BAD_KEY_UPDATE);
-        goto err;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_UPDATE,
+                 SSL_R_BAD_KEY_UPDATE);
+        return MSG_PROCESS_ERROR;
     }
 
     /*
@@ -623,9 +629,9 @@ MSG_PROCESS_RETURN tls_process_key_update(SSL *s, PACKET *pkt)
      */
     if (updatetype != SSL_KEY_UPDATE_NOT_REQUESTED
             && updatetype != SSL_KEY_UPDATE_REQUESTED) {
-        al = SSL_AD_ILLEGAL_PARAMETER;
-        SSLerr(SSL_F_TLS_PROCESS_KEY_UPDATE, SSL_R_BAD_KEY_UPDATE);
-        goto err;
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_KEY_UPDATE,
+                 SSL_R_BAD_KEY_UPDATE);
+        return MSG_PROCESS_ERROR;
     }
 
     /*
@@ -637,16 +643,11 @@ MSG_PROCESS_RETURN tls_process_key_update(SSL *s, PACKET *pkt)
         s->key_update = SSL_KEY_UPDATE_NOT_REQUESTED;
 
     if (!tls13_update_key(s, 0)) {
-        al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_KEY_UPDATE, ERR_R_INTERNAL_ERROR);
-        goto err;
+        /* SSLfatal() already called */
+        return MSG_PROCESS_ERROR;
     }
 
     return MSG_PROCESS_FINISHED_READING;
- err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, al);
-    ossl_statem_set_error(s);
-    return MSG_PROCESS_ERROR;
 }
 
 #ifndef OPENSSL_NO_NEXTPROTONEG
@@ -681,7 +682,6 @@ static void ssl3_take_mac(SSL *s)
 
 MSG_PROCESS_RETURN tls_process_change_cipher_spec(SSL *s, PACKET *pkt)
 {
-    int al;
     size_t remain;
 
     remain = PACKET_remaining(pkt);
@@ -695,32 +695,32 @@ MSG_PROCESS_RETURN tls_process_change_cipher_spec(SSL *s, PACKET *pkt)
              && remain != DTLS1_CCS_HEADER_LENGTH + 1)
             || (s->version != DTLS1_BAD_VER
                 && remain != DTLS1_CCS_HEADER_LENGTH - 1)) {
-            al = SSL_AD_DECODE_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC,
-                   SSL_R_BAD_CHANGE_CIPHER_SPEC);
-            goto f_err;
+            SSLfatal(s, SSL_AD_DECODE_ERROR,
+                     SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC,
+                    SSL_R_BAD_CHANGE_CIPHER_SPEC);
+            return MSG_PROCESS_ERROR;
         }
     } else {
         if (remain != 0) {
-            al = SSL_AD_DECODE_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC,
-                   SSL_R_BAD_CHANGE_CIPHER_SPEC);
-            goto f_err;
+            SSLfatal(s, SSL_AD_DECODE_ERROR,
+                     SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC,
+                     SSL_R_BAD_CHANGE_CIPHER_SPEC);
+            return MSG_PROCESS_ERROR;
         }
     }
 
     /* Check we have a cipher to change to */
     if (s->s3->tmp.new_cipher == NULL) {
-        al = SSL_AD_UNEXPECTED_MESSAGE;
-        SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, SSL_R_CCS_RECEIVED_EARLY);
-        goto f_err;
+        SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
+                 SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, SSL_R_CCS_RECEIVED_EARLY);
+        return MSG_PROCESS_ERROR;
     }
 
     s->s3->change_cipher_spec = 1;
     if (!ssl3_do_change_cipher_spec(s)) {
-        al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR);
-        goto f_err;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC,
+                 ERR_R_INTERNAL_ERROR);
+        return MSG_PROCESS_ERROR;
     }
 
     if (SSL_IS_DTLS(s)) {
@@ -740,15 +740,10 @@ MSG_PROCESS_RETURN tls_process_change_cipher_spec(SSL *s, PACKET *pkt)
     }
 
     return MSG_PROCESS_CONTINUE_READING;
- f_err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, al);
-    ossl_statem_set_error(s);
-    return MSG_PROCESS_ERROR;
 }
 
 MSG_PROCESS_RETURN tls_process_finished(SSL *s, PACKET *pkt)
 {
-    int al = SSL_AD_INTERNAL_ERROR;
     size_t md_len;
 
 
@@ -761,41 +756,41 @@ MSG_PROCESS_RETURN tls_process_finished(SSL *s, PACKET *pkt)
      * message must be on a record boundary.
      */
     if (SSL_IS_TLS13(s) && RECORD_LAYER_processed_read_pending(&s->rlayer)) {
-        al = SSL_AD_UNEXPECTED_MESSAGE;
-        SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_NOT_ON_RECORD_BOUNDARY);
-        goto f_err;
+        SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_FINISHED,
+                 SSL_R_NOT_ON_RECORD_BOUNDARY);
+        return MSG_PROCESS_ERROR;
     }
 
     /* If this occurs, we have missed a message */
     if (!SSL_IS_TLS13(s) && !s->s3->change_cipher_spec) {
-        al = SSL_AD_UNEXPECTED_MESSAGE;
-        SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_GOT_A_FIN_BEFORE_A_CCS);
-        goto f_err;
+        SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_FINISHED,
+                 SSL_R_GOT_A_FIN_BEFORE_A_CCS);
+        return MSG_PROCESS_ERROR;
     }
     s->s3->change_cipher_spec = 0;
 
     md_len = s->s3->tmp.peer_finish_md_len;
 
     if (md_len != PACKET_remaining(pkt)) {
-        al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_BAD_DIGEST_LENGTH);
-        goto f_err;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_FINISHED,
+                 SSL_R_BAD_DIGEST_LENGTH);
+        return MSG_PROCESS_ERROR;
     }
 
     if (CRYPTO_memcmp(PACKET_data(pkt), s->s3->tmp.peer_finish_md,
                       md_len) != 0) {
-        al = SSL_AD_DECRYPT_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_DIGEST_CHECK_FAILED);
-        goto f_err;
+        SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_FINISHED,
+                 SSL_R_DIGEST_CHECK_FAILED);
+        return MSG_PROCESS_ERROR;
     }
 
     /*
      * Copy the finished so we can use it for renegotiation checks
      */
     if (!ossl_assert(md_len <= EVP_MAX_MD_SIZE)) {
-        al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_FINISHED, ERR_R_INTERNAL_ERROR);
-        goto f_err;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_FINISHED,
+                 ERR_R_INTERNAL_ERROR);
+        return MSG_PROCESS_ERROR;
     }
     if (s->server) {
         memcpy(s->s3->previous_client_finished, s->s3->tmp.peer_finish_md,
@@ -815,38 +810,36 @@ MSG_PROCESS_RETURN tls_process_finished(SSL *s, PACKET *pkt)
         if (s->server) {
             if (!s->method->ssl3_enc->change_cipher_state(s,
                     SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_SERVER_READ)) {
-                SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_CANNOT_CHANGE_CIPHER);
-                goto f_err;
+                /* SSLfatal() already called */
+                return MSG_PROCESS_ERROR;
             }
         } else {
             if (!s->method->ssl3_enc->generate_master_secret(s,
                     s->master_secret, s->handshake_secret, 0,
                     &s->session->master_key_length)) {
-                SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_CANNOT_CHANGE_CIPHER);
-                goto f_err;
+                /* SSLfatal() already called */
+                return MSG_PROCESS_ERROR;
             }
             if (!s->method->ssl3_enc->change_cipher_state(s,
                     SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_CLIENT_READ)) {
-                SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_CANNOT_CHANGE_CIPHER);
-                goto f_err;
+                /* SSLfatal() already called */
+                return MSG_PROCESS_ERROR;
+            }
+            if (!tls_process_initial_server_flight(s)) {
+                /* SSLfatal() already called */
+                return MSG_PROCESS_ERROR;
             }
-            if (!tls_process_initial_server_flight(s, &al))
-                goto f_err;
         }
     }
 
     return MSG_PROCESS_FINISHED_READING;
- f_err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, al);
-    ossl_statem_set_error(s);
-    return MSG_PROCESS_ERROR;
 }
 
 int tls_construct_change_cipher_spec(SSL *s, WPACKET *pkt)
 {
     if (!WPACKET_put_bytes_u8(pkt, SSL3_MT_CCS)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR);
-        ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
@@ -854,42 +847,42 @@ int tls_construct_change_cipher_spec(SSL *s, WPACKET *pkt)
 }
 
 /* Add a certificate to the WPACKET */
-static int ssl_add_cert_to_wpacket(SSL *s, WPACKET *pkt, X509 *x, int chain,
-                                   int *al)
+static int ssl_add_cert_to_wpacket(SSL *s, WPACKET *pkt, X509 *x, int chain)
 {
     int len;
     unsigned char *outbytes;
 
     len = i2d_X509(x, NULL);
     if (len < 0) {
-        SSLerr(SSL_F_SSL_ADD_CERT_TO_WPACKET, ERR_R_BUF_LIB);
-        *al = SSL_AD_INTERNAL_ERROR;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_TO_WPACKET,
+                 ERR_R_BUF_LIB);
         return 0;
     }
     if (!WPACKET_sub_allocate_bytes_u24(pkt, len, &outbytes)
             || i2d_X509(x, &outbytes) != len) {
-        SSLerr(SSL_F_SSL_ADD_CERT_TO_WPACKET, ERR_R_INTERNAL_ERROR);
-        *al = SSL_AD_INTERNAL_ERROR;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_TO_WPACKET,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
     if (SSL_IS_TLS13(s)
             && !tls_construct_extensions(s, pkt, SSL_EXT_TLS1_3_CERTIFICATE, x,
-                                         chain, al))
+                                         chain)) {
+        /* SSLfatal() already called */
         return 0;
+    }
 
     return 1;
 }
 
 /* Add certificate chain to provided WPACKET */
-static int ssl_add_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk, int *al)
+static int ssl_add_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk)
 {
     int i, chain_count;
     X509 *x;
     STACK_OF(X509) *extra_certs;
     STACK_OF(X509) *chain = NULL;
     X509_STORE *chain_store;
-    int tmpal = SSL_AD_INTERNAL_ERROR;
 
     if (cpk == NULL || cpk->x509 == NULL)
         return 1;
@@ -915,13 +908,15 @@ static int ssl_add_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk, int *al)
         X509_STORE_CTX *xs_ctx = X509_STORE_CTX_new();
 
         if (xs_ctx == NULL) {
-            SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, ERR_R_MALLOC_FAILURE);
-            goto err;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN,
+                     ERR_R_MALLOC_FAILURE);
+            return 0;
         }
         if (!X509_STORE_CTX_init(xs_ctx, chain_store, x, NULL)) {
             X509_STORE_CTX_free(xs_ctx);
-            SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, ERR_R_X509_LIB);
-            goto err;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN,
+                     ERR_R_X509_LIB);
+            return 0;
         }
         /*
          * It is valid for the chain not to be complete (because normally we
@@ -942,52 +937,58 @@ static int ssl_add_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk, int *al)
             SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, SSL_R_CA_MD_TOO_WEAK);
 #endif
             X509_STORE_CTX_free(xs_ctx);
-            SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, i);
-            goto err;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN, i);
+            return 0;
         }
         chain_count = sk_X509_num(chain);
         for (i = 0; i < chain_count; i++) {
             x = sk_X509_value(chain, i);
 
-            if (!ssl_add_cert_to_wpacket(s, pkt, x, i, &tmpal)) {
+            if (!ssl_add_cert_to_wpacket(s, pkt, x, i)) {
+                /* SSLfatal() already called */
                 X509_STORE_CTX_free(xs_ctx);
-                goto err;
+                return 0;
             }
         }
         X509_STORE_CTX_free(xs_ctx);
     } else {
         i = ssl_security_cert_chain(s, extra_certs, x, 0);
         if (i != 1) {
-            SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, i);
-            goto err;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN, i);
+            return 0;
+        }
+        if (!ssl_add_cert_to_wpacket(s, pkt, x, 0)) {
+            /* SSLfatal() already called */
+            return 0;
         }
-        if (!ssl_add_cert_to_wpacket(s, pkt, x, 0, &tmpal))
-            goto err;
         for (i = 0; i < sk_X509_num(extra_certs); i++) {
             x = sk_X509_value(extra_certs, i);
-            if (!ssl_add_cert_to_wpacket(s, pkt, x, i + 1, &tmpal))
-                goto err;
+            if (!ssl_add_cert_to_wpacket(s, pkt, x, i + 1)) {
+                /* SSLfatal() already called */
+                return 0;
+            }
         }
     }
     return 1;
-
- err:
-    *al = tmpal;
-    return 0;
 }
 
-unsigned long ssl3_output_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk,
-                                     int *al)
+unsigned long ssl3_output_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk)
 {
-    int tmpal = SSL_AD_INTERNAL_ERROR;
+    if (!WPACKET_start_sub_packet_u24(pkt)) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_OUTPUT_CERT_CHAIN,
+                 ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
 
-    if (!WPACKET_start_sub_packet_u24(pkt)
-            || !ssl_add_cert_chain(s, pkt, cpk, &tmpal)
-            || !WPACKET_close(pkt)) {
-        SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN, ERR_R_INTERNAL_ERROR);
-        *al = tmpal;
+    if (!ssl_add_cert_chain(s, pkt, cpk))
+        return 0;
+
+    if (!WPACKET_close(pkt)) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_OUTPUT_CERT_CHAIN,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
     }
+
     return 1;
 }
 
@@ -1019,8 +1020,11 @@ WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs)
             BUF_MEM_free(s->init_buf);
             s->init_buf = NULL;
         }
-        if (!ssl_free_wbio_buffer(s))
+        if (!ssl_free_wbio_buffer(s)) {
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_FINISH_HANDSHAKE,
+                     ERR_R_INTERNAL_ERROR);
             return WORK_ERROR;
+        }
         s->init_num = 0;
     }
 
@@ -1086,7 +1090,7 @@ WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs)
 int tls_get_message_header(SSL *s, int *mt)
 {
     /* s->init_num < SSL3_HM_HEADER_LENGTH */
-    int skip_message, i, recvd_type, al;
+    int skip_message, i, recvd_type;
     unsigned char *p;
     size_t l, readbytes;
 
@@ -1108,10 +1112,10 @@ int tls_get_message_header(SSL *s, int *mt)
                  * in the middle of a handshake message.
                  */
                 if (s->init_num != 0 || readbytes != 1 || p[0] != SSL3_MT_CCS) {
-                    al = SSL_AD_UNEXPECTED_MESSAGE;
-                    SSLerr(SSL_F_TLS_GET_MESSAGE_HEADER,
-                           SSL_R_BAD_CHANGE_CIPHER_SPEC);
-                    goto f_err;
+                    SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
+                             SSL_F_TLS_GET_MESSAGE_HEADER,
+                             SSL_R_BAD_CHANGE_CIPHER_SPEC);
+                    return 0;
                 }
                 s->s3->tmp.message_type = *mt = SSL3_MT_CHANGE_CIPHER_SPEC;
                 s->init_num = readbytes - 1;
@@ -1119,9 +1123,10 @@ int tls_get_message_header(SSL *s, int *mt)
                 s->s3->tmp.message_size = readbytes;
                 return 1;
             } else if (recvd_type != SSL3_RT_HANDSHAKE) {
-                al = SSL_AD_UNEXPECTED_MESSAGE;
-                SSLerr(SSL_F_TLS_GET_MESSAGE_HEADER, SSL_R_CCS_RECEIVED_EARLY);
-                goto f_err;
+                SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
+                         SSL_F_TLS_GET_MESSAGE_HEADER,
+                         SSL_R_CCS_RECEIVED_EARLY);
+                return 0;
             }
             s->init_num += readbytes;
         }
@@ -1169,9 +1174,9 @@ int tls_get_message_header(SSL *s, int *mt)
         n2l3(p, l);
         /* BUF_MEM_grow takes an 'int' parameter */
         if (l > (INT_MAX - SSL3_HM_HEADER_LENGTH)) {
-            al = SSL_AD_ILLEGAL_PARAMETER;
-            SSLerr(SSL_F_TLS_GET_MESSAGE_HEADER, SSL_R_EXCESSIVE_MESSAGE_SIZE);
-            goto f_err;
+            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_GET_MESSAGE_HEADER,
+                     SSL_R_EXCESSIVE_MESSAGE_SIZE);
+            return 0;
         }
         s->s3->tmp.message_size = l;
 
@@ -1180,9 +1185,6 @@ int tls_get_message_header(SSL *s, int *mt)
     }
 
     return 1;
- f_err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, al);
-    return 0;
 }
 
 int tls_get_message_body(SSL *s, size_t *len)
@@ -1224,8 +1226,7 @@ int tls_get_message_body(SSL *s, size_t *len)
     if (RECORD_LAYER_is_sslv2_record(&s->rlayer)) {
         if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
                              s->init_num)) {
-            SSLerr(SSL_F_TLS_GET_MESSAGE_BODY, ERR_R_EVP_LIB);
-            ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+            /* SSLfatal() already called */
             *len = 0;
             return 0;
         }
@@ -1240,8 +1241,7 @@ int tls_get_message_body(SSL *s, size_t *len)
         if (s->s3->tmp.message_type != SSL3_MT_HELLO_RETRY_REQUEST
                 && !ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
                                     s->init_num + SSL3_HM_HEADER_LENGTH)) {
-            SSLerr(SSL_F_TLS_GET_MESSAGE_BODY, ERR_R_EVP_LIB);
-            ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+            /* SSLfatal() already called */
             *len = 0;
             return 0;
         }
@@ -1740,11 +1740,10 @@ int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello, DOWNGRADE *dgrd)
  * @s: client SSL handle.
  * @version: The proposed version from the server's HELLO.
  * @checkdgrd: Whether to check the downgrade sentinels in the server_random
- * @al: Where to store any alert value that may be generated
  *
- * Returns 0 on success or an SSL error reason number on failure.
+ * Returns 1 on success or 0 on error.
  */
-int ssl_choose_client_version(SSL *s, int version, int checkdgrd, int *al)
+int ssl_choose_client_version(SSL *s, int version, int checkdgrd)
 {
     const version_info *vent;
     const version_info *table;
@@ -1755,15 +1754,18 @@ int ssl_choose_client_version(SSL *s, int version, int checkdgrd, int *al)
         version = TLS1_3_VERSION;
 
     if (s->hello_retry_request && version != TLS1_3_VERSION) {
-        *al = SSL_AD_PROTOCOL_VERSION;
-        return SSL_R_WRONG_SSL_VERSION;
+        SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_SSL_CHOOSE_CLIENT_VERSION,
+                 SSL_R_WRONG_SSL_VERSION);
+        return 0;
     }
 
     switch (s->method->version) {
     default:
         if (version != s->version) {
-            *al = SSL_AD_PROTOCOL_VERSION;
-            return SSL_R_WRONG_SSL_VERSION;
+            SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
+                     SSL_F_SSL_CHOOSE_CLIENT_VERSION,
+                     SSL_R_WRONG_SSL_VERSION);
+            return 0;
         }
         /*
          * If this SSL handle is not from a version flexible method we don't
@@ -1772,7 +1774,7 @@ int ssl_choose_client_version(SSL *s, int version, int checkdgrd, int *al)
          * versions they don't want.  If not, then easy to fix, just return
          * ssl_method_error(s, s->method)
          */
-        return 0;
+        return 1;
     case TLS_ANY_VERSION:
         table = tls_version_table;
         break;
@@ -1795,8 +1797,9 @@ int ssl_choose_client_version(SSL *s, int version, int checkdgrd, int *al)
         err = ssl_method_error(s, method);
         if (err != 0) {
             if (version == vent->version) {
-                *al = SSL_AD_PROTOCOL_VERSION;
-                return err;
+                SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
+                         SSL_F_SSL_CHOOSE_CLIENT_VERSION, err);
+                return 0;
             }
 
             continue;
@@ -1815,8 +1818,10 @@ int ssl_choose_client_version(SSL *s, int version, int checkdgrd, int *al)
                            s->s3->server_random + SSL3_RANDOM_SIZE
                                                 - sizeof(tls12downgrade),
                            sizeof(tls12downgrade)) == 0) {
-                    *al = SSL_AD_ILLEGAL_PARAMETER;
-                    return SSL_R_INAPPROPRIATE_FALLBACK;
+                    SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+                             SSL_F_SSL_CHOOSE_CLIENT_VERSION,
+                             SSL_R_INAPPROPRIATE_FALLBACK);
+                    return 0;
                 }
             } else if (!SSL_IS_DTLS(s)
                        && version < TLS1_2_VERSION
@@ -1825,8 +1830,10 @@ int ssl_choose_client_version(SSL *s, int version, int checkdgrd, int *al)
                            s->s3->server_random + SSL3_RANDOM_SIZE
                                                 - sizeof(tls11downgrade),
                            sizeof(tls11downgrade)) == 0) {
-                    *al = SSL_AD_ILLEGAL_PARAMETER;
-                    return SSL_R_INAPPROPRIATE_FALLBACK;
+                    SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+                             SSL_F_SSL_CHOOSE_CLIENT_VERSION,
+                             SSL_R_INAPPROPRIATE_FALLBACK);
+                    return 0;
                 }
             }
         }
@@ -1834,11 +1841,12 @@ int ssl_choose_client_version(SSL *s, int version, int checkdgrd, int *al)
 
         s->method = method;
         s->version = version;
-        return 0;
+        return 1;
     }
 
-    *al = SSL_AD_PROTOCOL_VERSION;
-    return SSL_R_UNSUPPORTED_PROTOCOL;
+    SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_SSL_CHOOSE_CLIENT_VERSION,
+             SSL_R_UNSUPPORTED_PROTOCOL);
+    return 0;
 }
 
 /*
@@ -2010,20 +2018,22 @@ int create_synthetic_message_hash(SSL *s)
     /* Get the hash of the initial ClientHello */
     if (!ssl3_digest_cached_records(s, 0)
             || !ssl_handshake_hash(s, hashval, sizeof(hashval), &hashlen)) {
-        SSLerr(SSL_F_CREATE_SYNTHETIC_MESSAGE_HASH, ERR_R_INTERNAL_ERROR);
+        /* SSLfatal() already called */
         return 0;
     }
 
     /* Reinitialise the transcript hash */
-    if (!ssl3_init_finished_mac(s))
+    if (!ssl3_init_finished_mac(s)) {
+        /* SSLfatal() already called */
         return 0;
+    }
 
     /* Inject the synthetic message_hash message */
     msghdr[0] = SSL3_MT_MESSAGE_HASH;
     msghdr[SSL3_HM_HEADER_LENGTH - 1] = (unsigned char)hashlen;
     if (!ssl3_finish_mac(s, msghdr, SSL3_HM_HEADER_LENGTH)
             || !ssl3_finish_mac(s, hashval, hashlen)) {
-        SSLerr(SSL_F_CREATE_SYNTHETIC_MESSAGE_HASH, ERR_R_INTERNAL_ERROR);
+        /* SSLfatal() already called */
         return 0;
     }
 
@@ -2035,21 +2045,22 @@ static int ca_dn_cmp(const X509_NAME *const *a, const X509_NAME *const *b)
     return X509_NAME_cmp(*a, *b);
 }
 
-int parse_ca_names(SSL *s, PACKET *pkt, int *al)
+int parse_ca_names(SSL *s, PACKET *pkt)
 {
     STACK_OF(X509_NAME) *ca_sk = sk_X509_NAME_new(ca_dn_cmp);
     X509_NAME *xn = NULL;
     PACKET cadns;
 
     if (ca_sk == NULL) {
-        SSLerr(SSL_F_PARSE_CA_NAMES, ERR_R_MALLOC_FAILURE);
-        goto decerr;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_PARSE_CA_NAMES,
+                 ERR_R_MALLOC_FAILURE);
+        goto err;
     }
     /* get the CA RDNs */
     if (!PACKET_get_length_prefixed_2(pkt, &cadns)) {
-        *al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_PARSE_CA_NAMES, SSL_R_LENGTH_MISMATCH);
-        goto decerr;
+        SSLfatal(s, SSL_AD_DECODE_ERROR,SSL_F_PARSE_CA_NAMES,
+                 SSL_R_LENGTH_MISMATCH);
+        goto err;
     }
 
     while (PACKET_remaining(&cadns)) {
@@ -2058,23 +2069,26 @@ int parse_ca_names(SSL *s, PACKET *pkt, int *al)
 
         if (!PACKET_get_net_2(&cadns, &name_len)
             || !PACKET_get_bytes(&cadns, &namebytes, name_len)) {
-            SSLerr(SSL_F_PARSE_CA_NAMES, SSL_R_LENGTH_MISMATCH);
-            goto decerr;
+            SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_PARSE_CA_NAMES,
+                     SSL_R_LENGTH_MISMATCH);
+            goto err;
         }
 
         namestart = namebytes;
         if ((xn = d2i_X509_NAME(NULL, &namebytes, name_len)) == NULL) {
-            SSLerr(SSL_F_PARSE_CA_NAMES, ERR_R_ASN1_LIB);
-            goto decerr;
+            SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_PARSE_CA_NAMES,
+                     ERR_R_ASN1_LIB);
+            goto err;
         }
         if (namebytes != (namestart + name_len)) {
-            SSLerr(SSL_F_PARSE_CA_NAMES, SSL_R_CA_DN_LENGTH_MISMATCH);
-            goto decerr;
+            SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_PARSE_CA_NAMES,
+                     SSL_R_CA_DN_LENGTH_MISMATCH);
+            goto err;
         }
 
         if (!sk_X509_NAME_push(ca_sk, xn)) {
-            SSLerr(SSL_F_PARSE_CA_NAMES, ERR_R_MALLOC_FAILURE);
-            *al = SSL_AD_INTERNAL_ERROR;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_PARSE_CA_NAMES,
+                     ERR_R_MALLOC_FAILURE);
             goto err;
         }
         xn = NULL;
@@ -2085,8 +2099,6 @@ int parse_ca_names(SSL *s, PACKET *pkt, int *al)
 
     return 1;
 
- decerr:
-    *al = SSL_AD_DECODE_ERROR;
  err:
     sk_X509_NAME_pop_free(ca_sk, X509_NAME_free);
     X509_NAME_free(xn);
@@ -2098,8 +2110,11 @@ int construct_ca_names(SSL *s, WPACKET *pkt)
     const STACK_OF(X509_NAME) *ca_sk = SSL_get0_CA_list(s);
 
     /* Start sub-packet for client CA list */
-    if (!WPACKET_start_sub_packet_u16(pkt))
+    if (!WPACKET_start_sub_packet_u16(pkt)) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_CA_NAMES,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
+    }
 
     if (ca_sk != NULL) {
         int i;
@@ -2114,26 +2129,34 @@ int construct_ca_names(SSL *s, WPACKET *pkt)
                     || !WPACKET_sub_allocate_bytes_u16(pkt, namelen,
                                                        &namebytes)
                     || i2d_X509_NAME(name, &namebytes) != namelen) {
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_CA_NAMES,
+                         ERR_R_INTERNAL_ERROR);
                 return 0;
             }
         }
     }
 
-    if (!WPACKET_close(pkt))
+    if (!WPACKET_close(pkt)) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_CA_NAMES,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
+    }
 
     return 1;
 }
 
 /* Create a buffer containing data to be signed for server key exchange */
-size_t construct_key_exchange_tbs(const SSL *s, unsigned char **ptbs,
+size_t construct_key_exchange_tbs(SSL *s, unsigned char **ptbs,
                                   const void *param, size_t paramlen)
 {
     size_t tbslen = 2 * SSL3_RANDOM_SIZE + paramlen;
     unsigned char *tbs = OPENSSL_malloc(tbslen);
 
-    if (tbs == NULL)
+    if (tbs == NULL) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_KEY_EXCHANGE_TBS,
+                 ERR_R_MALLOC_FAILURE);
         return 0;
+    }
     memcpy(tbs, s->s3->client_random, SSL3_RANDOM_SIZE);
     memcpy(tbs + SSL3_RANDOM_SIZE, s->s3->server_random, SSL3_RANDOM_SIZE);
 
diff --git a/ssl/statem/statem_locl.h b/ssl/statem/statem_locl.h
index 0ec097c..888c0b5 100644
--- a/ssl/statem/statem_locl.h
+++ b/ssl/statem/statem_locl.h
@@ -58,9 +58,9 @@ typedef int (*confunc_f) (SSL *s, WPACKET *pkt);
 int check_in_list(SSL *s, uint16_t group_id, const uint16_t *groups,
                   size_t num_groups, int checkallow);
 int create_synthetic_message_hash(SSL *s);
-int parse_ca_names(SSL *s, PACKET *pkt, int *al);
+int parse_ca_names(SSL *s, PACKET *pkt);
 int construct_ca_names(SSL *s, WPACKET *pkt);
-size_t construct_key_exchange_tbs(const SSL *s, unsigned char **ptbs,
+size_t construct_key_exchange_tbs(SSL *s, unsigned char **ptbs,
                                   const void *param, size_t paramlen);
 
 /*
@@ -95,7 +95,7 @@ __owur int tls_get_message_body(SSL *s, size_t *len);
 __owur int dtls_get_message(SSL *s, int *mt, size_t *len);
 
 /* Message construction and processing functions */
-__owur int tls_process_initial_server_flight(SSL *s, int *al);
+__owur int tls_process_initial_server_flight(SSL *s);
 __owur MSG_PROCESS_RETURN tls_process_change_cipher_spec(SSL *s, PACKET *pkt);
 __owur MSG_PROCESS_RETURN tls_process_finished(SSL *s, PACKET *pkt);
 __owur int tls_construct_change_cipher_spec(SSL *s, WPACKET *pkt);
@@ -112,7 +112,7 @@ __owur int tls_construct_client_hello(SSL *s, WPACKET *pkt);
 __owur MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt);
 __owur MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt);
 __owur MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt);
-__owur int tls_process_cert_status_body(SSL *s, PACKET *pkt, int *al);
+__owur int tls_process_cert_status_body(SSL *s, PACKET *pkt);
 __owur MSG_PROCESS_RETURN tls_process_cert_status(SSL *s, PACKET *pkt);
 __owur MSG_PROCESS_RETURN tls_process_server_done(SSL *s, PACKET *pkt);
 __owur int tls_construct_cert_verify(SSL *s, WPACKET *pkt);
@@ -164,17 +164,15 @@ typedef enum ext_return_en {
 __owur int extension_is_relevant(SSL *s, unsigned int extctx,
                                  unsigned int thisctx);
 __owur int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
-                                  RAW_EXTENSION **res, int *al, size_t *len,
-                                  int init);
+                                  RAW_EXTENSION **res, size_t *len, int init);
 __owur int tls_parse_extension(SSL *s, TLSEXT_INDEX idx, int context,
-                               RAW_EXTENSION *exts,  X509 *x, size_t chainidx,
-                               int *al);
+                               RAW_EXTENSION *exts,  X509 *x, size_t chainidx);
 __owur int tls_parse_all_extensions(SSL *s, int context, RAW_EXTENSION *exts,
-                                    X509 *x, size_t chainidx, int *al, int fin);
+                                    X509 *x, size_t chainidx, int fin);
 __owur int should_add_extension(SSL *s, unsigned int extctx,
                                 unsigned int thisctx, int max_version);
 __owur int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context,
-                                    X509 *x, size_t chainidx, int *al);
+                                    X509 *x, size_t chainidx);
 
 __owur int tls_psk_do_binder(SSL *s, const EVP_MD *md,
                              const unsigned char *msgstart,
@@ -184,98 +182,98 @@ __owur int tls_psk_do_binder(SSL *s, const EVP_MD *md,
 
 /* Server Extension processing */
 int tls_parse_ctos_renegotiate(SSL *s, PACKET *pkt, unsigned int context,
-                               X509 *x, size_t chainidx, int *al);
+                               X509 *x, size_t chainidx);
 int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, unsigned int context,
-                               X509 *x, size_t chainidx, int *al);
+                               X509 *x, size_t chainidx);
 int tls_parse_ctos_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
-                                  X509 *x, size_t chainidx, int *al);
+                                  X509 *x, size_t chainidx);
 #ifndef OPENSSL_NO_SRP
 int tls_parse_ctos_srp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                       size_t chainidx, int *al);
+                       size_t chainidx);
 #endif
 int tls_parse_ctos_early_data(SSL *s, PACKET *pkt, unsigned int context,
-                              X509 *x, size_t chainidx, int *al);
+                              X509 *x, size_t chainidx);
 #ifndef OPENSSL_NO_EC
 int tls_parse_ctos_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
-                                 X509 *x, size_t chainidx, int *al);
+                                 X509 *x, size_t chainidx);
 int tls_parse_ctos_supported_groups(SSL *s, PACKET *pkt, unsigned int context,
-                                    X509 *x, size_t chainidx, int *al);
+                                    X509 *x, size_t chainidxl);
 #endif
 int tls_parse_ctos_session_ticket(SSL *s, PACKET *pkt, unsigned int context,
-                                  X509 *x, size_t chainidx, int *al);
+                                  X509 *x, size_t chainidx);
 int tls_parse_ctos_sig_algs(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                            size_t chainidx, int *al);
+                            size_t chainidx);
 #ifndef OPENSSL_NO_OCSP
 int tls_parse_ctos_status_request(SSL *s, PACKET *pkt, unsigned int context,
-                                  X509 *x, size_t chainidx, int *al);
+                                  X509 *x, size_t chainidx);
 #endif
 #ifndef OPENSSL_NO_NEXTPROTONEG
 int tls_parse_ctos_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                       size_t chainidx, int *al);
+                       size_t chainidx);
 #endif
 int tls_parse_ctos_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                        size_t chainidx, int *al);
+                        size_t chainidx);
 #ifndef OPENSSL_NO_SRTP
 int tls_parse_ctos_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                            size_t chainidx, int *al);
+                            size_t chainidx);
 #endif
 int tls_parse_ctos_etm(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                       size_t chainidx, int *al);
+                       size_t chainidx);
 int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                             size_t chainidx, int *al);
+                             size_t chainidx);
 int tls_parse_ctos_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                       size_t chainidx, int *al);
+                       size_t chainidx);
 int tls_parse_ctos_psk_kex_modes(SSL *s, PACKET *pkt, unsigned int context,
-                                 X509 *x, size_t chainidx, int *al);
+                                 X509 *x, size_t chainidx);
 int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                       size_t chainidx, int *al);
+                       size_t chainidx);
 
 EXT_RETURN tls_construct_stoc_renegotiate(SSL *s, WPACKET *pkt,
                                           unsigned int context, X509 *x,
-                                          size_t chainidx, int *al);
+                                          size_t chainidx);
 EXT_RETURN tls_construct_stoc_server_name(SSL *s, WPACKET *pkt,
                                           unsigned int context, X509 *x,
-                                          size_t chainidx, int *al);
+                                          size_t chainidx);
 EXT_RETURN tls_construct_stoc_early_data(SSL *s, WPACKET *pkt,
                                          unsigned int context, X509 *x,
-                                         size_t chainidx, int *al);
+                                         size_t chainidx);
 EXT_RETURN tls_construct_stoc_maxfragmentlen(SSL *s, WPACKET *pkt,
                                              unsigned int context, X509 *x,
-                                             size_t chainidx, int *al);
+                                             size_t chainidx);
 #ifndef OPENSSL_NO_EC
 EXT_RETURN tls_construct_stoc_ec_pt_formats(SSL *s, WPACKET *pkt,
                                             unsigned int context, X509 *x,
-                                            size_t chainidx, int *al);
+                                            size_t chainidx);
 #endif
 EXT_RETURN tls_construct_stoc_supported_groups(SSL *s, WPACKET *pkt,
                                                unsigned int context, X509 *x,
-                                               size_t chainidx, int *al);
+                                               size_t chainidx);
 EXT_RETURN tls_construct_stoc_session_ticket(SSL *s, WPACKET *pkt,
                                              unsigned int context, X509 *x,
-                                             size_t chainidx, int *al);
+                                             size_t chainidx);
 #ifndef OPENSSL_NO_OCSP
 EXT_RETURN tls_construct_stoc_status_request(SSL *s, WPACKET *pkt,
                                              unsigned int context, X509 *x,
-                                             size_t chainidx, int *al);
+                                             size_t chainidx);
 #endif
 #ifndef OPENSSL_NO_NEXTPROTONEG
 EXT_RETURN tls_construct_stoc_next_proto_neg(SSL *s, WPACKET *pkt,
                                              unsigned int context, X509 *x,
-                                             size_t chainidx, int *al);
+                                             size_t chainidx);
 #endif
 EXT_RETURN tls_construct_stoc_alpn(SSL *s, WPACKET *pkt, unsigned int context,
-                                   X509 *x, size_t chainidx, int *al);
+                                   X509 *x, size_t chainidx);
 #ifndef OPENSSL_NO_SRTP
 EXT_RETURN tls_construct_stoc_use_srtp(SSL *s, WPACKET *pkt, unsigned int context,
-                                X509 *x, size_t chainidx, int *al);
+                                X509 *x, size_t chainidx);
 #endif
 EXT_RETURN tls_construct_stoc_etm(SSL *s, WPACKET *pkt, unsigned int context,
-                                  X509 *x, size_t chainidx, int *al);
+                                  X509 *x, size_t chainidx);
 EXT_RETURN tls_construct_stoc_ems(SSL *s, WPACKET *pkt, unsigned int context,
-                                  X509 *x, size_t chainidx, int *al);
+                                  X509 *x, size_t chainidx);
 EXT_RETURN tls_construct_stoc_key_share(SSL *s, WPACKET *pkt,
                                         unsigned int context, X509 *x,
-                                        size_t chainidx, int *al);
+                                        size_t chainidx);
 /*
  * Not in public headers as this is not an official extension. Only used when
  * SSL_OP_CRYPTOPRO_TLSEXT_BUG is set.
@@ -283,118 +281,118 @@ EXT_RETURN tls_construct_stoc_key_share(SSL *s, WPACKET *pkt,
 #define TLSEXT_TYPE_cryptopro_bug      0xfde8
 EXT_RETURN tls_construct_stoc_cryptopro_bug(SSL *s, WPACKET *pkt,
                                             unsigned int context, X509 *x,
-                                            size_t chainidx, int *al);
+                                            size_t chainidx);
 EXT_RETURN tls_construct_stoc_psk(SSL *s, WPACKET *pkt, unsigned int context,
-                                  X509 *x, size_t chainidx, int *al);
+                                  X509 *x, size_t chainidx);
 
 /* Client Extension processing */
 EXT_RETURN tls_construct_ctos_renegotiate(SSL *s, WPACKET *pkt, unsigned int context,
-                                   X509 *x, size_t chainidx, int *al);
+                                   X509 *x, size_t chainidx);
 EXT_RETURN tls_construct_ctos_server_name(SSL *s, WPACKET *pkt, unsigned int context,
-                                   X509 *x, size_t chainidx, int *al);
+                                   X509 *x, size_t chainidx);
 EXT_RETURN tls_construct_ctos_maxfragmentlen(SSL *s, WPACKET *pkt, unsigned int context,
-                                             X509 *x, size_t chainidx, int *al);
+                                             X509 *x, size_t chainidx);
 #ifndef OPENSSL_NO_SRP
 EXT_RETURN tls_construct_ctos_srp(SSL *s, WPACKET *pkt, unsigned int context, X509 *x,
-                           size_t chainidx, int *al);
+                           size_t chainidx);
 #endif
 #ifndef OPENSSL_NO_EC
 EXT_RETURN tls_construct_ctos_ec_pt_formats(SSL *s, WPACKET *pkt,
                                             unsigned int context, X509 *x,
-                                            size_t chainidx, int *al);
+                                            size_t chainidx);
 EXT_RETURN tls_construct_ctos_supported_groups(SSL *s, WPACKET *pkt,
                                                unsigned int context, X509 *x,
-                                               size_t chainidx, int *al);
+                                               size_t chainidx);
 #endif
 EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt,
                                          unsigned int context, X509 *x,
-                                         size_t chainidx, int *al);
+                                         size_t chainidx);
 EXT_RETURN tls_construct_ctos_session_ticket(SSL *s, WPACKET *pkt,
                                              unsigned int context, X509 *x,
-                                             size_t chainidx, int *al);
+                                             size_t chainidx);
 EXT_RETURN tls_construct_ctos_sig_algs(SSL *s, WPACKET *pkt,
                                        unsigned int context, X509 *x,
-                                       size_t chainidx, int *al);
+                                       size_t chainidx);
 #ifndef OPENSSL_NO_OCSP
 EXT_RETURN tls_construct_ctos_status_request(SSL *s, WPACKET *pkt,
                                              unsigned int context, X509 *x,
-                                             size_t chainidx, int *al);
+                                             size_t chainidx);
 #endif
 #ifndef OPENSSL_NO_NEXTPROTONEG
 EXT_RETURN tls_construct_ctos_npn(SSL *s, WPACKET *pkt, unsigned int context,
-                                  X509 *x, size_t chainidx, int *al);
+                                  X509 *x, size_t chainidx);
 #endif
 EXT_RETURN tls_construct_ctos_alpn(SSL *s, WPACKET *pkt, unsigned int context,
-                                   X509 *x, size_t chainidx, int *al);
+                                   X509 *x, size_t chainidx);
 #ifndef OPENSSL_NO_SRTP
 EXT_RETURN tls_construct_ctos_use_srtp(SSL *s, WPACKET *pkt, unsigned int context,
-                                       X509 *x, size_t chainidx, int *al);
+                                       X509 *x, size_t chainidx);
 #endif
 EXT_RETURN tls_construct_ctos_etm(SSL *s, WPACKET *pkt, unsigned int context,
-                                  X509 *x, size_t chainidx, int *al);
+                                  X509 *x, size_t chainidx);
 #ifndef OPENSSL_NO_CT
 EXT_RETURN tls_construct_ctos_sct(SSL *s, WPACKET *pkt, unsigned int context,
-                                  X509 *x, size_t chainidx, int *al);
+                                  X509 *x, size_t chainidx);
 #endif
 EXT_RETURN tls_construct_ctos_ems(SSL *s, WPACKET *pkt, unsigned int context,
-                                  X509 *x, size_t chainidx, int *al);
+                                  X509 *x, size_t chainidx);
 EXT_RETURN tls_construct_ctos_supported_versions(SSL *s, WPACKET *pkt,
                                                  unsigned int context, X509 *x,
-                                                 size_t chainidx, int *al);
+                                                 size_t chainidx);
 EXT_RETURN tls_construct_ctos_key_share(SSL *s, WPACKET *pkt,
                                         unsigned int context, X509 *x,
-                                        size_t chainidx, int *al);
+                                        size_t chainidx);
 EXT_RETURN tls_construct_ctos_psk_kex_modes(SSL *s, WPACKET *pkt,
                                             unsigned int context, X509 *x,
-                                            size_t chainidx, int *al);
+                                            size_t chainidx);
 EXT_RETURN tls_construct_ctos_cookie(SSL *s, WPACKET *pkt, unsigned int context,
-                                     X509 *x, size_t chainidx, int *al);
+                                     X509 *x, size_t chainidx);
 EXT_RETURN tls_construct_ctos_padding(SSL *s, WPACKET *pkt,
                                       unsigned int context, X509 *x,
-                                      size_t chainidx, int *al);
+                                      size_t chainidx);
 EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
-                                  X509 *x, size_t chainidx, int *al);
+                                  X509 *x, size_t chainidx);
 int tls_parse_stoc_renegotiate(SSL *s, PACKET *pkt, unsigned int context,
-                               X509 *x, size_t chainidx, int *al);
+                               X509 *x, size_t chainidx);
 int tls_parse_stoc_server_name(SSL *s, PACKET *pkt, unsigned int context,
-                               X509 *x, size_t chainidx, int *al);
+                               X509 *x, size_t chainidx);
 int tls_parse_stoc_early_data(SSL *s, PACKET *pkt, unsigned int context,
-                              X509 *x, size_t chainidx, int *al);
+                              X509 *x, size_t chainidx);
 int tls_parse_stoc_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
-                                  X509 *x, size_t chainidx, int *al);
+                                  X509 *x, size_t chainidx);
 #ifndef OPENSSL_NO_EC
 int tls_parse_stoc_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
-                                 X509 *x, size_t chainidx, int *al);
+                                 X509 *x, size_t chainidx);
 #endif
 int tls_parse_stoc_session_ticket(SSL *s, PACKET *pkt, unsigned int context,
-                                  X509 *x, size_t chainidx, int *al);
+                                  X509 *x, size_t chainidx);
 #ifndef OPENSSL_NO_OCSP
 int tls_parse_stoc_status_request(SSL *s, PACKET *pkt, unsigned int context,
-                                  X509 *x, size_t chainidx, int *al);
+                                  X509 *x, size_t chainidx);
 #endif
 #ifndef OPENSSL_NO_CT
 int tls_parse_stoc_sct(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                       size_t chainidx, int *al);
+                       size_t chainidx);
 #endif
 #ifndef OPENSSL_NO_NEXTPROTONEG
 int tls_parse_stoc_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                       size_t chainidx, int *al);
+                       size_t chainidx);
 #endif
 int tls_parse_stoc_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                        size_t chainidx, int *al);
+                        size_t chainidx);
 #ifndef OPENSSL_NO_SRTP
 int tls_parse_stoc_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                            size_t chainidx, int *al);
+                            size_t chainidx);
 #endif
 int tls_parse_stoc_etm(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                       size_t chainidx, int *al);
+                       size_t chainidx);
 int tls_parse_stoc_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                       size_t chainidx, int *al);
+                       size_t chainidx);
 int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                             size_t chainidx, int *al);
+                             size_t chainidx);
 int tls_parse_stoc_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                       size_t chainidx, int *al);
+                       size_t chainidx);
 int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                       size_t chainidx, int *al);
+                       size_t chainidx);
 
-int tls_handle_alpn(SSL *s, int *al);
+int tls_handle_alpn(SSL *s);
diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c
index 3e118a8..f95c19b 100644
--- a/ssl/statem/statem_srvr.c
+++ b/ssl/statem/statem_srvr.c
@@ -171,10 +171,9 @@ int ossl_statem_server_read_transition(SSL *s, int mt)
                          * not going to accept it because we require a client
                          * cert.
                          */
-                        ssl3_send_alert(s, SSL3_AL_FATAL,
-                                        SSL3_AD_HANDSHAKE_FAILURE);
-                        SSLerr(SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION,
-                               SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
+                        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+                                 SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION,
+                                 SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
                         return 0;
                     }
                     st->hand_state = TLS_ST_SR_KEY_EXCH;
@@ -271,8 +270,9 @@ int ossl_statem_server_read_transition(SSL *s, int mt)
 
  err:
     /* No valid transition found */
-    ssl3_send_alert(s, SSL3_AL_FATAL, SSL3_AD_UNEXPECTED_MESSAGE);
-    SSLerr(SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION, SSL_R_UNEXPECTED_MESSAGE);
+    SSLfatal(s, SSL3_AD_UNEXPECTED_MESSAGE,
+             SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION,
+             SSL_R_UNEXPECTED_MESSAGE);
     return 0;
 }
 
@@ -378,6 +378,9 @@ static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s)
     switch (st->hand_state) {
     default:
         /* Shouldn't happen */
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_OSSL_STATEM_SERVER13_WRITE_TRANSITION,
+                 ERR_R_INTERNAL_ERROR);
         return WRITE_TRAN_ERROR;
 
     case TLS_ST_OK:
@@ -477,6 +480,9 @@ WRITE_TRAN ossl_statem_server_write_transition(SSL *s)
     switch (st->hand_state) {
     default:
         /* Shouldn't happen */
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_OSSL_STATEM_SERVER_WRITE_TRANSITION,
+                 ERR_R_INTERNAL_ERROR);
         return WRITE_TRAN_ERROR;
 
     case TLS_ST_OK:
@@ -488,7 +494,7 @@ WRITE_TRAN ossl_statem_server_write_transition(SSL *s)
         }
         /* Must be an incoming ClientHello */
         if (!tls_setup_handshake(s)) {
-            ossl_statem_set_error(s);
+            /* SSLfatal() already called */
             return WRITE_TRAN_ERROR;
         }
         /* Fall through */
@@ -630,8 +636,10 @@ WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst)
 
     case TLS_ST_SW_SRVR_DONE:
 #ifndef OPENSSL_NO_SCTP
-        if (SSL_IS_DTLS(s) && BIO_dgram_is_sctp(SSL_get_wbio(s)))
+        if (SSL_IS_DTLS(s) && BIO_dgram_is_sctp(SSL_get_wbio(s))) {
+            /* Calls SSLfatal() as required */
             return dtls_wait_for_dry(s);
+        }
 #endif
         return WORK_FINISHED_CONTINUE;
 
@@ -641,6 +649,8 @@ WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst)
              * Actually this is the end of the handshake, but we're going
              * straight into writing the session ticket out. So we finish off
              * the handshake, but keep the various buffers active.
+             * 
+             * Calls SSLfatal as required.
              */
             return tls_finish_handshake(s, wst, 0);
         } if (SSL_IS_DTLS(s)) {
@@ -655,7 +665,7 @@ WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst)
     case TLS_ST_SW_CHANGE:
         s->session->cipher = s->s3->tmp.new_cipher;
         if (!s->method->ssl3_enc->setup_key_block(s)) {
-            ossl_statem_set_error(s);
+            /* SSLfatal() already called */
             return WORK_ERROR;
         }
         if (SSL_IS_DTLS(s)) {
@@ -675,6 +685,7 @@ WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst)
         /* Fall through */
 
     case TLS_ST_OK:
+        /* Calls SSLfatal() as required */
         return tls_finish_handshake(s, wst, 1);
     }
 
@@ -705,7 +716,7 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst)
         if (statem_flush(s) != 1)
             return WORK_MORE_A;
         if (!ssl3_init_finished_mac(s)) {
-            ossl_statem_set_error(s);
+            /* SSLfatal() already called */
             return WORK_ERROR;
         }
         break;
@@ -715,7 +726,7 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst)
             return WORK_MORE_A;
         /* HelloVerifyRequest resets Finished MAC */
         if (s->version != DTLS1_BAD_VER && !ssl3_init_finished_mac(s)) {
-            ossl_statem_set_error(s);
+            /* SSLfatal() already called */
             return WORK_ERROR;
         }
         /*
@@ -742,7 +753,9 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst)
                                            sizeof(sctpauthkey), labelbuffer,
                                            sizeof(labelbuffer), NULL, 0,
                                            0) <= 0) {
-                ossl_statem_set_error(s);
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_OSSL_STATEM_SERVER_POST_WORK,
+                         ERR_R_INTERNAL_ERROR);
                 return WORK_ERROR;
             }
 
@@ -759,13 +772,17 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst)
         if (SSL_IS_TLS13(s)) {
             if (!s->method->ssl3_enc->setup_key_block(s)
                 || !s->method->ssl3_enc->change_cipher_state(s,
-                        SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_SERVER_WRITE))
+                        SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_SERVER_WRITE)) {
+                /* SSLfatal() already called */
                 return WORK_ERROR;
+            }
 
             if (s->ext.early_data != SSL_EARLY_DATA_ACCEPTED
                 && !s->method->ssl3_enc->change_cipher_state(s,
-                        SSL3_CC_HANDSHAKE |SSL3_CHANGE_CIPHER_SERVER_READ))
+                        SSL3_CC_HANDSHAKE |SSL3_CHANGE_CIPHER_SERVER_READ)) {
+                /* SSLfatal() already called */
                 return WORK_ERROR;
+            }
         }
         break;
 
@@ -783,7 +800,7 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst)
         if (!s->method->ssl3_enc->change_cipher_state(s,
                                                       SSL3_CHANGE_CIPHER_SERVER_WRITE))
         {
-            ossl_statem_set_error(s);
+            /* SSLfatal() already called */
             return WORK_ERROR;
         }
 
@@ -815,6 +832,7 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst)
                         &s->session->master_key_length)
                 || !s->method->ssl3_enc->change_cipher_state(s,
                         SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_SERVER_WRITE))
+            /* SSLfatal() already called */
             return WORK_ERROR;
         }
         break;
@@ -822,8 +840,10 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst)
     case TLS_ST_SW_KEY_UPDATE:
         if (statem_flush(s) != 1)
             return WORK_MORE_A;
-        if (!tls13_update_key(s, 1))
+        if (!tls13_update_key(s, 1)) {
+            /* SSLfatal() already called */
             return WORK_ERROR;
+        }
         break;
 
     case TLS_ST_SW_SESSION_TICKET:
@@ -851,6 +871,9 @@ int ossl_statem_server_construct_message(SSL *s, WPACKET *pkt,
     switch (st->hand_state) {
     default:
         /* Shouldn't happen */
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_OSSL_STATEM_SERVER_CONSTRUCT_MESSAGE,
+                 SSL_R_BAD_HANDSHAKE_STATE);
         return 0;
 
     case TLS_ST_SW_CHANGE:
@@ -1016,6 +1039,9 @@ MSG_PROCESS_RETURN ossl_statem_server_process_message(SSL *s, PACKET *pkt)
     switch (st->hand_state) {
     default:
         /* Shouldn't happen */
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_OSSL_STATEM_SERVER_PROCESS_MESSAGE,
+                 ERR_R_INTERNAL_ERROR);
         return MSG_PROCESS_ERROR;
 
     case TLS_ST_SR_CLNT_HELLO:
@@ -1061,6 +1087,9 @@ WORK_STATE ossl_statem_server_post_process_message(SSL *s, WORK_STATE wst)
     switch (st->hand_state) {
     default:
         /* Shouldn't happen */
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_OSSL_STATEM_SERVER_POST_PROCESS_MESSAGE,
+                 ERR_R_INTERNAL_ERROR);
         return WORK_ERROR;
 
     case TLS_ST_SR_CLNT_HELLO:
@@ -1073,11 +1102,11 @@ WORK_STATE ossl_statem_server_post_process_message(SSL *s, WORK_STATE wst)
 }
 
 #ifndef OPENSSL_NO_SRP
-static int ssl_check_srp_ext_ClientHello(SSL *s, int *al)
+/* Returns 1 on success, 0 for retryable error, -1 for fatal error */
+static int ssl_check_srp_ext_ClientHello(SSL *s)
 {
-    int ret = SSL_ERROR_NONE;
-
-    *al = SSL_AD_UNRECOGNIZED_NAME;
+    int ret;
+    int al = SSL_AD_UNRECOGNIZED_NAME;
 
     if ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) &&
         (s->srp_ctx.TLS_ext_srp_username_callback != NULL)) {
@@ -1086,13 +1115,24 @@ static int ssl_check_srp_ext_ClientHello(SSL *s, int *al)
              * RFC 5054 says SHOULD reject, we do so if There is no srp
              * login name
              */
-            ret = SSL3_AL_FATAL;
-            *al = SSL_AD_UNKNOWN_PSK_IDENTITY;
+            SSLfatal(s, SSL_AD_UNKNOWN_PSK_IDENTITY,
+                     SSL_F_SSL_CHECK_SRP_EXT_CLIENTHELLO,
+                     SSL_R_PSK_IDENTITY_NOT_FOUND);
+            return -1;
         } else {
-            ret = SSL_srp_server_param_with_username(s, al);
+            ret = SSL_srp_server_param_with_username(s, &al);
+            if (ret < 0)
+                return 0;
+            if (ret == SSL3_AL_FATAL) {
+                SSLfatal(s, al, SSL_F_SSL_CHECK_SRP_EXT_CLIENTHELLO,
+                         al == SSL_AD_UNKNOWN_PSK_IDENTITY
+                         ? SSL_R_PSK_IDENTITY_NOT_FOUND
+                         : SSL_R_CLIENTHELLO_TLSEXT);
+                return -1;
+            }
         }
     }
-    return ret;
+    return 1;
 }
 #endif
 
@@ -1114,15 +1154,16 @@ int dtls_construct_hello_verify_request(SSL *s, WPACKET *pkt)
         s->ctx->app_gen_cookie_cb(s, s->d1->cookie,
                                   &cookie_leni) == 0 ||
         cookie_leni > 255) {
-        SSLerr(SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST,
-               SSL_R_COOKIE_GEN_CALLBACK_FAILURE);
+        SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST,
+                 SSL_R_COOKIE_GEN_CALLBACK_FAILURE);
         return 0;
     }
     s->d1->cookie_len = cookie_leni;
 
     if (!dtls_raw_hello_verify_request(pkt, s->d1->cookie,
                                               s->d1->cookie_len)) {
-        SSLerr(SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
@@ -1195,7 +1236,6 @@ static void ssl_check_for_safari(SSL *s, const CLIENTHELLO_MSG *hello)
 
 MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
 {
-    int al = SSL_AD_INTERNAL_ERROR;
     /* |cookie| will only be initialized for DTLS. */
     PACKET session_id, compression, extensions, cookie;
     static const unsigned char null_compression = 0;
@@ -1203,7 +1243,8 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
 
     clienthello = OPENSSL_zalloc(sizeof(*clienthello));
     if (clienthello == NULL) {
-        SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+        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 */
@@ -1226,9 +1267,9 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
         unsigned int mt;
 
         if (!SSL_IS_FIRST_HANDSHAKE(s) || s->hello_retry_request) {
-            al = SSL_AD_UNEXPECTED_MESSAGE;
-            SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_UNEXPECTED_MESSAGE);
-            goto f_err;
+            SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
+                     SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_UNEXPECTED_MESSAGE);
+            goto err;
         }
 
         /*-
@@ -1253,14 +1294,15 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
              * layer in order to have determined that this is a SSLv2 record
              * in the first place
              */
-            SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
+                     ERR_R_INTERNAL_ERROR);
             goto err;
         }
     }
 
     if (!PACKET_get_net_2(pkt, &clienthello->legacy_version)) {
-        al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
+                 SSL_R_LENGTH_TOO_SHORT);
         goto err;
     }
 
@@ -1277,16 +1319,15 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
         if (!PACKET_get_net_2(pkt, &ciphersuite_len)
             || !PACKET_get_net_2(pkt, &session_id_len)
             || !PACKET_get_net_2(pkt, &challenge_len)) {
-            SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO,
-                   SSL_R_RECORD_LENGTH_MISMATCH);
-            al = SSL_AD_DECODE_ERROR;
-            goto f_err;
+            SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
+                     SSL_R_RECORD_LENGTH_MISMATCH);
+            goto err;
         }
 
         if (session_id_len > SSL_MAX_SSL_SESSION_ID_LENGTH) {
-            al = SSL_AD_ILLEGAL_PARAMETER;
-            SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
-            goto f_err;
+            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+                     SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
+            goto err;
         }
 
         if (!PACKET_get_sub_packet(pkt, &clienthello->ciphersuites,
@@ -1295,10 +1336,9 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
             || !PACKET_get_sub_packet(pkt, &challenge, challenge_len)
             /* No extensions. */
             || PACKET_remaining(pkt) != 0) {
-            SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO,
-                   SSL_R_RECORD_LENGTH_MISMATCH);
-            al = SSL_AD_DECODE_ERROR;
-            goto f_err;
+            SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
+                     SSL_R_RECORD_LENGTH_MISMATCH);
+            goto err;
         }
         clienthello->session_id_len = session_id_len;
 
@@ -1315,9 +1355,9 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
                                challenge_len, challenge_len)
             /* Advertise only null compression. */
             || !PACKET_buf_init(&compression, &null_compression, 1)) {
-            SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
-            al = SSL_AD_INTERNAL_ERROR;
-            goto f_err;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
+                     ERR_R_INTERNAL_ERROR);
+            goto err;
         }
 
         PACKET_null_init(&clienthello->extensions);
@@ -1328,23 +1368,23 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
             || !PACKET_copy_all(&session_id, clienthello->session_id,
                     SSL_MAX_SSL_SESSION_ID_LENGTH,
                     &clienthello->session_id_len)) {
-            al = SSL_AD_DECODE_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
-            goto f_err;
+            SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
+                     SSL_R_LENGTH_MISMATCH);
+            goto err;
         }
 
         if (SSL_IS_DTLS(s)) {
             if (!PACKET_get_length_prefixed_1(pkt, &cookie)) {
-                al = SSL_AD_DECODE_ERROR;
-                SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
-                goto f_err;
+                SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
+                         SSL_R_LENGTH_MISMATCH);
+                goto err;
             }
             if (!PACKET_copy_all(&cookie, clienthello->dtls_cookie,
                                  DTLS1_COOKIE_LENGTH,
                                  &clienthello->dtls_cookie_len)) {
-                al = SSL_AD_INTERNAL_ERROR;
-                SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
-                goto f_err;
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_TLS_PROCESS_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+                goto err;
             }
             /*
              * If we require cookies and this ClientHello doesn't contain one,
@@ -1358,15 +1398,15 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
         }
 
         if (!PACKET_get_length_prefixed_2(pkt, &clienthello->ciphersuites)) {
-            al = SSL_AD_DECODE_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
-            goto f_err;
+            SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
+                     SSL_R_LENGTH_MISMATCH);
+            goto err;
         }
 
         if (!PACKET_get_length_prefixed_1(pkt, &compression)) {
-            al = SSL_AD_DECODE_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
-            goto f_err;
+            SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
+                     SSL_R_LENGTH_MISMATCH);
+            goto err;
         }
 
         /* Could be empty. */
@@ -1375,9 +1415,9 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
         } else {
             if (!PACKET_get_length_prefixed_2(pkt, &clienthello->extensions)
                     || PACKET_remaining(pkt) != 0) {
-                al = SSL_AD_DECODE_ERROR;
-                SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
-                goto f_err;
+                SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
+                         SSL_R_LENGTH_MISMATCH);
+                goto err;
             }
         }
     }
@@ -1385,27 +1425,24 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
     if (!PACKET_copy_all(&compression, clienthello->compressions,
                          MAX_COMPRESSIONS_SIZE,
                          &clienthello->compressions_len)) {
-        al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
-        goto f_err;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
+                 ERR_R_INTERNAL_ERROR);
+        goto err;
     }
 
     /* Preserve the raw extensions PACKET for later use */
     extensions = clienthello->extensions;
     if (!tls_collect_extensions(s, &extensions, SSL_EXT_CLIENT_HELLO,
-                                &clienthello->pre_proc_exts, &al,
+                                &clienthello->pre_proc_exts,
                                 &clienthello->pre_proc_exts_len, 1)) {
-        /* SSLerr already been called */
-        goto f_err;
+        /* SSLfatal already been called */
+        goto err;
     }
     s->clienthello = clienthello;
 
     return MSG_PROCESS_CONTINUE_PROCESSING;
- f_err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, al);
- err:
-    ossl_statem_set_error(s);
 
+ err:
     if (clienthello != NULL)
         OPENSSL_free(clienthello->pre_proc_exts);
     OPENSSL_free(clienthello);
@@ -1413,7 +1450,7 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
     return MSG_PROCESS_ERROR;
 }
 
-static int tls_early_post_process_client_hello(SSL *s, int *pal)
+static int tls_early_post_process_client_hello(SSL *s)
 {
     unsigned int j;
     int i, al = SSL_AD_INTERNAL_ERROR;
@@ -1441,6 +1478,9 @@ static int tls_early_post_process_client_hello(SSL *s, int *pal)
             return -1;
         case SSL_CLIENT_HELLO_ERROR:
         default:
+            SSLfatal(s, al,
+                     SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+                     SSL_R_CALLBACK_FAILED);
             goto err;
         }
     }
@@ -1455,10 +1495,12 @@ static int tls_early_post_process_client_hello(SSL *s, int *pal)
                 || (clienthello->legacy_version & 0xff00)
                    != (SSL3_VERSION_MAJOR << 8)) {
             /*
-             * This is real SSLv2 or something complete unknown. We don't
+             * This is real SSLv2 or something completely unknown. We don't
              * support it.
              */
-            SSLerr(SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
+            SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
+                     SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+                     SSL_R_UNKNOWN_PROTOCOL);
             goto err;
         }
         /* SSLv3/TLS */
@@ -1478,20 +1520,20 @@ static int tls_early_post_process_client_hello(SSL *s, int *pal)
     }
 
     if (protverr) {
-        SSLerr(SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, protverr);
         if (SSL_IS_FIRST_HANDSHAKE(s)) {
             /* like ssl3_get_record, send alert using remote version number */
             s->version = s->client_version = clienthello->legacy_version;
         }
-        al = SSL_AD_PROTOCOL_VERSION;
+        SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
+                 SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, protverr);
         goto err;
     }
 
     /* TLSv1.3 specifies that a ClientHello must end on a record boundary */
     if (SSL_IS_TLS13(s) && RECORD_LAYER_processed_read_pending(&s->rlayer)) {
-        al = SSL_AD_UNEXPECTED_MESSAGE;
-        SSLerr(SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
-               SSL_R_NOT_ON_RECORD_BOUNDARY);
+        SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
+                 SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+                 SSL_R_NOT_ON_RECORD_BOUNDARY);
         goto err;
     }
 
@@ -1501,9 +1543,9 @@ static int tls_early_post_process_client_hello(SSL *s, int *pal)
             if (s->ctx->app_verify_cookie_cb != NULL) {
                 if (s->ctx->app_verify_cookie_cb(s, clienthello->dtls_cookie,
                         clienthello->dtls_cookie_len) == 0) {
-                    al = SSL_AD_HANDSHAKE_FAILURE;
-                    SSLerr(SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
-                           SSL_R_COOKIE_MISMATCH);
+                    SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+                             SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+                             SSL_R_COOKIE_MISMATCH);
                     goto err;
                     /* else cookie verification succeeded */
                 }
@@ -1511,8 +1553,9 @@ static int tls_early_post_process_client_hello(SSL *s, int *pal)
             } else if (s->d1->cookie_len != clienthello->dtls_cookie_len
                     || memcmp(clienthello->dtls_cookie, s->d1->cookie,
                               s->d1->cookie_len) != 0) {
-                al = SSL_AD_HANDSHAKE_FAILURE;
-                SSLerr(SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, SSL_R_COOKIE_MISMATCH);
+                SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+                         SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+                         SSL_R_COOKIE_MISMATCH);
                 goto err;
             }
             s->d1->cookie_verified = 1;
@@ -1520,9 +1563,9 @@ static int tls_early_post_process_client_hello(SSL *s, int *pal)
         if (s->method->version == DTLS_ANY_VERSION) {
             protverr = ssl_choose_server_version(s, clienthello, &dgrd);
             if (protverr != 0) {
-                SSLerr(SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, protverr);
                 s->version = s->client_version;
-                al = SSL_AD_PROTOCOL_VERSION;
+                SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
+                         SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, protverr);
                 goto err;
             }
         }
@@ -1531,9 +1574,10 @@ static int tls_early_post_process_client_hello(SSL *s, int *pal)
     s->hit = 0;
 
     if (!ssl_cache_cipherlist(s, &clienthello->ciphersuites,
-                              clienthello->isv2, &al) ||
+                              clienthello->isv2) ||
         !bytes_to_cipher_list(s, &clienthello->ciphersuites, &ciphers, &scsvs,
-                             clienthello->isv2, &al)) {
+                              clienthello->isv2, 1)) {
+        /* SSLfatal() already called */
         goto err;
     }
 
@@ -1545,9 +1589,9 @@ static int tls_early_post_process_client_hello(SSL *s, int *pal)
             if (SSL_CIPHER_get_id(c) == SSL3_CK_SCSV) {
                 if (s->renegotiate) {
                     /* SCSV is fatal if renegotiating */
-                    SSLerr(SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
-                           SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING);
-                    al = SSL_AD_HANDSHAKE_FAILURE;
+                    SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+                             SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+                             SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING);
                     goto err;
                 }
                 s->s3->send_connection_binding = 1;
@@ -1560,9 +1604,9 @@ static int tls_early_post_process_client_hello(SSL *s, int *pal)
                  * connection may have been tampered with in order to trigger
                  * an insecure downgrade.
                  */
-                SSLerr(SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
-                       SSL_R_INAPPROPRIATE_FALLBACK);
-                al = SSL_AD_INAPPROPRIATE_FALLBACK;
+                SSLfatal(s, SSL_AD_INAPPROPRIATE_FALLBACK,
+                         SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+                         SSL_R_INAPPROPRIATE_FALLBACK);
                 goto err;
             }
         }
@@ -1574,9 +1618,9 @@ static int tls_early_post_process_client_hello(SSL *s, int *pal)
             ssl3_choose_cipher(s, ciphers, SSL_get_ciphers(s));
 
         if (cipher == NULL) {
-            SSLerr(SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
-                   SSL_R_NO_SHARED_CIPHER);
-            al = SSL_AD_HANDSHAKE_FAILURE;
+            SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+                     SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+                     SSL_R_NO_SHARED_CIPHER);
             goto err;
         }
         if (s->hello_retry_request
@@ -1586,8 +1630,9 @@ static int tls_early_post_process_client_hello(SSL *s, int *pal)
              * A previous HRR picked a different ciphersuite to the one we
              * just selected. Something must have changed.
              */
-            al = SSL_AD_ILLEGAL_PARAMETER;
-            SSLerr(SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, SSL_R_BAD_CIPHER);
+            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+                     SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+                     SSL_R_BAD_CIPHER);
             goto err;
         }
         s->s3->tmp.new_cipher = cipher;
@@ -1596,8 +1641,8 @@ static int tls_early_post_process_client_hello(SSL *s, int *pal)
     /* We need to do this before getting the session */
     if (!tls_parse_extension(s, TLSEXT_IDX_extended_master_secret,
                              SSL_EXT_CLIENT_HELLO,
-                             clienthello->pre_proc_exts, NULL, 0, &al)) {
-        SSLerr(SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT);
+                             clienthello->pre_proc_exts, NULL, 0)) {
+        /* SSLfatal() already called */
         goto err;
     }
 
@@ -1620,19 +1665,24 @@ static int tls_early_post_process_client_hello(SSL *s, int *pal)
     if (clienthello->isv2 ||
         (s->new_session &&
          (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION))) {
-        if (!ssl_get_new_session(s, 1))
+        if (!ssl_get_new_session(s, 1)) {
+            /* SSLfatal() already called */
             goto err;
+        }
     } else {
-        i = ssl_get_prev_session(s, clienthello, &al);
+        i = ssl_get_prev_session(s, clienthello);
         if (i == 1) {
             /* previous session */
             s->hit = 1;
         } else if (i == -1) {
+            /* SSLfatal() already called */
             goto err;
         } else {
             /* i == 0 */
-            if (!ssl_get_new_session(s, 1))
+            if (!ssl_get_new_session(s, 1)) {
+                /* SSLfatal() already called */
                 goto err;
+            }
         }
     }
 
@@ -1663,9 +1713,9 @@ static int tls_early_post_process_client_hello(SSL *s, int *pal)
              * we need to have the cipher in the cipher list if we are asked
              * to reuse it
              */
-            al = SSL_AD_ILLEGAL_PARAMETER;
-            SSLerr(SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
-                   SSL_R_REQUIRED_CIPHER_MISSING);
+            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+                     SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+                     SSL_R_REQUIRED_CIPHER_MISSING);
             goto err;
         }
     }
@@ -1677,8 +1727,9 @@ static int tls_early_post_process_client_hello(SSL *s, int *pal)
 
     if (loop >= clienthello->compressions_len) {
         /* no compress */
-        al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, SSL_R_NO_COMPRESSION_SPECIFIED);
+        SSLfatal(s, SSL_AD_DECODE_ERROR,
+                 SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+                 SSL_R_NO_COMPRESSION_SPECIFIED);
         goto err;
     }
 
@@ -1689,8 +1740,8 @@ static int tls_early_post_process_client_hello(SSL *s, int *pal)
 
     /* TLS extensions */
     if (!tls_parse_all_extensions(s, SSL_EXT_CLIENT_HELLO,
-                                  clienthello->pre_proc_exts, NULL, 0, &al, 1)) {
-        SSLerr(SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, SSL_R_PARSE_TLSEXT);
+                                  clienthello->pre_proc_exts, NULL, 0, 1)) {
+        /* SSLfatal() already called */
         goto err;
     }
 
@@ -1704,6 +1755,9 @@ static int tls_early_post_process_client_hello(SSL *s, int *pal)
         unsigned char *pos;
         pos = s->s3->server_random;
         if (ssl_fill_hello_random(s, 1, pos, SSL3_RANDOM_SIZE, dgrd) <= 0) {
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+                     ERR_R_INTERNAL_ERROR);
             goto err;
         }
     }
@@ -1738,8 +1792,9 @@ static int tls_early_post_process_client_hello(SSL *s, int *pal)
                 pref_cipher = ssl3_choose_cipher(s, s->session->ciphers,
                                                  SSL_get_ciphers(s));
             if (pref_cipher == NULL) {
-                al = SSL_AD_HANDSHAKE_FAILURE;
-                SSLerr(SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, SSL_R_NO_SHARED_CIPHER);
+                SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+                         SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+                         SSL_R_NO_SHARED_CIPHER);
                 goto err;
             }
 
@@ -1764,9 +1819,9 @@ static int tls_early_post_process_client_hello(SSL *s, int *pal)
          * a TLSv1.3 ClientHello.
          */
         if (clienthello->compressions_len != 1) {
-            al = SSL_AD_ILLEGAL_PARAMETER;
-            SSLerr(SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
-                   SSL_R_INVALID_COMPRESSION_ALGORITHM);
+            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+                     SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+                     SSL_R_INVALID_COMPRESSION_ALGORITHM);
             goto err;
         }
     }
@@ -1778,8 +1833,9 @@ static int tls_early_post_process_client_hello(SSL *s, int *pal)
         /* Perform sanity checks on resumed compression algorithm */
         /* Can't disable compression */
         if (!ssl_allow_compression(s)) {
-            SSLerr(SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
-                   SSL_R_INCONSISTENT_COMPRESSION);
+            SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+                     SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+                     SSL_R_INCONSISTENT_COMPRESSION);
             goto err;
         }
         /* Look for resumed compression method */
@@ -1791,8 +1847,9 @@ static int tls_early_post_process_client_hello(SSL *s, int *pal)
             }
         }
         if (s->s3->tmp.new_compression == NULL) {
-            SSLerr(SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
-                   SSL_R_INVALID_COMPRESSION_ALGORITHM);
+            SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+                     SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+                     SSL_R_INVALID_COMPRESSION_ALGORITHM);
             goto err;
         }
         /* Look for resumed method in compression list */
@@ -1801,9 +1858,9 @@ static int tls_early_post_process_client_hello(SSL *s, int *pal)
                 break;
         }
         if (k >= clienthello->compressions_len) {
-            al = SSL_AD_ILLEGAL_PARAMETER;
-            SSLerr(SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
-                   SSL_R_REQUIRED_COMPRESSION_ALGORITHM_MISSING);
+            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+                     SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+                     SSL_R_REQUIRED_COMPRESSION_ALGORITHM_MISSING);
             goto err;
         }
     } else if (s->hit) {
@@ -1837,7 +1894,9 @@ static int tls_early_post_process_client_hello(SSL *s, int *pal)
      * using compression.
      */
     if (s->session->compress_meth != 0) {
-        SSLerr(SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, SSL_R_INCONSISTENT_COMPRESSION);
+        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+                 SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+                 SSL_R_INCONSISTENT_COMPRESSION);
         goto err;
     }
 #endif
@@ -1850,8 +1909,9 @@ static int tls_early_post_process_client_hello(SSL *s, int *pal)
         sk_SSL_CIPHER_free(s->session->ciphers);
         s->session->ciphers = ciphers;
         if (ciphers == NULL) {
-            al = SSL_AD_INTERNAL_ERROR;
-            SSLerr(SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
+                     ERR_R_INTERNAL_ERROR);
             goto err;
         }
         ciphers = NULL;
@@ -1864,7 +1924,7 @@ static int tls_early_post_process_client_hello(SSL *s, int *pal)
         s->session->compress_meth = (comp == NULL) ? 0 : comp->id;
 #endif
         if (!tls1_set_server_sigalgs(s)) {
-            SSLerr(SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT);
+            /* SSLfatal() already called */
             goto err;
         }
     }
@@ -1876,9 +1936,6 @@ static int tls_early_post_process_client_hello(SSL *s, int *pal)
     s->clienthello = NULL;
     return 1;
  err:
-    ossl_statem_set_error(s);
-    *pal = al;
-
     sk_SSL_CIPHER_free(ciphers);
     sk_SSL_CIPHER_free(scsvs);
     OPENSSL_free(clienthello->pre_proc_exts);
@@ -1890,9 +1947,9 @@ static int tls_early_post_process_client_hello(SSL *s, int *pal)
 
 /*
  * Call the status request callback if needed. Upon success, returns 1.
- * Upon failure, returns 0 and sets |*al| to the appropriate fatal alert.
+ * Upon failure, returns 0.
  */
-static int tls_handle_status_request(SSL *s, int *al)
+static int tls_handle_status_request(SSL *s)
 {
     s->ext.status_expected = 0;
 
@@ -1927,7 +1984,9 @@ static int tls_handle_status_request(SSL *s, int *al)
                 /* something bad happened */
             case SSL_TLSEXT_ERR_ALERT_FATAL:
             default:
-                *al = SSL_AD_INTERNAL_ERROR;
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_TLS_HANDLE_STATUS_REQUEST,
+                         SSL_R_CLIENTHELLO_TLSEXT);
                 return 0;
             }
         }
@@ -1938,9 +1997,9 @@ static int tls_handle_status_request(SSL *s, int *al)
 
 /*
  * Call the alpn_select callback if needed. Upon success, returns 1.
- * Upon failure, returns 0 and sets |*al| to the appropriate fatal alert.
+ * Upon failure, returns 0.
  */
-int tls_handle_alpn(SSL *s, int *al)
+int tls_handle_alpn(SSL *s)
 {
     const unsigned char *selected = NULL;
     unsigned char selected_len = 0;
@@ -1955,7 +2014,8 @@ int tls_handle_alpn(SSL *s, int *al)
             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;
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_HANDLE_ALPN,
+                         ERR_R_INTERNAL_ERROR);
                 return 0;
             }
             s->s3->alpn_selected_len = selected_len;
@@ -1977,7 +2037,9 @@ int tls_handle_alpn(SSL *s, int *al)
                     s->session->ext.alpn_selected = OPENSSL_memdup(selected,
                                                                    selected_len);
                     if (s->session->ext.alpn_selected == NULL) {
-                        *al = SSL_AD_INTERNAL_ERROR;
+                        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                                 SSL_F_TLS_HANDLE_ALPN,
+                                 ERR_R_INTERNAL_ERROR);
                         return 0;
                     }
                     s->session->ext.alpn_selected_len = selected_len;
@@ -1986,7 +2048,8 @@ int tls_handle_alpn(SSL *s, int *al)
 
             return 1;
         } else if (r != SSL_TLSEXT_ERR_NOACK) {
-            *al = SSL_AD_NO_APPLICATION_PROTOCOL;
+            SSLfatal(s, SSL_AD_NO_APPLICATION_PROTOCOL, SSL_F_TLS_HANDLE_ALPN,
+                     SSL_R_NO_APPLICATION_PROTOCOL);
             return 0;
         }
         /*
@@ -2006,14 +2069,13 @@ int tls_handle_alpn(SSL *s, int *al)
 
 WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst)
 {
-    int al = SSL_AD_HANDSHAKE_FAILURE;
     const SSL_CIPHER *cipher;
 
     if (wst == WORK_MORE_A) {
-        int rv = tls_early_post_process_client_hello(s, &al);
+        int rv = tls_early_post_process_client_hello(s);
         if (rv == 0) {
-            /* SSLErr() was already called */
-            goto f_err;
+            /* SSLfatal() was already called */
+            goto err;
         }
         if (rv < 0)
             return WORK_MORE_A;
@@ -2025,10 +2087,10 @@ WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst)
             if (!s->hit && s->cert->cert_cb != NULL) {
                 int rv = s->cert->cert_cb(s, s->cert->cert_cb_arg);
                 if (rv == 0) {
-                    al = SSL_AD_INTERNAL_ERROR;
-                    SSLerr(SSL_F_TLS_POST_PROCESS_CLIENT_HELLO,
-                           SSL_R_CERT_CB_ERROR);
-                    goto f_err;
+                    SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                             SSL_F_TLS_POST_PROCESS_CLIENT_HELLO,
+                             SSL_R_CERT_CB_ERROR);
+                    goto err;
                 }
                 if (rv < 0) {
                     s->rwstate = SSL_X509_LOOKUP;
@@ -2043,15 +2105,18 @@ WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst)
                     ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
 
                 if (cipher == NULL) {
-                    SSLerr(SSL_F_TLS_POST_PROCESS_CLIENT_HELLO,
-                           SSL_R_NO_SHARED_CIPHER);
-                    goto f_err;
+                    SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+                             SSL_F_TLS_POST_PROCESS_CLIENT_HELLO,
+                             SSL_R_NO_SHARED_CIPHER);
+                    goto err;
                 }
                 s->s3->tmp.new_cipher = cipher;
             }
             if (!s->hit) {
-                if (!tls_choose_sigalg(s, &al))
-                    goto f_err;
+                if (!tls_choose_sigalg(s, 1)) {
+                    /* SSLfatal already called */
+                    goto err;
+                }
                 /* check whether we should disable session resumption */
                 if (s->not_resumable_session_cb != NULL)
                     s->session->not_resumable =
@@ -2083,10 +2148,9 @@ WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst)
          * Call status_request callback if needed. Has to be done after the
          * certificate callbacks etc above.
          */
-        if (!tls_handle_status_request(s, &al)) {
-            SSLerr(SSL_F_TLS_POST_PROCESS_CLIENT_HELLO,
-                   SSL_R_CLIENTHELLO_TLSEXT);
-            goto f_err;
+        if (!tls_handle_status_request(s)) {
+            /* SSLfatal() already called */
+            goto err;
         }
         /*
          * Call alpn_select callback if needed.  Has to be done after SNI and
@@ -2094,10 +2158,9 @@ WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst)
          * 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;
+        if (!SSL_IS_TLS13(s) && !tls_handle_alpn(s)) {
+            /* SSLfatal() already called */
+            goto err;
         }
 
         wst = WORK_MORE_C;
@@ -2105,39 +2168,28 @@ WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst)
 #ifndef OPENSSL_NO_SRP
     if (wst == WORK_MORE_C) {
         int ret;
-        if ((ret = ssl_check_srp_ext_ClientHello(s, &al)) < 0) {
+        if ((ret = ssl_check_srp_ext_ClientHello(s)) == 0) {
             /*
              * callback indicates further work to be done
              */
             s->rwstate = SSL_X509_LOOKUP;
             return WORK_MORE_C;
         }
-        if (ret != SSL_ERROR_NONE) {
-            /*
-             * This is not really an error but the only means to for
-             * a client to detect whether srp is supported.
-             */
-            if (al != TLS1_AD_UNKNOWN_PSK_IDENTITY)
-                SSLerr(SSL_F_TLS_POST_PROCESS_CLIENT_HELLO,
-                       SSL_R_CLIENTHELLO_TLSEXT);
-            else
-                SSLerr(SSL_F_TLS_POST_PROCESS_CLIENT_HELLO,
-                       SSL_R_PSK_IDENTITY_NOT_FOUND);
-            goto f_err;
+        if (ret < 0) {
+            /* SSLfatal() already called */
+            goto err;
         }
     }
 #endif
 
     return WORK_FINISHED_STOP;
- f_err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, al);
-    ossl_statem_set_error(s);
+ err:
     return WORK_ERROR;
 }
 
 int tls_construct_server_hello(SSL *s, WPACKET *pkt)
 {
-    int compm, al = SSL_AD_INTERNAL_ERROR;
+    int compm;
     size_t sl, len;
     int version;
 
@@ -2149,8 +2201,9 @@ int tls_construct_server_hello(SSL *s, WPACKET *pkt)
                 * tls_process_client_hello()
                 */
             || !WPACKET_memcpy(pkt, s->s3->server_random, SSL3_RANDOM_SIZE)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
-        goto err;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_SERVER_HELLO,
+                 ERR_R_INTERNAL_ERROR);
+        return 0;
     }
 
     /*-
@@ -2176,8 +2229,9 @@ int tls_construct_server_hello(SSL *s, WPACKET *pkt)
 
     sl = s->session->session_id_length;
     if (sl > sizeof(s->session->session_id)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
-        goto err;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_SERVER_HELLO,
+                 ERR_R_INTERNAL_ERROR);
+        return 0;
     }
 
     /* set up the compression method */
@@ -2199,28 +2253,25 @@ int tls_construct_server_hello(SSL *s, WPACKET *pkt)
                                          SSL_IS_TLS13(s)
                                             ? SSL_EXT_TLS1_3_SERVER_HELLO
                                             : SSL_EXT_TLS1_2_SERVER_HELLO,
-                                         NULL, 0, &al)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
-        goto err;
+                                         NULL, 0)) {
+        /* SSLfatal() already called */
+        return 0;
     }
 
     if (!(s->verify_mode & SSL_VERIFY_PEER)
             && !ssl3_digest_cached_records(s, 0)) {
-        al = SSL_AD_INTERNAL_ERROR;
-        goto err;
+        /* SSLfatal() already called */;
+        return 0;
     }
 
     return 1;
- err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, al);
-    return 0;
 }
 
 int tls_construct_server_done(SSL *s, WPACKET *pkt)
 {
     if (!s->s3->tmp.cert_request) {
         if (!ssl3_digest_cached_records(s, 0)) {
-            ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+            /* SSLfatal() already called */
             return 0;
         }
     }
@@ -2238,7 +2289,7 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
     int curve_id = 0;
 #endif
     const SIGALG_LOOKUP *lu = s->s3->tmp.sigalg;
-    int al = SSL_AD_INTERNAL_ERROR, i;
+    int i;
     unsigned long type;
     const BIGNUM *r[4];
     EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
@@ -2246,13 +2297,15 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
     size_t paramlen, paramoffset;
 
     if (!WPACKET_get_total_written(pkt, &paramoffset)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
-        goto f_err;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+        goto err;
     }
 
     if (md_ctx == NULL) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
-        goto f_err;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
+        goto err;
     }
 
     type = s->s3->tmp.new_cipher->algorithm_mkey;
@@ -2275,9 +2328,10 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
             pkdh = EVP_PKEY_new();
             if (pkdh == NULL || dhp == NULL) {
                 DH_free(dhp);
-                SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
-                       ERR_R_INTERNAL_ERROR);
-                goto f_err;
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+                         ERR_R_INTERNAL_ERROR);
+                goto err;
             }
             EVP_PKEY_assign_DH(pkdh, dhp);
             pkdhp = pkdh;
@@ -2288,35 +2342,36 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
             DH *dhp = s->cert->dh_tmp_cb(s, 0, 1024);
             pkdh = ssl_dh_to_pkey(dhp);
             if (pkdh == NULL) {
-                SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
-                       ERR_R_INTERNAL_ERROR);
-                goto f_err;
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+                         ERR_R_INTERNAL_ERROR);
+                goto err;
             }
             pkdhp = pkdh;
         }
         if (pkdhp == NULL) {
-            al = SSL_AD_INTERNAL_ERROR;
-            SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
-                   SSL_R_MISSING_TMP_DH_KEY);
-            goto f_err;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+                     SSL_R_MISSING_TMP_DH_KEY);
+            goto err;
         }
         if (!ssl_security(s, SSL_SECOP_TMP_DH,
                           EVP_PKEY_security_bits(pkdhp), 0, pkdhp)) {
-            al = SSL_AD_HANDSHAKE_FAILURE;
-            SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
-                   SSL_R_DH_KEY_TOO_SMALL);
-            goto f_err;
+            SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+                     SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+                     SSL_R_DH_KEY_TOO_SMALL);
+            goto err;
         }
         if (s->s3->tmp.pkey != NULL) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
-                   ERR_R_INTERNAL_ERROR);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+                     ERR_R_INTERNAL_ERROR);
             goto err;
         }
 
         s->s3->tmp.pkey = ssl_generate_pkey(pkdhp);
-
         if (s->s3->tmp.pkey == NULL) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_EVP_LIB);
+            /* SSLfatal() already called */
             goto err;
         }
 
@@ -2333,30 +2388,33 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
     if (type & (SSL_kECDHE | SSL_kECDHEPSK)) {
 
         if (s->s3->tmp.pkey != NULL) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
-                   ERR_R_INTERNAL_ERROR);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+                     ERR_R_INTERNAL_ERROR);
             goto err;
         }
 
         /* Get NID of appropriate shared curve */
         curve_id = tls1_shared_group(s, -2);
         if (curve_id == 0) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
-                   SSL_R_UNSUPPORTED_ELLIPTIC_CURVE);
+            SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+                     SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+                     SSL_R_UNSUPPORTED_ELLIPTIC_CURVE);
             goto err;
         }
-        s->s3->tmp.pkey = ssl_generate_pkey_group(curve_id);
+        s->s3->tmp.pkey = ssl_generate_pkey_group(s, curve_id);
         /* Generate a new key for this curve */
         if (s->s3->tmp.pkey == NULL) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_EVP_LIB);
-            goto f_err;
+            /* SSLfatal() already called */
+            goto err;
         }
 
         /* Encode the public key. */
         encodedlen = EVP_PKEY_get1_tls_encodedpoint(s->s3->tmp.pkey,
                                                     &encodedPoint);
         if (encodedlen == 0) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_EC_LIB);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_EC_LIB);
             goto err;
         }
 
@@ -2375,8 +2433,9 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
         if ((s->srp_ctx.N == NULL) ||
             (s->srp_ctx.g == NULL) ||
             (s->srp_ctx.s == NULL) || (s->srp_ctx.B == NULL)) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
-                   SSL_R_MISSING_SRP_PARAM);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+                     SSL_R_MISSING_SRP_PARAM);
             goto err;
         }
         r[0] = s->srp_ctx.N;
@@ -2386,18 +2445,19 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
     } else
 #endif
     {
-        al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
-               SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
-        goto f_err;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+                 SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
+        goto err;
     }
 
     if (((s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP)) != 0)
         || ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK)) != 0) {
         lu = NULL;
     } else if (lu == NULL) {
-        al = SSL_AD_DECODE_ERROR;
-        goto f_err;
+        SSLfatal(s, SSL_AD_DECODE_ERROR,
+                 SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+        goto err;
     }
 
 #ifndef OPENSSL_NO_PSK
@@ -2412,9 +2472,10 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
         if (len > PSK_MAX_IDENTITY_LEN
                 || !WPACKET_sub_memcpy_u16(pkt, s->cert->psk_identity_hint,
                                            len)) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
-                   ERR_R_INTERNAL_ERROR);
-            goto f_err;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+                     ERR_R_INTERNAL_ERROR);
+            goto err;
         }
     }
 #endif
@@ -2431,9 +2492,10 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
             res = WPACKET_start_sub_packet_u16(pkt);
 
         if (!res) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
-                   ERR_R_INTERNAL_ERROR);
-            goto f_err;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+                     ERR_R_INTERNAL_ERROR);
+            goto err;
         }
 
 #ifndef OPENSSL_NO_DH
@@ -2447,9 +2509,10 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
 
             if (len > 0) {
                 if (!WPACKET_allocate_bytes(pkt, len, &binval)) {
-                    SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
-                           ERR_R_INTERNAL_ERROR);
-                    goto f_err;
+                    SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                             SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+                             ERR_R_INTERNAL_ERROR);
+                    goto err;
                 }
                 memset(binval, 0, len);
             }
@@ -2457,9 +2520,10 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
 #endif
         if (!WPACKET_allocate_bytes(pkt, BN_num_bytes(r[i]), &binval)
                 || !WPACKET_close(pkt)) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
-                   ERR_R_INTERNAL_ERROR);
-            goto f_err;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+                     ERR_R_INTERNAL_ERROR);
+            goto err;
         }
 
         BN_bn2bin(r[i], binval);
@@ -2477,9 +2541,10 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
                 || !WPACKET_put_bytes_u8(pkt, 0)
                 || !WPACKET_put_bytes_u8(pkt, curve_id)
                 || !WPACKET_sub_memcpy_u8(pkt, encodedPoint, encodedlen)) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
-                   ERR_R_INTERNAL_ERROR);
-            goto f_err;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+                     ERR_R_INTERNAL_ERROR);
+            goto err;
         }
         OPENSSL_free(encodedPoint);
         encodedPoint = NULL;
@@ -2496,10 +2561,10 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
 
         if (pkey == NULL || !tls1_lookup_md(lu, &md)) {
             /* Should never happen */
-            al = SSL_AD_INTERNAL_ERROR;
-            SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
-                   ERR_R_INTERNAL_ERROR);
-            goto f_err;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+                     ERR_R_INTERNAL_ERROR);
+            goto err;
         }
         /*
          * n is the length of the params, they start at &(d[4]) and p
@@ -2508,13 +2573,18 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
 
         /* Get length of the parameters we have written above */
         if (!WPACKET_get_length(pkt, &paramlen)) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
-                   ERR_R_INTERNAL_ERROR);
-            goto f_err;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+                     ERR_R_INTERNAL_ERROR);
+            goto err;
         }
         /* send signature algorithm */
-        if (SSL_USE_SIGALGS(s) && !WPACKET_put_bytes_u16(pkt, lu->sigalg))
-                return 0;
+        if (SSL_USE_SIGALGS(s) && !WPACKET_put_bytes_u16(pkt, lu->sigalg)) {
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+                     ERR_R_INTERNAL_ERROR);
+            goto err;
+        }
         /*
          * Create the signature. We don't know the actual length of the sig
          * until after we've created it, so we reserve enough bytes for it
@@ -2524,40 +2594,40 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
         siglen = EVP_PKEY_size(pkey);
         if (!WPACKET_sub_reserve_bytes_u16(pkt, siglen, &sigbytes1)
             || EVP_DigestSignInit(md_ctx, &pctx, md, NULL, pkey) <= 0) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
-                   ERR_R_INTERNAL_ERROR);
-            goto f_err;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+                     ERR_R_INTERNAL_ERROR);
+            goto err;
         }
         if (lu->sig == EVP_PKEY_RSA_PSS) {
             if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0
                 || EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, RSA_PSS_SALTLEN_DIGEST) <= 0) {
-                SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
-                       ERR_R_EVP_LIB);
-                goto f_err;
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+                        ERR_R_EVP_LIB);
+                goto err;
             }
         }
         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;
+            /* SSLfatal() already called */
+            goto 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);
-            goto f_err;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+                     ERR_R_INTERNAL_ERROR);
+            goto err;
         }
     }
 
     EVP_MD_CTX_free(md_ctx);
     return 1;
- f_err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, al);
  err:
 #ifndef OPENSSL_NO_DH
     EVP_PKEY_free(pkdh);
@@ -2571,22 +2641,20 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
 
 int tls_construct_certificate_request(SSL *s, WPACKET *pkt)
 {
-    int al = SSL_AD_INTERNAL_ERROR;
-
     if (SSL_IS_TLS13(s)) {
         /* TODO(TLS1.3) for now send empty request context */
         if (!WPACKET_put_bytes_u8(pkt, 0)) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST,
-                   ERR_R_INTERNAL_ERROR);
-            goto err;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST,
+                     ERR_R_INTERNAL_ERROR);
+            return 0;
         }
 
         if (!tls_construct_extensions(s, pkt,
                                       SSL_EXT_TLS1_3_CERTIFICATE_REQUEST, NULL,
-                                      0, &al)) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST,
-                   ERR_R_INTERNAL_ERROR);
-            goto err;
+                                      0)) {
+            /* SSLfatal() already called */
+            return 0;
         }
         goto done;
     }
@@ -2594,8 +2662,9 @@ int tls_construct_certificate_request(SSL *s, WPACKET *pkt)
     /* get the list of acceptable cert types */
     if (!WPACKET_start_sub_packet_u8(pkt)
         || !ssl3_get_req_cert_type(s, pkt) || !WPACKET_close(pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, ERR_R_INTERNAL_ERROR);
-        goto err;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, ERR_R_INTERNAL_ERROR);
+        return 0;
     }
 
     if (SSL_USE_SIGALGS(s)) {
@@ -2606,26 +2675,24 @@ int tls_construct_certificate_request(SSL *s, WPACKET *pkt)
                 || !WPACKET_set_flags(pkt, WPACKET_FLAGS_NON_ZERO_LENGTH)
                 || !tls12_copy_sigalgs(s, pkt, psigs, nl)
                 || !WPACKET_close(pkt)) {
-            SSLerr(SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST,
-                   ERR_R_INTERNAL_ERROR);
-            goto err;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST,
+                     ERR_R_INTERNAL_ERROR);
+            return 0;
         }
     }
 
     if (!construct_ca_names(s, pkt)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, ERR_R_INTERNAL_ERROR);
-        goto err;
+        /* SSLfatal() already called */
+        return 0;
     }
 
  done:
     s->s3->tmp.cert_request = 1;
     return 1;
- err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, al);
-    return 0;
 }
 
-static int tls_process_cke_psk_preamble(SSL *s, PACKET *pkt, int *al)
+static int tls_process_cke_psk_preamble(SSL *s, PACKET *pkt)
 {
 #ifndef OPENSSL_NO_PSK
     unsigned char psk[PSK_MAX_PSK_LEN];
@@ -2633,24 +2700,24 @@ static int tls_process_cke_psk_preamble(SSL *s, PACKET *pkt, int *al)
     PACKET psk_identity;
 
     if (!PACKET_get_length_prefixed_2(pkt, &psk_identity)) {
-        *al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, SSL_R_LENGTH_MISMATCH);
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
+                 SSL_R_LENGTH_MISMATCH);
         return 0;
     }
     if (PACKET_remaining(&psk_identity) > PSK_MAX_IDENTITY_LEN) {
-        *al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, SSL_R_DATA_LENGTH_TOO_LONG);
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
+                 SSL_R_DATA_LENGTH_TOO_LONG);
         return 0;
     }
     if (s->psk_server_callback == NULL) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, SSL_R_PSK_NO_SERVER_CB);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
+                 SSL_R_PSK_NO_SERVER_CB);
         return 0;
     }
 
     if (!PACKET_strndup(&psk_identity, &s->session->psk_identity)) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
@@ -2658,16 +2725,16 @@ static int tls_process_cke_psk_preamble(SSL *s, PACKET *pkt, int *al)
                                     psk, sizeof(psk));
 
     if (psklen > PSK_MAX_PSK_LEN) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
     } else if (psklen == 0) {
         /*
          * PSK related to the given identity not found
          */
-        *al = SSL_AD_UNKNOWN_PSK_IDENTITY;
-        SSLerr(SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
-               SSL_R_PSK_IDENTITY_NOT_FOUND);
+        SSLfatal(s, SSL_AD_UNKNOWN_PSK_IDENTITY,
+                 SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
+                 SSL_R_PSK_IDENTITY_NOT_FOUND);
         return 0;
     }
 
@@ -2676,8 +2743,8 @@ static int tls_process_cke_psk_preamble(SSL *s, PACKET *pkt, int *al)
     OPENSSL_cleanse(psk, psklen);
 
     if (s->s3->tmp.psk == NULL) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, ERR_R_MALLOC_FAILURE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, ERR_R_MALLOC_FAILURE);
         return 0;
     }
 
@@ -2686,13 +2753,13 @@ static int tls_process_cke_psk_preamble(SSL *s, PACKET *pkt, int *al)
     return 1;
 #else
     /* Should never happen */
-    *al = SSL_AD_INTERNAL_ERROR;
-    SSLerr(SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
+    SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
+             ERR_R_INTERNAL_ERROR);
     return 0;
 #endif
 }
 
-static int tls_process_cke_rsa(SSL *s, PACKET *pkt, int *al)
+static int tls_process_cke_rsa(SSL *s, PACKET *pkt)
 {
 #ifndef OPENSSL_NO_RSA
     unsigned char rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH];
@@ -2706,8 +2773,8 @@ static int tls_process_cke_rsa(SSL *s, PACKET *pkt, int *al)
 
     rsa = EVP_PKEY_get0_RSA(s->cert->pkeys[SSL_PKEY_RSA].privatekey);
     if (rsa == NULL) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CKE_RSA, SSL_R_MISSING_RSA_CERTIFICATE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
+                 SSL_R_MISSING_RSA_CERTIFICATE);
         return 0;
     }
 
@@ -2717,8 +2784,8 @@ static int tls_process_cke_rsa(SSL *s, PACKET *pkt, int *al)
     } else {
         if (!PACKET_get_length_prefixed_2(pkt, &enc_premaster)
             || PACKET_remaining(pkt) != 0) {
-            *al = SSL_AD_DECODE_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_CKE_RSA, SSL_R_LENGTH_MISMATCH);
+            SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
+                     SSL_R_LENGTH_MISMATCH);
             return 0;
         }
     }
@@ -2730,15 +2797,15 @@ static int tls_process_cke_rsa(SSL *s, PACKET *pkt, int *al)
      * their ciphertext cannot accommodate a premaster secret anyway.
      */
     if (RSA_size(rsa) < SSL_MAX_MASTER_KEY_LENGTH) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CKE_RSA, RSA_R_KEY_SIZE_TOO_SMALL);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
+                 RSA_R_KEY_SIZE_TOO_SMALL);
         return 0;
     }
 
     rsa_decrypt = OPENSSL_malloc(RSA_size(rsa));
     if (rsa_decrypt == NULL) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CKE_RSA, ERR_R_MALLOC_FAILURE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
+                 ERR_R_MALLOC_FAILURE);
         return 0;
     }
 
@@ -2750,8 +2817,12 @@ static int tls_process_cke_rsa(SSL *s, PACKET *pkt, int *al)
      * fails. See https://tools.ietf.org/html/rfc5246#section-7.4.7.1
      */
 
-    if (ssl_randbytes(s, rand_premaster_secret, sizeof(rand_premaster_secret)) <= 0)
+    if (ssl_randbytes(s, rand_premaster_secret,
+                      sizeof(rand_premaster_secret)) <= 0) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
+    }
 
     /*
      * Decrypt with no padding. PKCS#1 padding will be removed as part of
@@ -2761,8 +2832,11 @@ static int tls_process_cke_rsa(SSL *s, PACKET *pkt, int *al)
     decrypt_len = (int)RSA_private_decrypt((int)PACKET_remaining(&enc_premaster),
                                            PACKET_data(&enc_premaster),
                                            rsa_decrypt, rsa, RSA_NO_PADDING);
-    if (decrypt_len < 0)
+    if (decrypt_len < 0) {
+        SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
+    }
 
     /* Check the padding. See RFC 3447, section 7.2.2. */
 
@@ -2772,8 +2846,8 @@ static int tls_process_cke_rsa(SSL *s, PACKET *pkt, int *al)
      * PS is at least 8 bytes.
      */
     if (decrypt_len < 11 + SSL_MAX_MASTER_KEY_LENGTH) {
-        *al = SSL_AD_DECRYPT_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CKE_RSA, SSL_R_DECRYPTION_FAILED);
+        SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
+                 SSL_R_DECRYPTION_FAILED);
         goto err;
     }
 
@@ -2840,8 +2914,7 @@ static int tls_process_cke_rsa(SSL *s, PACKET *pkt, int *al)
 
     if (!ssl_generate_master_secret(s, rsa_decrypt + padding_len,
                                     sizeof(rand_premaster_secret), 0)) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CKE_RSA, ERR_R_INTERNAL_ERROR);
+        /* SSLfatal() already called */
         goto err;
     }
 
@@ -2851,13 +2924,13 @@ static int tls_process_cke_rsa(SSL *s, PACKET *pkt, int *al)
     return ret;
 #else
     /* Should never happen */
-    *al = SSL_AD_INTERNAL_ERROR;
-    SSLerr(SSL_F_TLS_PROCESS_CKE_RSA, ERR_R_INTERNAL_ERROR);
+    SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
+             ERR_R_INTERNAL_ERROR);
     return 0;
 #endif
 }
 
-static int tls_process_cke_dhe(SSL *s, PACKET *pkt, int *al)
+static int tls_process_cke_dhe(SSL *s, PACKET *pkt)
 {
 #ifndef OPENSSL_NO_DH
     EVP_PKEY *skey = NULL;
@@ -2869,47 +2942,47 @@ static int tls_process_cke_dhe(SSL *s, PACKET *pkt, int *al)
     int ret = 0;
 
     if (!PACKET_get_net_2(pkt, &i) || PACKET_remaining(pkt) != i) {
-        *al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CKE_DHE,
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
                SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG);
         goto err;
     }
     skey = s->s3->tmp.pkey;
     if (skey == NULL) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CKE_DHE, SSL_R_MISSING_TMP_DH_KEY);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
+                 SSL_R_MISSING_TMP_DH_KEY);
         goto err;
     }
 
     if (PACKET_remaining(pkt) == 0L) {
-        *al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CKE_DHE, SSL_R_MISSING_TMP_DH_KEY);
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
+                 SSL_R_MISSING_TMP_DH_KEY);
         goto err;
     }
     if (!PACKET_get_bytes(pkt, &data, i)) {
         /* We already checked we have enough data */
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CKE_DHE, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
     }
     ckey = EVP_PKEY_new();
     if (ckey == NULL || EVP_PKEY_copy_parameters(ckey, skey) == 0) {
-        SSLerr(SSL_F_TLS_PROCESS_CKE_DHE, SSL_R_BN_LIB);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
+                 SSL_R_BN_LIB);
         goto err;
     }
     cdh = EVP_PKEY_get0_DH(ckey);
     pub_key = BN_bin2bn(data, i, NULL);
 
     if (pub_key == NULL || !DH_set0_key(cdh, pub_key, NULL)) {
-        SSLerr(SSL_F_TLS_PROCESS_CKE_DHE, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
+                 ERR_R_INTERNAL_ERROR);
         if (pub_key != NULL)
             BN_free(pub_key);
         goto err;
     }
 
     if (ssl_derive(s, skey, ckey, 1) == 0) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CKE_DHE, ERR_R_INTERNAL_ERROR);
+        /* SSLfatal() already called */
         goto err;
     }
 
@@ -2921,13 +2994,13 @@ static int tls_process_cke_dhe(SSL *s, PACKET *pkt, int *al)
     return ret;
 #else
     /* Should never happen */
-    *al = SSL_AD_INTERNAL_ERROR;
-    SSLerr(SSL_F_TLS_PROCESS_CKE_DHE, ERR_R_INTERNAL_ERROR);
+    SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
+             ERR_R_INTERNAL_ERROR);
     return 0;
 #endif
 }
 
-static int tls_process_cke_ecdhe(SSL *s, PACKET *pkt, int *al)
+static int tls_process_cke_ecdhe(SSL *s, PACKET *pkt)
 {
 #ifndef OPENSSL_NO_EC
     EVP_PKEY *skey = s->s3->tmp.pkey;
@@ -2936,8 +3009,8 @@ static int tls_process_cke_ecdhe(SSL *s, PACKET *pkt, int *al)
 
     if (PACKET_remaining(pkt) == 0L) {
         /* We don't support ECDH client auth */
-        *al = SSL_AD_HANDSHAKE_FAILURE;
-        SSLerr(SSL_F_TLS_PROCESS_CKE_ECDHE, SSL_R_MISSING_TMP_ECDH_KEY);
+        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PROCESS_CKE_ECDHE,
+                 SSL_R_MISSING_TMP_ECDH_KEY);
         goto err;
     } else {
         unsigned int i;
@@ -2951,25 +3024,25 @@ static int tls_process_cke_ecdhe(SSL *s, PACKET *pkt, int *al)
         /* Get encoded point length */
         if (!PACKET_get_1(pkt, &i) || !PACKET_get_bytes(pkt, &data, i)
             || PACKET_remaining(pkt) != 0) {
-            *al = SSL_AD_DECODE_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_CKE_ECDHE, SSL_R_LENGTH_MISMATCH);
+            SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE,
+                     SSL_R_LENGTH_MISMATCH);
             goto err;
         }
         ckey = EVP_PKEY_new();
         if (ckey == NULL || EVP_PKEY_copy_parameters(ckey, skey) <= 0) {
-            SSLerr(SSL_F_TLS_PROCESS_CKE_ECDHE, ERR_R_EVP_LIB);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE,
+                     ERR_R_EVP_LIB);
             goto err;
         }
         if (EVP_PKEY_set1_tls_encodedpoint(ckey, data, i) == 0) {
-            *al = SSL_AD_ILLEGAL_PARAMETER;
-            SSLerr(SSL_F_TLS_PROCESS_CKE_ECDHE, ERR_R_EC_LIB);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE,
+                     ERR_R_EC_LIB);
             goto err;
         }
     }
 
     if (ssl_derive(s, skey, ckey, 1) == 0) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CKE_ECDHE, ERR_R_INTERNAL_ERROR);
+        /* SSLfatal() already called */
         goto err;
     }
 
@@ -2982,13 +3055,13 @@ static int tls_process_cke_ecdhe(SSL *s, PACKET *pkt, int *al)
     return ret;
 #else
     /* Should never happen */
-    *al = SSL_AD_INTERNAL_ERROR;
-    SSLerr(SSL_F_TLS_PROCESS_CKE_ECDHE, ERR_R_INTERNAL_ERROR);
+    SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE,
+             ERR_R_INTERNAL_ERROR);
     return 0;
 #endif
 }
 
-static int tls_process_cke_srp(SSL *s, PACKET *pkt, int *al)
+static int tls_process_cke_srp(SSL *s, PACKET *pkt)
 {
 #ifndef OPENSSL_NO_SRP
     unsigned int i;
@@ -2996,42 +3069,43 @@ static int tls_process_cke_srp(SSL *s, PACKET *pkt, int *al)
 
     if (!PACKET_get_net_2(pkt, &i)
         || !PACKET_get_bytes(pkt, &data, i)) {
-        *al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CKE_SRP, SSL_R_BAD_SRP_A_LENGTH);
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_SRP,
+                 SSL_R_BAD_SRP_A_LENGTH);
         return 0;
     }
     if ((s->srp_ctx.A = BN_bin2bn(data, i, NULL)) == NULL) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CKE_SRP, ERR_R_BN_LIB);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_SRP,
+                 ERR_R_BN_LIB);
         return 0;
     }
     if (BN_ucmp(s->srp_ctx.A, s->srp_ctx.N) >= 0 || BN_is_zero(s->srp_ctx.A)) {
-        *al = SSL_AD_ILLEGAL_PARAMETER;
-        SSLerr(SSL_F_TLS_PROCESS_CKE_SRP, SSL_R_BAD_SRP_PARAMETERS);
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_CKE_SRP,
+                 SSL_R_BAD_SRP_PARAMETERS);
         return 0;
     }
     OPENSSL_free(s->session->srp_username);
     s->session->srp_username = OPENSSL_strdup(s->srp_ctx.login);
     if (s->session->srp_username == NULL) {
-        SSLerr(SSL_F_TLS_PROCESS_CKE_SRP, ERR_R_MALLOC_FAILURE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_SRP,
+                 ERR_R_MALLOC_FAILURE);
         return 0;
     }
 
     if (!srp_generate_server_master_secret(s)) {
-        SSLerr(SSL_F_TLS_PROCESS_CKE_SRP, ERR_R_INTERNAL_ERROR);
+        /* SSLfatal() already called */
         return 0;
     }
 
     return 1;
 #else
     /* Should never happen */
-    *al = SSL_AD_INTERNAL_ERROR;
-    SSLerr(SSL_F_TLS_PROCESS_CKE_SRP, ERR_R_INTERNAL_ERROR);
+    SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_SRP,
+             ERR_R_INTERNAL_ERROR);
     return 0;
 #endif
 }
 
-static int tls_process_cke_gost(SSL *s, PACKET *pkt, int *al)
+static int tls_process_cke_gost(SSL *s, PACKET *pkt)
 {
 #ifndef OPENSSL_NO_GOST
     EVP_PKEY_CTX *pkey_ctx;
@@ -3065,13 +3139,13 @@ static int tls_process_cke_gost(SSL *s, PACKET *pkt, int *al)
 
     pkey_ctx = EVP_PKEY_CTX_new(pk, NULL);
     if (pkey_ctx == NULL) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CKE_GOST, ERR_R_MALLOC_FAILURE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
+                 ERR_R_MALLOC_FAILURE);
         return 0;
     }
     if (EVP_PKEY_decrypt_init(pkey_ctx) <= 0) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CKE_GOST, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
     }
     /*
@@ -3088,36 +3162,35 @@ static int tls_process_cke_gost(SSL *s, PACKET *pkt, int *al)
     /* Decrypt session key */
     sess_key_len = PACKET_remaining(pkt);
     if (!PACKET_get_bytes(pkt, &data, sess_key_len)) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CKE_GOST, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
+                 ERR_R_INTERNAL_ERROR);
         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) {
-        *al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CKE_GOST, SSL_R_DECRYPTION_FAILED);
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
+                 SSL_R_DECRYPTION_FAILED);
         goto err;
     }
     start = data;
     inlen = Tlen;
-    if (EVP_PKEY_decrypt
-        (pkey_ctx, premaster_secret, &outlen, start, inlen) <= 0) {
-        *al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CKE_GOST, SSL_R_DECRYPTION_FAILED);
+    if (EVP_PKEY_decrypt(pkey_ctx, premaster_secret, &outlen, start,
+                         inlen) <= 0) {
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
+                 SSL_R_DECRYPTION_FAILED);
         goto err;
     }
     /* Generate master secret */
     if (!ssl_generate_master_secret(s, premaster_secret,
                                     sizeof(premaster_secret), 0)) {
-        *al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CKE_GOST, ERR_R_INTERNAL_ERROR);
+        /* SSLfatal() already called */
         goto err;
     }
     /* Check if pubkey from client certificate was used */
-    if (EVP_PKEY_CTX_ctrl
-        (pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, NULL) > 0)
+    if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2,
+                          NULL) > 0)
         s->statem.no_cert_verify = 1;
 
     ret = 1;
@@ -3126,68 +3199,75 @@ static int tls_process_cke_gost(SSL *s, PACKET *pkt, int *al)
     return ret;
 #else
     /* Should never happen */
-    *al = SSL_AD_INTERNAL_ERROR;
-    SSLerr(SSL_F_TLS_PROCESS_CKE_GOST, ERR_R_INTERNAL_ERROR);
+    SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
+             ERR_R_INTERNAL_ERROR);
     return 0;
 #endif
 }
 
 MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt)
 {
-    int al = -1;
     unsigned long alg_k;
 
     alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
 
     /* For PSK parse and retrieve identity, obtain PSK key */
-    if ((alg_k & SSL_PSK) && !tls_process_cke_psk_preamble(s, pkt, &al))
+    if ((alg_k & SSL_PSK) && !tls_process_cke_psk_preamble(s, pkt)) {
+        /* SSLfatal() already called */
         goto err;
+    }
 
     if (alg_k & SSL_kPSK) {
         /* Identity extracted earlier: should be nothing left */
         if (PACKET_remaining(pkt) != 0) {
-            al = SSL_AD_DECODE_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE,
-                   SSL_R_LENGTH_MISMATCH);
+            SSLfatal(s, SSL_AD_DECODE_ERROR,
+                     SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE,
+                     SSL_R_LENGTH_MISMATCH);
             goto err;
         }
         /* PSK handled by ssl_generate_master_secret */
         if (!ssl_generate_master_secret(s, NULL, 0, 0)) {
-            al = SSL_AD_INTERNAL_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+            /* SSLfatal() already called */
             goto err;
         }
     } else if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) {
-        if (!tls_process_cke_rsa(s, pkt, &al))
+        if (!tls_process_cke_rsa(s, pkt)) {
+            /* SSLfatal() already called */
             goto err;
+        }
     } else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
-        if (!tls_process_cke_dhe(s, pkt, &al))
+        if (!tls_process_cke_dhe(s, pkt)) {
+            /* SSLfatal() already called */
             goto err;
+        }
     } else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
-        if (!tls_process_cke_ecdhe(s, pkt, &al))
+        if (!tls_process_cke_ecdhe(s, pkt)) {
+            /* SSLfatal() already called */
             goto err;
+        }
     } else if (alg_k & SSL_kSRP) {
-        if (!tls_process_cke_srp(s, pkt, &al))
+        if (!tls_process_cke_srp(s, pkt)) {
+            /* SSLfatal() already called */
             goto err;
+        }
     } else if (alg_k & SSL_kGOST) {
-        if (!tls_process_cke_gost(s, pkt, &al))
+        if (!tls_process_cke_gost(s, pkt)) {
+            /* SSLfatal() already called */
             goto err;
+        }
     } else {
-        al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE,
-               SSL_R_UNKNOWN_CIPHER_TYPE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE,
+                 SSL_R_UNKNOWN_CIPHER_TYPE);
         goto err;
     }
 
     return MSG_PROCESS_CONTINUE_PROCESSING;
  err:
-    if (al != -1)
-        ssl3_send_alert(s, SSL3_AL_FATAL, al);
 #ifndef OPENSSL_NO_PSK
     OPENSSL_clear_free(s->s3->tmp.psk, s->s3->tmp.psklen);
     s->s3->tmp.psk = NULL;
 #endif
-    ossl_statem_set_error(s);
     return MSG_PROCESS_ERROR;
 }
 
@@ -3209,7 +3289,9 @@ WORK_STATE tls_post_process_client_key_exchange(SSL *s, WORK_STATE wst)
                                            sizeof(sctpauthkey), labelbuffer,
                                            sizeof(labelbuffer), NULL, 0,
                                            0) <= 0) {
-                ossl_statem_set_error(s);
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE,
+                         ERR_R_INTERNAL_ERROR);
                 return WORK_ERROR;
             }
 
@@ -3225,15 +3307,15 @@ WORK_STATE tls_post_process_client_key_exchange(SSL *s, WORK_STATE wst)
          * the handshake_buffer
          */
         if (!ssl3_digest_cached_records(s, 0)) {
-            ossl_statem_set_error(s);
+            /* SSLfatal() already called */
             return WORK_ERROR;
         }
         return WORK_FINISHED_CONTINUE;
     } else {
         if (!s->s3->handshake_buffer) {
-            SSLerr(SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE,
-                   ERR_R_INTERNAL_ERROR);
-            ossl_statem_set_error(s);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE,
+                     ERR_R_INTERNAL_ERROR);
             return WORK_ERROR;
         }
         /*
@@ -3241,7 +3323,7 @@ WORK_STATE tls_post_process_client_key_exchange(SSL *s, WORK_STATE wst)
          * extms we've done this already so this is a no-op
          */
         if (!ssl3_digest_cached_records(s, 1)) {
-            ossl_statem_set_error(s);
+            /* SSLfatal() already called */
             return WORK_ERROR;
         }
     }
@@ -3251,7 +3333,7 @@ WORK_STATE tls_post_process_client_key_exchange(SSL *s, WORK_STATE wst)
 
 MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
 {
-    int i, al = SSL_AD_INTERNAL_ERROR;
+    int i;
     MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR;
     X509 *x = NULL;
     unsigned long l, llen;
@@ -3261,8 +3343,9 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
     size_t chainidx;
 
     if ((sk = sk_X509_new_null()) == NULL) {
-        SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, ERR_R_MALLOC_FAILURE);
-        goto f_err;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
+                 ERR_R_MALLOC_FAILURE);
+        goto err;
     }
 
     /* TODO(TLS1.3): For now we ignore the context. We need to verify this */
@@ -3270,31 +3353,32 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
             || !PACKET_get_net_3(pkt, &llen)
             || !PACKET_get_sub_packet(pkt, &spkt, llen)
             || PACKET_remaining(pkt) != 0) {
-        al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, SSL_R_LENGTH_MISMATCH);
-        goto f_err;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
+                 SSL_R_LENGTH_MISMATCH);
+        goto err;
     }
 
     for (chainidx = 0; PACKET_remaining(&spkt) > 0; chainidx++) {
         if (!PACKET_get_net_3(&spkt, &l)
             || !PACKET_get_bytes(&spkt, &certbytes, l)) {
-            al = SSL_AD_DECODE_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
-                   SSL_R_CERT_LENGTH_MISMATCH);
-            goto f_err;
+            SSLfatal(s, SSL_AD_DECODE_ERROR,
+                     SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
+                     SSL_R_CERT_LENGTH_MISMATCH);
+            goto err;
         }
 
         certstart = certbytes;
         x = d2i_X509(NULL, (const unsigned char **)&certbytes, l);
         if (x == NULL) {
-            SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, ERR_R_ASN1_LIB);
-            goto f_err;
+            SSLfatal(s, SSL_AD_DECODE_ERROR,
+                     SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, ERR_R_ASN1_LIB);
+            goto err;
         }
         if (certbytes != (certstart + l)) {
-            al = SSL_AD_DECODE_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
-                   SSL_R_CERT_LENGTH_MISMATCH);
-            goto f_err;
+            SSLfatal(s, SSL_AD_DECODE_ERROR,
+                     SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
+                     SSL_R_CERT_LENGTH_MISMATCH);
+            goto err;
         }
 
         if (SSL_IS_TLS13(s)) {
@@ -3302,25 +3386,28 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
             PACKET extensions;
 
             if (!PACKET_get_length_prefixed_2(&spkt, &extensions)) {
-                al = SSL_AD_DECODE_ERROR;
-                SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, SSL_R_BAD_LENGTH);
-                goto f_err;
+                SSLfatal(s, SSL_AD_DECODE_ERROR,
+                         SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
+                         SSL_R_BAD_LENGTH);
+                goto err;
             }
             if (!tls_collect_extensions(s, &extensions,
                                         SSL_EXT_TLS1_3_CERTIFICATE, &rawexts,
-                                        &al, NULL, chainidx == 0)
+                                        NULL, chainidx == 0)
                 || !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_CERTIFICATE,
-                                             rawexts, x, chainidx, &al,
+                                             rawexts, x, chainidx,
                                              PACKET_remaining(&spkt) == 0)) {
                 OPENSSL_free(rawexts);
-                goto f_err;
+                goto err;
             }
             OPENSSL_free(rawexts);
         }
 
         if (!sk_X509_push(sk, x)) {
-            SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, ERR_R_MALLOC_FAILURE);
-            goto f_err;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
+                     ERR_R_MALLOC_FAILURE);
+            goto err;
         }
         x = NULL;
     }
@@ -3328,43 +3415,44 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
     if (sk_X509_num(sk) <= 0) {
         /* TLS does not mind 0 certs returned */
         if (s->version == SSL3_VERSION) {
-            al = SSL_AD_HANDSHAKE_FAILURE;
-            SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
-                   SSL_R_NO_CERTIFICATES_RETURNED);
-            goto f_err;
+            SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+                     SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
+                     SSL_R_NO_CERTIFICATES_RETURNED);
+            goto err;
         }
         /* Fail for TLS only if we required a certificate */
         else if ((s->verify_mode & SSL_VERIFY_PEER) &&
                  (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) {
-            SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
-                   SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
-            al = SSL_AD_CERTIFICATE_REQUIRED;
-            goto f_err;
+            SSLfatal(s, SSL_AD_CERTIFICATE_REQUIRED,
+                     SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
+                     SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
+            goto err;
         }
         /* No client certificate so digest cached records */
         if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s, 0)) {
-            goto f_err;
+            /* SSLfatal() already called */
+            goto err;
         }
     } else {
         EVP_PKEY *pkey;
         i = ssl_verify_cert_chain(s, sk);
         if (i <= 0) {
-            al = ssl_verify_alarm_type(s->verify_result);
-            SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
-                   SSL_R_CERTIFICATE_VERIFY_FAILED);
-            goto f_err;
+            SSLfatal(s, ssl_verify_alarm_type(s->verify_result),
+                     SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
+                     SSL_R_CERTIFICATE_VERIFY_FAILED);
+            goto err;
         }
         if (i > 1) {
-            SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, i);
-            al = SSL_AD_HANDSHAKE_FAILURE;
-            goto f_err;
+            SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+                     SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, i);
+            goto err;
         }
         pkey = X509_get0_pubkey(sk_X509_value(sk, 0));
         if (pkey == NULL) {
-            al = SSL3_AD_HANDSHAKE_FAILURE;
-            SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
-                   SSL_R_UNKNOWN_CERTIFICATE_TYPE);
-            goto f_err;
+            SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+                     SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
+                     SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+            goto err;
         }
     }
 
@@ -3380,9 +3468,8 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
      * message
      */
     if (SSL_IS_TLS13(s) && !ssl3_digest_cached_records(s, 1)) {
-        al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR);
-        goto f_err;
+        /* SSLfatal() already called */
+        goto err;
     }
 
     /*
@@ -3396,18 +3483,13 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
             && !ssl_handshake_hash(s, s->cert_verify_hash,
                                    sizeof(s->cert_verify_hash),
                                    &s->cert_verify_hash_len)) {
-        al = SSL_AD_INTERNAL_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR);
-        goto f_err;
+        /* SSLfatal() already called */
+        goto err;
     }
 
     ret = MSG_PROCESS_CONTINUE_READING;
-    goto done;
 
- f_err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, al);
-    ossl_statem_set_error(s);
- done:
+ err:
     X509_free(x);
     sk_X509_pop_free(sk, X509_free);
     return ret;
@@ -3416,10 +3498,10 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
 int tls_construct_server_certificate(SSL *s, WPACKET *pkt)
 {
     CERT_PKEY *cpk = s->s3->tmp.cert;
-    int al = SSL_AD_INTERNAL_ERROR;
 
     if (cpk == NULL) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
@@ -3427,10 +3509,13 @@ int tls_construct_server_certificate(SSL *s, WPACKET *pkt)
      * In TLSv1.3 the certificate chain is always preceded by a 0 length context
      * for the server Certificate message
      */
-    if ((SSL_IS_TLS13(s) && !WPACKET_put_bytes_u8(pkt, 0))
-            || !ssl3_output_cert_chain(s, pkt, cpk, &al)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR);
-        ssl3_send_alert(s, SSL3_AL_FATAL, al);
+    if (SSL_IS_TLS13(s) && !WPACKET_put_bytes_u8(pkt, 0)) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+    if (!ssl3_output_cert_chain(s, pkt, cpk)) {
+        /* SSLfatal() already called */
         return 0;
     }
 
@@ -3450,7 +3535,7 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
     SSL_CTX *tctx = s->session_ctx;
     unsigned char iv[EVP_MAX_IV_LENGTH];
     unsigned char key_name[TLSEXT_KEYNAME_LENGTH];
-    int iv_len, al = SSL_AD_INTERNAL_ERROR;
+    int iv_len;
     size_t macoffset, macendoffset;
     union {
         unsigned char age_add_c[sizeof(uint32_t)];
@@ -3458,8 +3543,12 @@ 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)
+        if (ssl_randbytes(s, 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);
             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
@@ -3469,8 +3558,9 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
         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);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
+                     ERR_R_MALLOC_FAILURE);
             goto err;
         }
         s->session->ext.tick_nonce_len = 1;
@@ -3480,8 +3570,9 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
             s->session->ext.alpn_selected =
                 OPENSSL_memdup(s->s3->alpn_selected, s->s3->alpn_selected_len);
             if (s->session->ext.alpn_selected == NULL) {
-                SSLerr(SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
-                       ERR_R_MALLOC_FAILURE);
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
+                         ERR_R_MALLOC_FAILURE);
                 goto err;
             }
             s->session->ext.alpn_selected_len = s->s3->alpn_selected_len;
@@ -3496,42 +3587,56 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
      * long
      */
     if (slen_full == 0 || slen_full > 0xFF00) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
         goto err;
     }
     senc = OPENSSL_malloc(slen_full);
     if (senc == NULL) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
     ctx = EVP_CIPHER_CTX_new();
     hctx = HMAC_CTX_new();
     if (ctx == NULL || hctx == NULL) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
     p = senc;
-    if (!i2d_SSL_SESSION(s->session, &p))
+    if (!i2d_SSL_SESSION(s->session, &p)) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
         goto err;
+    }
 
     /*
      * create a fresh copy (not shared with other threads) to clean up
      */
     const_p = senc;
     sess = d2i_SSL_SESSION(NULL, &const_p, slen_full);
-    if (sess == NULL)
+    if (sess == NULL) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 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) { /* shouldn't ever happen */
+    if (slen == 0 || slen > slen_full) {
+        /* shouldn't ever happen */
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
         SSL_SESSION_free(sess);
         goto err;
     }
     p = senc;
     if (!i2d_SSL_SESSION(sess, &p)) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
         SSL_SESSION_free(sess);
         goto err;
     }
@@ -3551,8 +3656,9 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
             /* Put timeout and length */
             if (!WPACKET_put_bytes_u32(pkt, 0)
                     || !WPACKET_put_bytes_u16(pkt, 0)) {
-                SSLerr(SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
-                       ERR_R_INTERNAL_ERROR);
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
+                         ERR_R_INTERNAL_ERROR);
                 goto err;
             }
             OPENSSL_free(senc);
@@ -3560,22 +3666,28 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
             HMAC_CTX_free(hctx);
             return 1;
         }
-        if (ret < 0)
+        if (ret < 0) {
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
+                     SSL_R_CALLBACK_FAILED);
             goto err;
+        }
         iv_len = EVP_CIPHER_CTX_iv_length(ctx);
     } else {
         const EVP_CIPHER *cipher = EVP_aes_256_cbc();
 
         iv_len = EVP_CIPHER_iv_length(cipher);
-        if (ssl_randbytes(s, iv, iv_len) <= 0)
-            goto err;
-        if (!EVP_EncryptInit_ex(ctx, cipher, NULL,
-                                tctx->ext.tick_aes_key, iv))
-            goto err;
-        if (!HMAC_Init_ex(hctx, tctx->ext.tick_hmac_key,
-                          sizeof(tctx->ext.tick_hmac_key),
-                          EVP_sha256(), NULL))
+        if (ssl_randbytes(s, 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),
+                                 EVP_sha256(), NULL)) {
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                     SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
+                     ERR_R_INTERNAL_ERROR);
             goto err;
+        }
         memcpy(key_name, tctx->ext.tick_key_name,
                sizeof(tctx->ext.tick_key_name));
     }
@@ -3619,12 +3731,16 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
             || hlen > EVP_MAX_MD_SIZE
             || !WPACKET_allocate_bytes(pkt, hlen, &macdata2)
             || macdata1 != macdata2
-            || !WPACKET_close(pkt)
-            || (SSL_IS_TLS13(s)
-                && !tls_construct_extensions(s, pkt,
-                                             SSL_EXT_TLS1_3_NEW_SESSION_TICKET,
-                                             NULL, 0, &al))) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
+            || !WPACKET_close(pkt)) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 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;
     }
     EVP_CIPHER_CTX_free(ctx);
@@ -3633,11 +3749,9 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
 
     return 1;
  err:
-    ossl_statem_set_error(s);
     OPENSSL_free(senc);
     EVP_CIPHER_CTX_free(ctx);
     HMAC_CTX_free(hctx);
-    ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
     return 0;
 }
 
@@ -3650,7 +3764,8 @@ int tls_construct_cert_status_body(SSL *s, WPACKET *pkt)
     if (!WPACKET_put_bytes_u8(pkt, s->ext.status_type)
             || !WPACKET_sub_memcpy_u24(pkt, s->ext.ocsp.resp,
                                        s->ext.ocsp.resp_len)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_CERT_STATUS_BODY, ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_STATUS_BODY,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
@@ -3660,7 +3775,7 @@ int tls_construct_cert_status_body(SSL *s, WPACKET *pkt)
 int tls_construct_cert_status(SSL *s, WPACKET *pkt)
 {
     if (!tls_construct_cert_status_body(s, pkt)) {
-        ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+        /* SSLfatal() already called */
         return 0;
     }
 
@@ -3676,7 +3791,6 @@ MSG_PROCESS_RETURN tls_process_next_proto(SSL *s, PACKET *pkt)
 {
     PACKET next_proto, padding;
     size_t next_proto_len;
-    int al = SSL_AD_INTERNAL_ERROR;
 
     /*-
      * The payload looks like:
@@ -3688,34 +3802,29 @@ MSG_PROCESS_RETURN tls_process_next_proto(SSL *s, PACKET *pkt)
     if (!PACKET_get_length_prefixed_1(pkt, &next_proto)
         || !PACKET_get_length_prefixed_1(pkt, &padding)
         || PACKET_remaining(pkt) > 0) {
-        al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_NEXT_PROTO, SSL_R_LENGTH_MISMATCH);
-        goto err;
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_NEXT_PROTO,
+                 SSL_R_LENGTH_MISMATCH);
+        return MSG_PROCESS_ERROR;
     }
 
     if (!PACKET_memdup(&next_proto, &s->ext.npn, &next_proto_len)) {
         s->ext.npn_len = 0;
-        goto err;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_NEXT_PROTO,
+                 ERR_R_INTERNAL_ERROR);
+        return MSG_PROCESS_ERROR;
     }
 
     s->ext.npn_len = (unsigned char)next_proto_len;
 
     return MSG_PROCESS_CONTINUE_READING;
- err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, al);
-    ossl_statem_set_error(s);
-    return MSG_PROCESS_ERROR;
 }
 #endif
 
 static int tls_construct_encrypted_extensions(SSL *s, WPACKET *pkt)
 {
-    int al;
-
     if (!tls_construct_extensions(s, pkt, SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
-                                  NULL, 0, &al)) {
-        ssl3_send_alert(s, SSL3_AL_FATAL, al);
-        SSLerr(SSL_F_TLS_CONSTRUCT_ENCRYPTED_EXTENSIONS, ERR_R_INTERNAL_ERROR);
+                                  NULL, 0)) {
+        /* SSLfatal() already called */
         return 0;
     }
 
@@ -3724,7 +3833,6 @@ static int tls_construct_encrypted_extensions(SSL *s, WPACKET *pkt)
 
 static int tls_construct_hello_retry_request(SSL *s, WPACKET *pkt)
 {
-    int al = SSL_AD_INTERNAL_ERROR;
     size_t len = 0;
 
     /*
@@ -3732,12 +3840,17 @@ static int tls_construct_hello_retry_request(SSL *s, WPACKET *pkt)
      * (should be s->version)
      */
     if (!WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT)
-            || !s->method->put_cipher_by_char(s->s3->tmp.new_cipher, pkt, &len)
-            || !tls_construct_extensions(s, pkt,
-                                         SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST,
-                                         NULL, 0, &al)) {
-        SSLerr(SSL_F_TLS_CONSTRUCT_HELLO_RETRY_REQUEST, ERR_R_INTERNAL_ERROR);
-        goto err;
+            || !s->method->put_cipher_by_char(s->s3->tmp.new_cipher, pkt,
+                                              &len)) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS_CONSTRUCT_HELLO_RETRY_REQUEST, ERR_R_INTERNAL_ERROR);
+       return 0;
+    }
+
+    if (!tls_construct_extensions(s, pkt, SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST,
+                                  NULL, 0)) {
+        /* SSLfatal() already called */
+        return 0;
     }
 
     /* Ditch the session. We'll create a new one next time around */
@@ -3749,30 +3862,27 @@ static int tls_construct_hello_retry_request(SSL *s, WPACKET *pkt)
      * Re-initialise the Transcript Hash. We're going to prepopulate it with
      * a synthetic message_hash in place of ClientHello1.
      */
-    if (!create_synthetic_message_hash(s))
-        goto err;
+    if (!create_synthetic_message_hash(s)) {
+        /* SSLfatal() already called */
+        return 0;
+    }
 
     return 1;
- err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, al);
-    return 0;
 }
 
 MSG_PROCESS_RETURN tls_process_end_of_early_data(SSL *s, PACKET *pkt)
 {
-    int al = SSL_AD_INTERNAL_ERROR;
-
     if (PACKET_remaining(pkt) != 0) {
-        al = SSL_AD_DECODE_ERROR;
-        SSLerr(SSL_F_TLS_PROCESS_END_OF_EARLY_DATA, SSL_R_LENGTH_MISMATCH);
-        ossl_statem_set_error(s);
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_END_OF_EARLY_DATA,
+                 SSL_R_LENGTH_MISMATCH);
         return MSG_PROCESS_ERROR;
     }
 
     if (s->early_data_state != SSL_EARLY_DATA_READING
             && s->early_data_state != SSL_EARLY_DATA_READ_RETRY) {
-        SSLerr(SSL_F_TLS_PROCESS_END_OF_EARLY_DATA, ERR_R_INTERNAL_ERROR);
-        goto err;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_END_OF_EARLY_DATA,
+                 ERR_R_INTERNAL_ERROR);
+        return MSG_PROCESS_ERROR;
     }
 
     /*
@@ -3780,22 +3890,18 @@ MSG_PROCESS_RETURN tls_process_end_of_early_data(SSL *s, PACKET *pkt)
      * a record boundary.
      */
     if (RECORD_LAYER_processed_read_pending(&s->rlayer)) {
-        al = SSL_AD_UNEXPECTED_MESSAGE;
-        SSLerr(SSL_F_TLS_PROCESS_END_OF_EARLY_DATA,
-               SSL_R_NOT_ON_RECORD_BOUNDARY);
-        goto err;
+        SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
+                 SSL_F_TLS_PROCESS_END_OF_EARLY_DATA,
+                 SSL_R_NOT_ON_RECORD_BOUNDARY);
+        return MSG_PROCESS_ERROR;
     }
 
     s->early_data_state = SSL_EARLY_DATA_FINISHED_READING;
     if (!s->method->ssl3_enc->change_cipher_state(s,
                 SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_SERVER_READ)) {
-        SSLerr(SSL_F_TLS_PROCESS_END_OF_EARLY_DATA, ERR_R_INTERNAL_ERROR);
-        goto err;
+        /* SSLfatal() already called */
+        return MSG_PROCESS_ERROR;
     }
 
     return MSG_PROCESS_CONTINUE_READING;
- err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, al);
-    ossl_statem_set_error(s);
-    return MSG_PROCESS_ERROR;
 }
diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c
index 8fe2dfd..465d483 100644
--- a/ssl/t1_enc.c
+++ b/ssl/t1_enc.c
@@ -23,37 +23,39 @@ static int tls1_PRF(SSL *s,
                     const void *seed4, size_t seed4_len,
                     const void *seed5, size_t seed5_len,
                     const unsigned char *sec, size_t slen,
-                    unsigned char *out, size_t olen)
+                    unsigned char *out, size_t olen, int fatal)
 {
     const EVP_MD *md = ssl_prf_md(s);
     EVP_PKEY_CTX *pctx = NULL;
-
     int ret = 0;
 
     if (md == NULL) {
         /* Should never happen */
-        SSLerr(SSL_F_TLS1_PRF, ERR_R_INTERNAL_ERROR);
+        if (fatal)
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_PRF,
+                     ERR_R_INTERNAL_ERROR);
+        else
+            SSLerr(SSL_F_TLS1_PRF, ERR_R_INTERNAL_ERROR);
         return 0;
     }
     pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_TLS1_PRF, NULL);
     if (pctx == NULL || EVP_PKEY_derive_init(pctx) <= 0
         || EVP_PKEY_CTX_set_tls1_prf_md(pctx, md) <= 0
-        || EVP_PKEY_CTX_set1_tls1_prf_secret(pctx, sec, (int)slen) <= 0)
-        goto err;
-
-    if (EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed1, (int)seed1_len) <= 0)
-        goto err;
-    if (EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed2, (int)seed2_len) <= 0)
-        goto err;
-    if (EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed3, (int)seed3_len) <= 0)
-        goto err;
-    if (EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed4, (int)seed4_len) <= 0)
-        goto err;
-    if (EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed5, (int)seed5_len) <= 0)
+        || EVP_PKEY_CTX_set1_tls1_prf_secret(pctx, sec, (int)slen) <= 0
+        || EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed1, (int)seed1_len) <= 0
+        || EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed2, (int)seed2_len) <= 0
+        || EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed3, (int)seed3_len) <= 0
+        || EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed4, (int)seed4_len) <= 0
+        || EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed5, (int)seed5_len) <= 0
+        || EVP_PKEY_derive(pctx, out, &olen) <= 0) {
+        if (fatal)
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_PRF,
+                     ERR_R_INTERNAL_ERROR);
+        else
+            SSLerr(SSL_F_TLS1_PRF, ERR_R_INTERNAL_ERROR);
         goto err;
+    }
 
-    if (EVP_PKEY_derive(pctx, out, &olen) <= 0)
-        goto err;
     ret = 1;
 
  err:
@@ -64,12 +66,14 @@ static int tls1_PRF(SSL *s,
 static int tls1_generate_key_block(SSL *s, unsigned char *km, size_t num)
 {
     int ret;
+
+    /* Calls SSLfatal() as required */
     ret = tls1_PRF(s,
                    TLS_MD_KEY_EXPANSION_CONST,
                    TLS_MD_KEY_EXPANSION_CONST_SIZE, s->s3->server_random,
                    SSL3_RANDOM_SIZE, s->s3->client_random, SSL3_RANDOM_SIZE,
                    NULL, 0, NULL, 0, s->session->master_key,
-                   s->session->master_key_length, km, num);
+                   s->session->master_key_length, km, num, 1);
 
     return ret;
 }
@@ -113,15 +117,18 @@ int tls1_change_cipher_state(SSL *s, int which)
         else
             s->mac_flags &= ~SSL_MAC_FLAG_READ_MAC_STREAM;
 
-        if (s->enc_read_ctx != NULL)
+        if (s->enc_read_ctx != NULL) {
             reuse_dd = 1;
-        else if ((s->enc_read_ctx = EVP_CIPHER_CTX_new()) == NULL)
+        } else if ((s->enc_read_ctx = EVP_CIPHER_CTX_new()) == NULL) {
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE,
+                     ERR_R_MALLOC_FAILURE);
             goto err;
-        else
+        } else {
             /*
              * make sure it's initialised in case we exit later with an error
              */
             EVP_CIPHER_CTX_reset(s->enc_read_ctx);
+        }
         dd = s->enc_read_ctx;
         mac_ctx = ssl_replace_hash(&s->read_hash, NULL);
         if (mac_ctx == NULL)
@@ -132,9 +139,10 @@ int tls1_change_cipher_state(SSL *s, int which)
         if (comp != NULL) {
             s->expand = COMP_CTX_new(comp->method);
             if (s->expand == NULL) {
-                SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,
-                       SSL_R_COMPRESSION_LIBRARY_ERROR);
-                goto err2;
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_TLS1_CHANGE_CIPHER_STATE,
+                         SSL_R_COMPRESSION_LIBRARY_ERROR);
+                goto err;
             }
         }
 #endif
@@ -155,20 +163,31 @@ int tls1_change_cipher_state(SSL *s, int which)
             s->mac_flags |= SSL_MAC_FLAG_WRITE_MAC_STREAM;
         else
             s->mac_flags &= ~SSL_MAC_FLAG_WRITE_MAC_STREAM;
-        if (s->enc_write_ctx != NULL && !SSL_IS_DTLS(s))
+        if (s->enc_write_ctx != NULL && !SSL_IS_DTLS(s)) {
             reuse_dd = 1;
-        else if ((s->enc_write_ctx = EVP_CIPHER_CTX_new()) == NULL)
+        } else if ((s->enc_write_ctx = EVP_CIPHER_CTX_new()) == NULL) {
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE,
+                     ERR_R_MALLOC_FAILURE);
             goto err;
+        }
         dd = s->enc_write_ctx;
         if (SSL_IS_DTLS(s)) {
             mac_ctx = EVP_MD_CTX_new();
-            if (mac_ctx == NULL)
+            if (mac_ctx == NULL) {
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_TLS1_CHANGE_CIPHER_STATE,
+                         ERR_R_MALLOC_FAILURE);
                 goto err;
+            }
             s->write_hash = mac_ctx;
         } else {
             mac_ctx = ssl_replace_hash(&s->write_hash, NULL);
-            if (mac_ctx == NULL)
+            if (mac_ctx == NULL) {
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_TLS1_CHANGE_CIPHER_STATE,
+                         ERR_R_MALLOC_FAILURE);
                 goto err;
+            }
         }
 #ifndef OPENSSL_NO_COMP
         COMP_CTX_free(s->compress);
@@ -176,9 +195,10 @@ int tls1_change_cipher_state(SSL *s, int which)
         if (comp != NULL) {
             s->compress = COMP_CTX_new(comp->method);
             if (s->compress == NULL) {
-                SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,
-                       SSL_R_COMPRESSION_LIBRARY_ERROR);
-                goto err2;
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_TLS1_CHANGE_CIPHER_STATE,
+                        SSL_R_COMPRESSION_LIBRARY_ERROR);
+                goto err;
             }
         }
 #endif
@@ -227,8 +247,9 @@ int tls1_change_cipher_state(SSL *s, int which)
     }
 
     if (n > s->s3->tmp.key_block_length) {
-        SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
-        goto err2;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE,
+                 ERR_R_INTERNAL_ERROR);
+        goto err;
     }
 
     memcpy(mac_secret, ms, i);
@@ -240,8 +261,9 @@ int tls1_change_cipher_state(SSL *s, int which)
         if (mac_key == NULL
             || EVP_DigestSignInit(mac_ctx, NULL, m, NULL, mac_key) <= 0) {
             EVP_PKEY_free(mac_key);
-            SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
-            goto err2;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE,
+                     ERR_R_INTERNAL_ERROR);
+            goto err;
         }
         EVP_PKEY_free(mac_key);
     }
@@ -258,8 +280,9 @@ int tls1_change_cipher_state(SSL *s, int which)
         if (!EVP_CipherInit_ex(dd, c, NULL, key, NULL, (which & SSL3_CC_WRITE))
             || !EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_GCM_SET_IV_FIXED, (int)k,
                                     iv)) {
-            SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
-            goto err2;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE,
+                     ERR_R_INTERNAL_ERROR);
+            goto err;
         }
     } else if (EVP_CIPHER_mode(c) == EVP_CIPH_CCM_MODE) {
         int taglen;
@@ -273,21 +296,24 @@ int tls1_change_cipher_state(SSL *s, int which)
             || !EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_AEAD_SET_TAG, taglen, NULL)
             || !EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_CCM_SET_IV_FIXED, (int)k, iv)
             || !EVP_CipherInit_ex(dd, NULL, NULL, key, NULL, -1)) {
-            SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
-            goto err2;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE,
+                     ERR_R_INTERNAL_ERROR);
+            goto err;
         }
     } else {
         if (!EVP_CipherInit_ex(dd, c, NULL, key, iv, (which & SSL3_CC_WRITE))) {
-            SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
-            goto err2;
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE,
+                     ERR_R_INTERNAL_ERROR);
+            goto err;
         }
     }
     /* Needed for "composite" AEADs, such as RC4-HMAC-MD5 */
     if ((EVP_CIPHER_flags(c) & EVP_CIPH_FLAG_AEAD_CIPHER) && *mac_secret_size
         && !EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_AEAD_SET_MAC_KEY,
                                 (int)*mac_secret_size, mac_secret)) {
-        SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
-        goto err2;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE,
+                 ERR_R_INTERNAL_ERROR);
+        goto err;
     }
 
 #ifdef SSL_DEBUG
@@ -312,8 +338,6 @@ int tls1_change_cipher_state(SSL *s, int which)
     OPENSSL_cleanse(iv2, sizeof(iv2));
     return 1;
  err:
-    SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE);
- err2:
     OPENSSL_cleanse(tmp1, sizeof(tmp1));
     OPENSSL_cleanse(tmp2, sizeof(tmp1));
     OPENSSL_cleanse(iv1, sizeof(iv1));
@@ -336,7 +360,8 @@ int tls1_setup_key_block(SSL *s)
 
     if (!ssl_cipher_get_evp(s->session, &c, &hash, &mac_type, &mac_secret_size,
                             &comp, s->ext.use_etm)) {
-        SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK, SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_SETUP_KEY_BLOCK,
+                 SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
         return 0;
     }
 
@@ -350,7 +375,8 @@ int tls1_setup_key_block(SSL *s)
     ssl3_cleanup_key_block(s);
 
     if ((p = OPENSSL_malloc(num)) == NULL) {
-        SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK, ERR_R_MALLOC_FAILURE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_SETUP_KEY_BLOCK,
+                 ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
@@ -380,8 +406,10 @@ int tls1_setup_key_block(SSL *s)
                    ((z + 1) % 16) ? ' ' : '\n');
     }
 #endif
-    if (!tls1_generate_key_block(s, p, num))
+    if (!tls1_generate_key_block(s, p, num)) {
+        /* SSLfatal() already called */
         goto err;
+    }
 #ifdef SSL_DEBUG
     printf("\nkey block\n");
     {
@@ -421,16 +449,22 @@ size_t tls1_final_finish_mac(SSL *s, const char *str, size_t slen,
     size_t hashlen;
     unsigned char hash[EVP_MAX_MD_SIZE];
 
-    if (!ssl3_digest_cached_records(s, 0))
+    if (!ssl3_digest_cached_records(s, 0)) {
+        /* SSLfatal() already called */
         return 0;
+    }
 
-    if (!ssl_handshake_hash(s, hash, sizeof(hash), &hashlen))
+    if (!ssl_handshake_hash(s, hash, sizeof(hash), &hashlen)) {
+        /* SSLfatal() already called */
         return 0;
+    }
 
     if (!tls1_PRF(s, str, slen, hash, hashlen, NULL, 0, NULL, 0, NULL, 0,
                   s->session->master_key, s->session->master_key_length,
-                  out, TLS1_FINISH_MAC_LENGTH))
+                  out, TLS1_FINISH_MAC_LENGTH, 1)) {
+        /* SSLfatal() already called */
         return 0;
+    }
     OPENSSL_cleanse(hash, hashlen);
     return TLS1_FINISH_MAC_LENGTH;
 }
@@ -446,32 +480,39 @@ int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
          * affect client auth because we're freezing the buffer at the same
          * point (after client key exchange and before certificate verify)
          */
-        if (!ssl3_digest_cached_records(s, 1))
-            return 0;
-        if (!ssl_handshake_hash(s, hash, sizeof(hash), &hashlen))
+        if (!ssl3_digest_cached_records(s, 1)
+                || !ssl_handshake_hash(s, hash, sizeof(hash), &hashlen)) {
+            /* SSLfatal() already called */
             return 0;
+        }
 #ifdef SSL_DEBUG
         fprintf(stderr, "Handshake hashes:\n");
         BIO_dump_fp(stderr, (char *)hash, hashlen);
 #endif
-        tls1_PRF(s,
-                 TLS_MD_EXTENDED_MASTER_SECRET_CONST,
-                 TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE,
-                 hash, hashlen,
-                 NULL, 0,
-                 NULL, 0,
-                 NULL, 0, p, len, out,
-                 SSL3_MASTER_SECRET_SIZE);
+        if (!tls1_PRF(s,
+                      TLS_MD_EXTENDED_MASTER_SECRET_CONST,
+                      TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE,
+                      hash, hashlen,
+                      NULL, 0,
+                      NULL, 0,
+                      NULL, 0, p, len, out,
+                      SSL3_MASTER_SECRET_SIZE, 1)) {
+            /* SSLfatal() already called */
+            return 0;
+        }
         OPENSSL_cleanse(hash, hashlen);
     } else {
-        tls1_PRF(s,
-                 TLS_MD_MASTER_SECRET_CONST,
-                 TLS_MD_MASTER_SECRET_CONST_SIZE,
-                 s->s3->client_random, SSL3_RANDOM_SIZE,
-                 NULL, 0,
-                 s->s3->server_random, SSL3_RANDOM_SIZE,
-                 NULL, 0, p, len, out,
-                 SSL3_MASTER_SECRET_SIZE);
+        if (!tls1_PRF(s,
+                      TLS_MD_MASTER_SECRET_CONST,
+                      TLS_MD_MASTER_SECRET_CONST_SIZE,
+                      s->s3->client_random, SSL3_RANDOM_SIZE,
+                      NULL, 0,
+                      s->s3->server_random, SSL3_RANDOM_SIZE,
+                      NULL, 0, p, len, out,
+                      SSL3_MASTER_SECRET_SIZE, 1)) {
+           /* SSLfatal() already called */
+            return 0;
+        }
     }
 #ifdef SSL_DEBUG
     fprintf(stderr, "Premaster Secret:\n");
@@ -557,7 +598,7 @@ int tls1_export_keying_material(SSL *s, unsigned char *out, size_t olen,
                   NULL, 0,
                   NULL, 0,
                   s->session->master_key, s->session->master_key_length,
-                  out, olen);
+                  out, olen, 0);
 
     goto ret;
  err1:
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index c1db7df..9dfbb8e 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -894,7 +894,8 @@ int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey)
     if (SSL_IS_TLS13(s)) {
         /* Disallow DSA for TLS 1.3 */
         if (pkeyid == EVP_PKEY_DSA) {
-            SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE);
+            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS12_CHECK_PEER_SIGALG,
+                     SSL_R_WRONG_SIGNATURE_TYPE);
             return 0;
         }
         /* Only allow PSS for TLS 1.3 */
@@ -910,7 +911,8 @@ int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey)
         || (SSL_IS_TLS13(s) && (lu->hash == NID_sha1 || lu->hash == NID_sha224))
         || (pkeyid != lu->sig
         && (lu->sig != EVP_PKEY_RSA_PSS || pkeyid != EVP_PKEY_RSA))) {
-        SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE);
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS12_CHECK_PEER_SIGALG,
+                 SSL_R_WRONG_SIGNATURE_TYPE);
         return 0;
     }
 #ifndef OPENSSL_NO_EC
@@ -918,8 +920,9 @@ int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey)
 
         /* Check point compression is permitted */
         if (!tls1_check_pkey_comp(s, pkey)) {
-            SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG,
-                   SSL_R_ILLEGAL_POINT_COMPRESSION);
+            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+                     SSL_F_TLS12_CHECK_PEER_SIGALG,
+                     SSL_R_ILLEGAL_POINT_COMPRESSION);
             return 0;
         }
 
@@ -929,27 +932,32 @@ int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey)
             int curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
 
             if (lu->curve != NID_undef && curve != lu->curve) {
-                SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_CURVE);
+                SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+                         SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_CURVE);
                 return 0;
             }
         }
         if (!SSL_IS_TLS13(s)) {
             /* Check curve matches extensions */
             if (!tls1_check_group_id(s, tls1_get_group_id(pkey))) {
-                SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_CURVE);
+                SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+                         SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_CURVE);
                 return 0;
             }
             if (tls1_suiteb(s)) {
                 /* Check sigalg matches a permissible Suite B value */
                 if (sig != TLSEXT_SIGALG_ecdsa_secp256r1_sha256
                     && sig != TLSEXT_SIGALG_ecdsa_secp384r1_sha384) {
-                    SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG,
-                           SSL_R_WRONG_SIGNATURE_TYPE);
+                    SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
+                             SSL_F_TLS12_CHECK_PEER_SIGALG,
+                             SSL_R_WRONG_SIGNATURE_TYPE);
                     return 0;
                 }
             }
         }
     } else if (tls1_suiteb(s)) {
+        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS12_CHECK_PEER_SIGALG,
+                 SSL_R_WRONG_SIGNATURE_TYPE);
         return 0;
     }
 #endif
@@ -963,12 +971,14 @@ int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey)
     /* Allow fallback to SHA1 if not strict mode */
     if (i == sent_sigslen && (lu->hash != NID_sha1
         || s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)) {
-        SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE);
+        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS12_CHECK_PEER_SIGALG,
+                 SSL_R_WRONG_SIGNATURE_TYPE);
         return 0;
     }
     if (!tls1_lookup_md(lu, &md)) {
-            SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_UNKNOWN_DIGEST);
-            return 0;
+        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS12_CHECK_PEER_SIGALG,
+                 SSL_R_UNKNOWN_DIGEST);
+        return 0;
     }
     if (md != NULL) {
         /*
@@ -980,7 +990,8 @@ int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey)
         if (!ssl_security(s, SSL_SECOP_SIGALG_CHECK,
                     EVP_MD_size(md) * 4, EVP_MD_type(md),
                     (void *)sigalgstr)) {
-            SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE);
+            SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS12_CHECK_PEER_SIGALG,
+                     SSL_R_WRONG_SIGNATURE_TYPE);
             return 0;
         }
     }
@@ -1074,7 +1085,6 @@ int tls_use_ticket(SSL *s)
 
 int tls1_set_server_sigalgs(SSL *s)
 {
-    int al;
     size_t i;
 
     /* Clear any shared signature algorithms */
@@ -1110,17 +1120,16 @@ int tls1_set_server_sigalgs(SSL *s)
     }
 
     if (!tls1_process_sigalgs(s)) {
-        SSLerr(SSL_F_TLS1_SET_SERVER_SIGALGS, ERR_R_MALLOC_FAILURE);
-        al = SSL_AD_INTERNAL_ERROR;
-        goto err;
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_TLS1_SET_SERVER_SIGALGS, ERR_R_INTERNAL_ERROR);
+        return 0;
     }
     if (s->cert->shared_sigalgs != NULL)
         return 1;
+
     /* Fatal error if no shared signature algorithms */
-    SSLerr(SSL_F_TLS1_SET_SERVER_SIGALGS, SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS);
-    al = SSL_AD_HANDSHAKE_FAILURE;
- err:
-    ssl3_send_alert(s, SSL3_AL_FATAL, al);
+    SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS1_SET_SERVER_SIGALGS,
+             SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS);
     return 0;
 }
 
@@ -2240,14 +2249,14 @@ static int tls12_get_cert_sigalg_idx(const SSL *s, const SIGALG_LOOKUP *lu)
  * Choose an appropriate signature algorithm based on available certificates
  * Sets chosen certificate and signature algorithm.
  *
- * For servers if we fail to find a required certificate it is a fatal error
- * and an appropriate error code is set and the TLS alert set in *al.
+ * For servers if we fail to find a required certificate it is a fatal error,
+ * an appropriate error code is set and a TLS alert is sent.
  *
- * For clients al is set to NULL. If a certificate is not suitable it is not
+ * For clients fatalerrs is set to 0. If a certificate is not suitable it is not
  * a fatal error: we will either try another certificate or not present one
  * to the server. In this case no error is set.
  */
-int tls_choose_sigalg(SSL *s, int *al)
+int tls_choose_sigalg(SSL *s, int fatalerrs)
 {
     const SIGALG_LOOKUP *lu = NULL;
     int sig_idx = -1;
@@ -2298,11 +2307,10 @@ int tls_choose_sigalg(SSL *s, int *al)
             break;
         }
         if (i == s->cert->shared_sigalgslen) {
-            if (al == NULL)
+            if (!fatalerrs)
                 return 1;
-            *al = SSL_AD_HANDSHAKE_FAILURE;
-            SSLerr(SSL_F_TLS_CHOOSE_SIGALG,
-                   SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
+            SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_CHOOSE_SIGALG,
+                     SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
             return 0;
         }
     } else {
@@ -2354,10 +2362,10 @@ int tls_choose_sigalg(SSL *s, int *al)
                         break;
                 }
                 if (i == s->cert->shared_sigalgslen) {
-                    if (al == NULL)
+                    if (!fatalerrs)
                         return 1;
-                    *al = SSL_AD_INTERNAL_ERROR;
-                    SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR);
+                    SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CHOOSE_SIGALG,
+                             ERR_R_INTERNAL_ERROR);
                     return 0;
                 }
             } else {
@@ -2368,10 +2376,10 @@ int tls_choose_sigalg(SSL *s, int *al)
                 size_t sent_sigslen, i;
 
                 if ((lu = tls1_get_legacy_sigalg(s, -1)) == NULL) {
-                    if (al == NULL)
+                    if (!fatalerrs)
                         return 1;
-                    *al = SSL_AD_INTERNAL_ERROR;
-                    SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR);
+                    SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CHOOSE_SIGALG,
+                             ERR_R_INTERNAL_ERROR);
                     return 0;
                 }
 
@@ -2382,19 +2390,20 @@ int tls_choose_sigalg(SSL *s, int *al)
                         break;
                 }
                 if (i == sent_sigslen) {
-                    if (al == NULL)
+                    if (!fatalerrs)
                         return 1;
-                    SSLerr(SSL_F_TLS_CHOOSE_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE);
-                    *al = SSL_AD_ILLEGAL_PARAMETER;
+                    SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+                             SSL_F_TLS_CHOOSE_SIGALG,
+                             SSL_R_WRONG_SIGNATURE_TYPE);
                     return 0;
                 }
             }
         } else {
             if ((lu = tls1_get_legacy_sigalg(s, -1)) == NULL) {
-                if (al == NULL)
+                if (!fatalerrs)
                     return 1;
-                *al = SSL_AD_INTERNAL_ERROR;
-                SSLerr(SSL_F_TLS_CHOOSE_SIGALG, ERR_R_INTERNAL_ERROR);
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CHOOSE_SIGALG,
+                         ERR_R_INTERNAL_ERROR);
                 return 0;
             }
         }
diff --git a/ssl/tls13_enc.c b/ssl/tls13_enc.c
index 98a1d1e..fe817f8 100644
--- a/ssl/tls13_enc.c
+++ b/ssl/tls13_enc.c
@@ -59,6 +59,8 @@ int tls13_hkdf_expand(SSL *s, const EVP_MD *md, const unsigned char *secret,
             || !WPACKET_finish(&pkt)) {
         EVP_PKEY_CTX_free(pctx);
         WPACKET_cleanup(&pkt);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_HKDF_EXPAND,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
@@ -72,6 +74,10 @@ int tls13_hkdf_expand(SSL *s, const EVP_MD *md, const unsigned char *secret,
 
     EVP_PKEY_CTX_free(pctx);
 
+    if (ret != 0)
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_HKDF_EXPAND,
+                 ERR_R_INTERNAL_ERROR);
+
     return ret == 0;
 }
 
@@ -128,8 +134,11 @@ int tls13_generate_secret(SSL *s, const EVP_MD *md,
     static const char derived_secret_label[] = "derived";
     unsigned char preextractsec[EVP_MAX_MD_SIZE];
 
-    if (pctx == NULL)
+    if (pctx == NULL) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_GENERATE_SECRET,
+                 ERR_R_INTERNAL_ERROR);
         return 0;
+    }
 
     mdlen = EVP_MD_size(md);
 
@@ -148,6 +157,8 @@ int tls13_generate_secret(SSL *s, const EVP_MD *md,
         if (mctx == NULL
                 || EVP_DigestInit_ex(mctx, md, NULL) <= 0
                 || EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) {
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_GENERATE_SECRET,
+                     ERR_R_INTERNAL_ERROR);
             EVP_MD_CTX_free(mctx);
             EVP_PKEY_CTX_free(pctx);
             return 0;
@@ -159,6 +170,7 @@ int tls13_generate_secret(SSL *s, const EVP_MD *md,
                                (unsigned char *)derived_secret_label,
                                sizeof(derived_secret_label) - 1, hash, mdlen,
                                preextractsec, mdlen)) {
+            /* SSLfatal() already called */
             EVP_PKEY_CTX_free(pctx);
             return 0;
         }
@@ -177,6 +189,10 @@ int tls13_generate_secret(SSL *s, const EVP_MD *md,
             || EVP_PKEY_derive(pctx, outsecret, &mdlen)
                <= 0;
 
+    if (ret != 0)
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_GENERATE_SECRET,
+                 ERR_R_INTERNAL_ERROR);
+
     EVP_PKEY_CTX_free(pctx);
     if (prevsecret == preextractsec)
         OPENSSL_cleanse(preextractsec, mdlen);
@@ -191,6 +207,7 @@ int tls13_generate_secret(SSL *s, const EVP_MD *md,
 int tls13_generate_handshake_secret(SSL *s, const unsigned char *insecret,
                                 size_t insecretlen)
 {
+    /* Calls SSLfatal() if required */
     return tls13_generate_secret(s, ssl_handshake_md(s), s->early_secret,
                                  insecret, insecretlen,
                                  (unsigned char *)&s->handshake_secret);
@@ -208,6 +225,7 @@ int tls13_generate_master_secret(SSL *s, unsigned char *out,
     const EVP_MD *md = ssl_handshake_md(s);
 
     *secret_size = EVP_MD_size(md);
+    /* Calls SSLfatal() if required */
     return tls13_generate_secret(s, md, prev, NULL, 0, out);
 }
 
@@ -224,8 +242,10 @@ size_t tls13_final_finish_mac(SSL *s, const char *str, size_t slen,
     EVP_PKEY *key = NULL;
     EVP_MD_CTX *ctx = EVP_MD_CTX_new();
 
-    if (!ssl_handshake_hash(s, hash, sizeof(hash), &hashlen))
+    if (!ssl_handshake_hash(s, hash, sizeof(hash), &hashlen)) {
+        /* SSLfatal() already called */
         goto err;
+    }
 
     if (str == s->method->ssl3_enc->server_finished_label)
         key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL,
@@ -238,8 +258,11 @@ size_t tls13_final_finish_mac(SSL *s, const char *str, size_t slen,
             || ctx == NULL
             || EVP_DigestSignInit(ctx, NULL, md, NULL, key) <= 0
             || EVP_DigestSignUpdate(ctx, hash, hashlen) <= 0
-            || EVP_DigestSignFinal(ctx, out, &hashlen) <= 0)
+            || EVP_DigestSignFinal(ctx, out, &hashlen) <= 0) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_FINAL_FINISH_MAC,
+                 ERR_R_INTERNAL_ERROR);
         goto err;
+    }
 
     ret = hashlen;
  err:
@@ -261,7 +284,8 @@ int tls13_setup_key_block(SSL *s)
     s->session->cipher = s->s3->tmp.new_cipher;
     if (!ssl_cipher_get_evp
         (s->session, &c, &hash, &mac_type, NULL, NULL, 0)) {
-        SSLerr(SSL_F_TLS13_SETUP_KEY_BLOCK, SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_SETUP_KEY_BLOCK,
+                 SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
         return 0;
     }
 
@@ -285,7 +309,7 @@ static int derive_secret_key_and_iv(SSL *s, int sending, const EVP_MD *md,
 
     if (!tls13_hkdf_expand(s, md, insecret, label, labellen, hash, hashlen,
                            secret, hashlen)) {
-        SSLerr(SSL_F_DERIVE_SECRET_KEY_AND_IV, ERR_R_INTERNAL_ERROR);
+        /* SSLfatal() already called */
         goto err;
     }
 
@@ -312,7 +336,7 @@ static int derive_secret_key_and_iv(SSL *s, int sending, const EVP_MD *md,
 
     if (!tls13_derive_key(s, md, secret, key, keylen)
             || !tls13_derive_iv(s, md, secret, iv, ivlen)) {
-        SSLerr(SSL_F_DERIVE_SECRET_KEY_AND_IV, ERR_R_INTERNAL_ERROR);
+        /* SSLfatal() already called */
         goto err;
     }
 
@@ -321,7 +345,8 @@ static int derive_secret_key_and_iv(SSL *s, int sending, const EVP_MD *md,
         || (taglen != 0 && !EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_TAG,
                                                 taglen, NULL))
         || EVP_CipherInit_ex(ciph_ctx, NULL, NULL, key, NULL, -1) <= 0) {
-        SSLerr(SSL_F_DERIVE_SECRET_KEY_AND_IV, ERR_R_EVP_LIB);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DERIVE_SECRET_KEY_AND_IV,
+                 ERR_R_EVP_LIB);
         goto err;
     }
 
@@ -361,7 +386,8 @@ int tls13_change_cipher_state(SSL *s, int which)
         } else {
             s->enc_read_ctx = EVP_CIPHER_CTX_new();
             if (s->enc_read_ctx == NULL) {
-                SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE);
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE);
                 goto err;
             }
         }
@@ -375,7 +401,8 @@ int tls13_change_cipher_state(SSL *s, int which)
         } else {
             s->enc_write_ctx = EVP_CIPHER_CTX_new();
             if (s->enc_write_ctx == NULL) {
-                SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE);
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE);
                 goto err;
             }
         }
@@ -401,8 +428,9 @@ int tls13_change_cipher_state(SSL *s, int which)
 
             handlen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
             if (handlen <= 0) {
-                SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE,
-                       SSL_R_BAD_HANDSHAKE_LENGTH);
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_TLS13_CHANGE_CIPHER_STATE,
+                         SSL_R_BAD_HANDSHAKE_LENGTH);
                 goto err;
             }
 
@@ -417,14 +445,16 @@ int tls13_change_cipher_state(SSL *s, int which)
                 if (!ossl_assert(s->psksession != NULL
                         && s->max_early_data ==
                            s->psksession->ext.max_early_data)) {
-                    SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE,
-                           ERR_R_INTERNAL_ERROR);
+                    SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                             SSL_F_TLS13_CHANGE_CIPHER_STATE,
+                             ERR_R_INTERNAL_ERROR);
                     goto err;
                 }
                 sslcipher = SSL_SESSION_get0_cipher(s->psksession);
             }
             if (sslcipher == NULL) {
-                SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, SSL_R_BAD_PSK);
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_TLS13_CHANGE_CIPHER_STATE, SSL_R_BAD_PSK);
                 goto err;
             }
 
@@ -435,7 +465,8 @@ int tls13_change_cipher_state(SSL *s, int which)
              */
             mdctx = EVP_MD_CTX_new();
             if (mdctx == NULL) {
-                SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE);
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE);
                 goto err;
             }
             cipher = EVP_get_cipherbynid(SSL_CIPHER_get_cipher_nid(sslcipher));
@@ -443,7 +474,8 @@ int tls13_change_cipher_state(SSL *s, int which)
             if (md == NULL || !EVP_DigestInit_ex(mdctx, md, NULL)
                     || !EVP_DigestUpdate(mdctx, hdata, handlen)
                     || !EVP_DigestFinal_ex(mdctx, hashval, &hashlenui)) {
-                SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                         SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
                 EVP_MD_CTX_free(mdctx);
                 goto err;
             }
@@ -501,7 +533,7 @@ int tls13_change_cipher_state(SSL *s, int which)
         cipher = s->s3->tmp.new_sym_enc;
         if (!ssl3_digest_cached_records(s, 1)
                 || !ssl_handshake_hash(s, hashval, sizeof(hashval), &hashlen)) {
-            SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+            /* SSLfatal() already called */;
             goto err;
         }
     }
@@ -526,7 +558,7 @@ int tls13_change_cipher_state(SSL *s, int which)
                                sizeof(resumption_master_secret) - 1,
                                hashval, hashlen, s->session->master_key,
                                hashlen)) {
-            SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+            /* SSLfatal() already called */
             goto err;
         }
         s->session->master_key_length = hashlen;
@@ -537,7 +569,7 @@ int tls13_change_cipher_state(SSL *s, int which)
                                sizeof(exporter_master_secret) - 1,
                                hash, hashlen, s->exporter_master_secret,
                                hashlen)) {
-            SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+            /* SSLfatal() already called */
             goto err;
         }
     }
@@ -545,6 +577,7 @@ int tls13_change_cipher_state(SSL *s, int which)
     if (!derive_secret_key_and_iv(s, which & SSL3_CC_WRITE, md, cipher,
                                   insecret, hash, label, labellen, secret, iv,
                                   ciph_ctx)) {
+        /* SSLfatal() already called */
         goto err;
     }
 
@@ -554,14 +587,14 @@ int tls13_change_cipher_state(SSL *s, int which)
         memcpy(s->client_app_traffic_secret, secret, hashlen);
 
     if (!ssl_log_secret(s, log_label, secret, hashlen)) {
-        SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+        /* SSLfatal() already called */
         goto err;
     }
 
     if (finsecret != NULL
             && !tls13_derive_finishedkey(s, ssl_handshake_md(s), secret,
                                          finsecret, finsecretlen)) {
-        SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
+        /* SSLfatal() already called */
         goto err;
     }
 
@@ -600,8 +633,10 @@ int tls13_update_key(SSL *s, int sending)
                                   s->s3->tmp.new_sym_enc, insecret, NULL,
                                   application_traffic,
                                   sizeof(application_traffic) - 1, secret, iv,
-                                  ciph_ctx))
+                                  ciph_ctx)) {
+        /* SSLfatal() already called */
         goto err;
+    }
 
     memcpy(insecret, secret, hashlen);
 
diff --git a/ssl/tls_srp.c b/ssl/tls_srp.c
index d1683c5..37adcbc 100644
--- a/ssl/tls_srp.c
+++ b/ssl/tls_srp.c
@@ -257,9 +257,13 @@ int srp_generate_server_master_secret(SSL *s)
         goto err;
 
     tmp_len = BN_num_bytes(K);
-    if ((tmp = OPENSSL_malloc(tmp_len)) == NULL)
+    if ((tmp = OPENSSL_malloc(tmp_len)) == NULL) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_SRP_GENERATE_SERVER_MASTER_SECRET, ERR_R_MALLOC_FAILURE);
         goto err;
+    }
     BN_bn2bin(K, tmp);
+    /* Calls SSLfatal() as required */
     ret = ssl_generate_master_secret(s, tmp, tmp_len, 1);
  err:
     BN_clear_free(K);
@@ -278,26 +282,39 @@ int srp_generate_client_master_secret(SSL *s)
     /*
      * Checks if b % n == 0
      */
-    if (SRP_Verify_B_mod_N(s->srp_ctx.B, s->srp_ctx.N) == 0)
-        goto err;
-    if ((u = SRP_Calc_u(s->srp_ctx.A, s->srp_ctx.B, s->srp_ctx.N)) == NULL)
-        goto err;
-    if (s->srp_ctx.SRP_give_srp_client_pwd_callback == NULL)
-        goto err;
-    if (!
-        (passwd =
-         s->srp_ctx.SRP_give_srp_client_pwd_callback(s, s->srp_ctx.SRP_cb_arg)))
+    if (SRP_Verify_B_mod_N(s->srp_ctx.B, s->srp_ctx.N) == 0
+            || (u = SRP_Calc_u(s->srp_ctx.A, s->srp_ctx.B, s->srp_ctx.N))
+               == NULL
+            || s->srp_ctx.SRP_give_srp_client_pwd_callback == NULL) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_SRP_GENERATE_CLIENT_MASTER_SECRET, ERR_R_INTERNAL_ERROR);
         goto err;
-    if ((x = SRP_Calc_x(s->srp_ctx.s, s->srp_ctx.login, passwd)) == NULL)
+    }
+    if ((passwd = s->srp_ctx.SRP_give_srp_client_pwd_callback(s,
+                                                      s->srp_ctx.SRP_cb_arg))
+            == NULL) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_SRP_GENERATE_CLIENT_MASTER_SECRET,
+                 SSL_R_CALLBACK_FAILED);
         goto err;
-    if ((K = SRP_Calc_client_key(s->srp_ctx.N, s->srp_ctx.B, s->srp_ctx.g, x,
-                                 s->srp_ctx.a, u)) == NULL)
+    }
+    if ((x = SRP_Calc_x(s->srp_ctx.s, s->srp_ctx.login, passwd)) == NULL
+            || (K = SRP_Calc_client_key(s->srp_ctx.N, s->srp_ctx.B,
+                                        s->srp_ctx.g, x,
+                                        s->srp_ctx.a, u)) == NULL) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_SRP_GENERATE_CLIENT_MASTER_SECRET, ERR_R_INTERNAL_ERROR);
         goto err;
+    }
 
     tmp_len = BN_num_bytes(K);
-    if ((tmp = OPENSSL_malloc(tmp_len)) == NULL)
+    if ((tmp = OPENSSL_malloc(tmp_len)) == NULL) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+                 SSL_F_SRP_GENERATE_CLIENT_MASTER_SECRET, ERR_R_MALLOC_FAILURE);
         goto err;
+    }
     BN_bn2bin(K, tmp);
+    /* Calls SSLfatal() as required */
     ret = ssl_generate_master_secret(s, tmp, tmp_len, 1);
  err:
     BN_clear_free(K);
@@ -308,7 +325,7 @@ int srp_generate_client_master_secret(SSL *s)
     return ret;
 }
 
-int srp_verify_server_param(SSL *s, int *al)
+int srp_verify_server_param(SSL *s)
 {
     SRP_CTX *srp = &s->srp_ctx;
     /*
@@ -317,22 +334,27 @@ int srp_verify_server_param(SSL *s, int *al)
      */
     if (BN_ucmp(srp->g, srp->N) >= 0 || BN_ucmp(srp->B, srp->N) >= 0
         || BN_is_zero(srp->B)) {
-        *al = SSL3_AD_ILLEGAL_PARAMETER;
+        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SRP_VERIFY_SERVER_PARAM,
+                 SSL_R_BAD_DATA);
         return 0;
     }
 
     if (BN_num_bits(srp->N) < srp->strength) {
-        *al = TLS1_AD_INSUFFICIENT_SECURITY;
+        SSLfatal(s, SSL_AD_INSUFFICIENT_SECURITY, SSL_F_SRP_VERIFY_SERVER_PARAM,
+                 SSL_R_INSUFFICIENT_SECURITY);
         return 0;
     }
 
     if (srp->SRP_verify_param_callback) {
         if (srp->SRP_verify_param_callback(s, srp->SRP_cb_arg) <= 0) {
-            *al = TLS1_AD_INSUFFICIENT_SECURITY;
+            SSLfatal(s, SSL_AD_INSUFFICIENT_SECURITY,
+                     SSL_F_SRP_VERIFY_SERVER_PARAM,
+                     SSL_R_CALLBACK_FAILED);
             return 0;
         }
     } else if (!SRP_check_known_gN_param(srp->g, srp->N)) {
-        *al = TLS1_AD_INSUFFICIENT_SECURITY;
+        SSLfatal(s, SSL_AD_INSUFFICIENT_SECURITY, SSL_F_SRP_VERIFY_SERVER_PARAM,
+                 SSL_R_INSUFFICIENT_SECURITY);
         return 0;
     }
 
diff --git a/test/ossl_shim/ossl_config.json b/test/ossl_shim/ossl_config.json
index 26da5f0..0643d71 100644
--- a/test/ossl_shim/ossl_config.json
+++ b/test/ossl_shim/ossl_config.json
@@ -277,7 +277,7 @@
         ":BAD_DH_P_LENGTH:":"dh key too small",
         ":PEER_DID_NOT_RETURN_A_CERTIFICATE:":"peer did not return a certificate",
         ":UNSUPPORTED_PROTOCOL:":"unsupported protocol",
-        ":PARSE_TLSEXT:":"parse tlsext",
+        ":PARSE_TLSEXT:":"bad extension",
         ":BAD_SRTP_PROTECTION_PROFILE_LIST:":"bad srtp protection profile list",
         ":OLD_SESSION_VERSION_NOT_RETURNED:":"ssl session version mismatch",
         ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:":"inconsistent extms",
diff --git a/test/tls13secretstest.c b/test/tls13secretstest.c
index 1c47e41..16542c4 100644
--- a/test/tls13secretstest.c
+++ b/test/tls13secretstest.c
@@ -207,6 +207,11 @@ const EVP_MD *ssl_md(int idx)
     return EVP_sha256();
 }
 
+void ossl_statem_fatal(SSL *s, int al, int func, int reason, const char *file,
+                           int line)
+{
+}
+
 /* End of mocked out code */
 
 static int test_secret(SSL *s, unsigned char *prk,


More information about the openssl-commits mailing list