]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
QUIC TLS: Rethink error handling
authorHugo Landau <hlandau@openssl.org>
Thu, 3 Aug 2023 10:56:12 +0000 (11:56 +0100)
committerMatt Caswell <matt@openssl.org>
Tue, 8 Aug 2023 13:33:42 +0000 (14:33 +0100)
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/21547)

15 files changed:
crypto/err/err_mark.c
crypto/err/err_save.c
crypto/err/openssl.txt
doc/man3/ERR_set_mark.pod
doc/man3/OSSL_ERR_STATE_save.pod
include/internal/quic_channel.h
include/internal/quic_tls.h
include/internal/ssl.h
include/openssl/err.h.in
include/openssl/sslerr.h
ssl/quic/quic_channel.c
ssl/quic/quic_tls.c
ssl/ssl_err.c
ssl/ssl_lib.c
util/libcrypto.num

index cc1baba7a389d07a0633552b3d4f3143992527ec..1395e944dd23df67b7126d7c1939e2e2e84f693c 100644 (file)
@@ -46,6 +46,25 @@ int ERR_pop_to_mark(void)
     return 1;
 }
 
+int ERR_count_to_mark(void)
+{
+    ERR_STATE *es;
+    int count = 0, top;
+
+    es = ossl_err_get_state_int();
+    if (es == NULL)
+        return 0;
+
+    top = es->top;
+    while (es->bottom != top
+           && es->err_marks[top] == 0) {
+        ++count;
+        top = top > 0 ? top - 1 : ERR_NUM_ERRORS - 1;
+    }
+
+    return count;
+}
+
 int ERR_clear_last_mark(void)
 {
     ERR_STATE *es;
index a471b22682ad92c2995240d8684ac2363b80c463..3ca059adc336b0dbf9cf61f80ab95bd086b8b629 100644 (file)
@@ -43,6 +43,71 @@ void OSSL_ERR_STATE_save(ERR_STATE *es)
     memset(thread_es, 0, sizeof(*thread_es));
 }
 
+void OSSL_ERR_STATE_save_to_mark(ERR_STATE *es)
+{
+    size_t i, j, count;
+    int top;
+    ERR_STATE *thread_es;
+
+    if (es == NULL)
+        return;
+
+    thread_es = ossl_err_get_state_int();
+    if (thread_es == NULL) {
+        for (i = 0; i < ERR_NUM_ERRORS; ++i)
+            err_clear(es, i, 1);
+
+        es->top = es->bottom = 0;
+        return;
+    }
+
+    /* Determine number of errors we are going to move. */
+    for (count = 0, top = thread_es->top;
+         thread_es->bottom != top
+         && thread_es->err_marks[top] == 0;
+         ++count)
+        top = top > 0 ? top - 1 : ERR_NUM_ERRORS - 1;
+
+    /* Move the errors, preserving order. */
+    for (i = 0, j = top; i < count; ++i) {
+        j = (j + 1) % ERR_NUM_ERRORS;
+
+        err_clear(es, i, 1);
+
+        /* Move the error entry to the given ERR_STATE. */
+        es->err_flags[i]        = thread_es->err_flags[j];
+        es->err_marks[i]        = 0;
+        es->err_buffer[i]       = thread_es->err_buffer[j];
+        es->err_data[i]         = thread_es->err_data[j];
+        es->err_data_size[i]    = thread_es->err_data_size[j];
+        es->err_data_flags[i]   = thread_es->err_data_flags[j];
+        es->err_file[i]         = thread_es->err_file[j];
+        es->err_line[i]         = thread_es->err_line[j];
+        es->err_func[i]         = thread_es->err_func[j];
+
+        thread_es->err_flags[j]     = 0;
+        thread_es->err_buffer[j]    = 0;
+        thread_es->err_data[j]      = NULL;
+        thread_es->err_data_size[j] = 0;
+        thread_es->err_file[j]      = NULL;
+        thread_es->err_line[j]      = 0;
+        thread_es->err_func[j]      = NULL;
+    }
+
+    if (i > 0) {
+        /* If we moved anything, es's stack always starts at [0]. */
+        es->top     = i - 1;
+        es->bottom  = ERR_NUM_ERRORS - 1;
+    } else {
+        /* Didn't move anything - empty stack */
+        es->top = es->bottom = 0;
+    }
+
+    /* Erase extra space as a precaution. */
+    for (; i < ERR_NUM_ERRORS; ++i)
+        err_clear(es, i, 1);
+}
+
 void OSSL_ERR_STATE_restore(const ERR_STATE *es)
 {
     size_t i;
index 0be223b974f5909d66b8c5cc65c4ce64acbf4212..70c1645a4f82d9b97985a37de9ebd6275af5629d 100644 (file)
@@ -1498,6 +1498,7 @@ SSL_R_PROTOCOL_IS_SHUTDOWN:207:protocol is shutdown
 SSL_R_PSK_IDENTITY_NOT_FOUND:223:psk identity not found
 SSL_R_PSK_NO_CLIENT_CB:224:psk no client cb
 SSL_R_PSK_NO_SERVER_CB:225:psk no server cb
+SSL_R_QUIC_HANDSHAKE_LAYER_ERROR:393:quic handshake layer error
 SSL_R_QUIC_NETWORK_ERROR:387:quic network error
 SSL_R_QUIC_PROTOCOL_ERROR:382:quic protocol error
 SSL_R_READ_BIO_NOT_SET:211:read bio not set
index e61d5c61edd4021e68acd1e8d819e2227c9c1a1b..add9b232c09df077dbe2628a6e53fab2e079bfc3 100644 (file)
@@ -2,8 +2,8 @@
 
 =head1 NAME
 
-ERR_set_mark, ERR_clear_last_mark, ERR_pop_to_mark
-- set mark, clear mark and pop errors until mark
+ERR_set_mark, ERR_clear_last_mark, ERR_pop_to_mark, ERR_count_to_mark - set
+mark, clear mark and pop errors until mark
 
 =head1 SYNOPSIS
 
@@ -12,6 +12,7 @@ ERR_set_mark, ERR_clear_last_mark, ERR_pop_to_mark
  int ERR_set_mark(void);
  int ERR_pop_to_mark(void);
  int ERR_clear_last_mark(void);
+ int ERR_count_to_mark(void);
 
 =head1 DESCRIPTION
 
@@ -23,6 +24,10 @@ The mark is then removed.  If there is no mark, the whole stack is removed.
 
 ERR_clear_last_mark() removes the last mark added if there is one.
 
+ERR_count_to_mark() returns the number of entries on the error stack above the
+most recently marked entry, not including that entry. If there is no mark in the
+error stack, the number of entries in the error stack is returned.
+
 =head1 RETURN VALUES
 
 ERR_set_mark() returns 0 if the error stack is empty, otherwise 1.
@@ -30,6 +35,9 @@ ERR_set_mark() returns 0 if the error stack is empty, otherwise 1.
 ERR_clear_last_mark() and ERR_pop_to_mark() return 0 if there was no mark in the
 error stack, which implies that the stack became empty, otherwise 1.
 
+ERR_count_to_mark() returns the number of error stack entries found above the
+most recent mark, if any, or the total number of error stack entries.
+
 =head1 COPYRIGHT
 
 Copyright 2003-2021 The OpenSSL Project Authors. All Rights Reserved.
index 79f3aba5f84bba9a0f16f47da61149837985308f..05c738fc552a33e6a188547a4ba6bc8225e799cc 100644 (file)
@@ -2,8 +2,8 @@
 
 =head1 NAME
 
-OSSL_ERR_STATE_new, OSSL_ERR_STATE_save, OSSL_ERR_STATE_restore,
-OSSL_ERR_STATE_free - saving and restoring error state
+OSSL_ERR_STATE_new, OSSL_ERR_STATE_save, OSSL_ERR_STATE_save_to_mark,
+OSSL_ERR_STATE_restore, OSSL_ERR_STATE_free - saving and restoring error state
 
 =head1 SYNOPSIS
 
@@ -11,6 +11,7 @@ OSSL_ERR_STATE_free - saving and restoring error state
 
  ERR_STATE *OSSL_ERR_STATE_new(void);
  void OSSL_ERR_STATE_save(ERR_STATE *es);
+ void OSSL_ERR_STATE_save_to_mark(ERR_STATE *es);
  void OSSL_ERR_STATE_restore(const ERR_STATE *es);
  void OSSL_ERR_STATE_free(ERR_STATE *es);
 
@@ -26,6 +27,18 @@ OSSL_ERR_STATE_save() saves the thread error state to I<es>. It
 subsequently clears the thread error state. Any previously saved
 state in I<es> is cleared prior to saving the new state.
 
+OSSL_ERR_STATE_save_to_mark() is similar to OSSL_ERR_STATE_save() but only saves
+ERR entries up to the most recent mark on the ERR stack. These entries are moved
+to I<es> and removed from the thread error state. However, the most recent
+marked ERR and any ERR state before it remains part of the thread error state
+and is not moved to the ERR_STATE. The mark is not cleared and must be cleared
+explicitly after a call to this function using L<ERR_pop_to_mark(3)> or
+L<ERR_clear_last_mark(3)>. (Since a call to OSSL_ERR_STATE_save_to_mark() leaves
+the marked ERR as the top error, either of these functions will have the same
+effect.) If there is no marked ERR in the thread local error state, all ERR
+entries are copied and the effect is the same as for a call to
+OSSL_ERR_STATE_save().
+
 OSSL_ERR_STATE_restore() adds all the error entries from the
 saved state I<es> to the thread error state. Existing entries in
 the thread error state are not affected if there is enough space
@@ -39,13 +52,13 @@ OSSL_ERR_STATE_free() frees the saved error state I<es>.
 OSSL_ERR_STATE_new() returns a pointer to the allocated ERR_STATE
 structure or NULL on error.
 
-OSSL_ERR_STATE_save(), OSSL_ERR_STATE_restore(), OSSL_ERR_STATE_free()
-do not return any values.
+OSSL_ERR_STATE_save(), OSSL_ERR_STATE_save_to_mark(), OSSL_ERR_STATE_restore(),
+OSSL_ERR_STATE_free() do not return any values.
 
 =head1 NOTES
 
-OSSL_ERR_STATE_save() cannot fail as it takes over any allocated
-data from the thread error state.
+OSSL_ERR_STATE_save() and OSSL_ERR_STATE_save_to_mark() cannot fail as it takes
+over any allocated data from the thread error state.
 
 OSSL_ERR_STATE_restore() is a best effort function. The only failure
 that can happen during its operation is when memory allocation fails.
index f9e654fd937ac9435f2376849dc5050e52059135..f9f2e30e23329243746fdae12b68a246ff6c0977 100644 (file)
@@ -221,6 +221,7 @@ void ossl_quic_channel_raise_protocol_error_loc(QUIC_CHANNEL *ch,
                                                 uint64_t error_code,
                                                 uint64_t frame_type,
                                                 const char *reason,
+                                                ERR_STATE *err_state,
                                                 const char *src_file,
                                                 int src_line,
                                                 const char *src_func);
@@ -229,10 +230,21 @@ void ossl_quic_channel_raise_protocol_error_loc(QUIC_CHANNEL *ch,
     ossl_quic_channel_raise_protocol_error_loc((ch), (error_code),  \
                                                (frame_type),        \
                                                (reason),            \
+                                               NULL,                \
                                                OPENSSL_FILE,        \
                                                OPENSSL_LINE,        \
                                                OPENSSL_FUNC)
 
+#define ossl_quic_channel_raise_protocol_error_state(ch, error_code, frame_type, reason, state) \
+    ossl_quic_channel_raise_protocol_error_loc((ch), (error_code),  \
+                                               (frame_type),        \
+                                               (reason),            \
+                                               (state),             \
+                                               OPENSSL_FILE,        \
+                                               OPENSSL_LINE,        \
+                                               OPENSSL_FUNC)
+
+
 /*
  * Returns 1 if permanent net error was detected on the QUIC_CHANNEL,
  * 0 otherwise.
index 13da5882c96504256503a7ccbec45ca94bede6cf..770c698d315ddbe3e887f910d9721c5ee59c0e1c 100644 (file)
@@ -98,8 +98,6 @@ int ossl_quic_tls_set_transport_params(QUIC_TLS *qtls,
 int ossl_quic_tls_get_error(QUIC_TLS *qtls,
                             uint64_t *error_code,
                             const char **error_msg,
-                            const char **error_src_file,
-                            int *error_src_line,
-                            const char **error_src_func);
+                            ERR_STATE **error_state);
 
 #endif
index 3bf9bf9e34d09d30beb3c8e3438c62a27717df05..46146a9e7ebf86b96d15bf57dbf1c91aa661309c 100644 (file)
@@ -16,4 +16,6 @@
 typedef void (*ossl_msg_cb)(int write_p, int version, int content_type,
                             const void *buf, size_t len, SSL *ssl, void *arg);
 
+int ossl_ssl_get_error(const SSL *s, int i, int check_err);
+
 #endif
index 075d683f8d4ac33145d95ba4dcd86e2e73c46f50..a28afa885fe232dc6d25da4a4d6365db33131d06 100644 (file)
@@ -485,9 +485,11 @@ int ERR_get_next_error_library(void);
 int ERR_set_mark(void);
 int ERR_pop_to_mark(void);
 int ERR_clear_last_mark(void);
+int ERR_count_to_mark(void);
 
 ERR_STATE *OSSL_ERR_STATE_new(void);
 void OSSL_ERR_STATE_save(ERR_STATE *es);
+void OSSL_ERR_STATE_save_to_mark(ERR_STATE *es);
 void OSSL_ERR_STATE_restore(const ERR_STATE *es);
 void OSSL_ERR_STATE_free(ERR_STATE *es);
 
index b330b90be4a88b8262d669bd6f04ed1b79e6e0af..30e7e86db38836d3632137692a5e93f3a543fe7f 100644 (file)
 # define SSL_R_PSK_IDENTITY_NOT_FOUND                     223
 # define SSL_R_PSK_NO_CLIENT_CB                           224
 # define SSL_R_PSK_NO_SERVER_CB                           225
+# define SSL_R_QUIC_HANDSHAKE_LAYER_ERROR                 393
 # define SSL_R_QUIC_NETWORK_ERROR                         387
 # define SSL_R_QUIC_PROTOCOL_ERROR                        382
 # define SSL_R_READ_BIO_NOT_SET                           211
index 5fb49a90dfc0696c5b5ecae363bad38d92782dd1..54ccf5d3169439ae26045c93f7140b7b7735038f 100644 (file)
@@ -1616,8 +1616,8 @@ static void ch_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags)
     QUIC_CHANNEL *ch = arg;
     int channel_only = (flags & QUIC_REACTOR_TICK_FLAG_CHANNEL_ONLY) != 0;
     uint64_t error_code;
-    const char *error_msg, *error_src_file, *error_src_func;
-    int error_src_line;
+    const char *error_msg;
+    ERR_STATE *error_state = NULL;
 
     /*
      * When we tick the QUIC connection, we do everything we need to do
@@ -1674,15 +1674,9 @@ static void ch_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags)
                 ossl_quic_tls_tick(ch->qtls);
 
                 if (ossl_quic_tls_get_error(ch->qtls, &error_code, &error_msg,
-                                            &error_src_file,
-                                            &error_src_line,
-                                            &error_src_func)) {
-                    ossl_quic_channel_raise_protocol_error_loc(ch, error_code, 0,
-                                                               error_msg,
-                                                               error_src_file,
-                                                               error_src_line,
-                                                               error_src_func);
-                }
+                                            &error_state))
+                    ossl_quic_channel_raise_protocol_error_state(ch, error_code, 0,
+                                                                 error_msg, error_state);
             }
 
             /*
@@ -2916,6 +2910,7 @@ void ossl_quic_channel_raise_protocol_error_loc(QUIC_CHANNEL *ch,
                                                 uint64_t error_code,
                                                 uint64_t frame_type,
                                                 const char *reason,
+                                                ERR_STATE *err_state,
                                                 const char *src_file,
                                                 int src_line,
                                                 const char *src_func)
@@ -2934,6 +2929,13 @@ void ossl_quic_channel_raise_protocol_error_loc(QUIC_CHANNEL *ch,
         err_str_sfx = "";
     }
 
+    /*
+     * If we were provided an underlying error state, restore it and then append
+     * our ERR on top as a "cover letter" error.
+     */
+    if (err_state != NULL)
+        OSSL_ERR_STATE_restore(err_state);
+
     if (frame_type != 0) {
         ft_str = ossl_quic_frame_type_to_string(frame_type);
         if (ft_str == NULL) {
index d8770bf9f7d145bd8f936bee472cdb1841a0f870..fd24026fa38351f5958dfab39f4aadd068c83600 100644 (file)
@@ -29,6 +29,8 @@ struct quic_tls_st {
     const unsigned char *local_transport_params;
     size_t local_transport_params_len;
 
+    ERR_STATE *error_state;
+
     /*
      * QUIC error code (usually in the TLS Alert-mapped CRYPTO_ERR range). Valid
      * only if inerror is 1.
@@ -41,10 +43,6 @@ struct quic_tls_st {
      */
     const char *error_msg;
 
-    const char *error_src_file;
-    const char *error_src_func;
-    int error_src_line;
-
     /* Whether our SSL object for TLS has been configured for use in QUIC */
     unsigned int configured : 1;
 
@@ -636,12 +634,18 @@ QUIC_TLS *ossl_quic_tls_new(const QUIC_TLS_ARGS *args)
     if (qtls == NULL)
         return NULL;
 
+    if ((qtls->error_state = OSSL_ERR_STATE_new()) == NULL) {
+        OPENSSL_free(qtls);
+        return NULL;
+    }
+
     qtls->args = *args;
     return qtls;
 }
 
 void ossl_quic_tls_free(QUIC_TLS *qtls)
 {
+    OSSL_ERR_STATE_free(qtls->error_state);
     OPENSSL_free(qtls);
 }
 
@@ -651,12 +655,28 @@ static int raise_error(QUIC_TLS *qtls, uint64_t error_code,
                        int src_line,
                        const char *src_func)
 {
+    /*
+     * When QTLS fails, add a "cover letter" error with information, potentially
+     * with any underlying libssl errors underneath it (but our cover error may
+     * be the only error in some cases). Then capture this into an ERR_STATE so
+     * we can report it later if need be when the QUIC_CHANNEL asks for it.
+     */
+    ERR_new();
+    ERR_set_debug(src_file, src_line, src_func);
+    ERR_set_error(ERR_LIB_SSL, SSL_R_QUIC_HANDSHAKE_LAYER_ERROR,
+                  "handshake layer error, error code %zu (\"%s\")",
+                  error_code, error_msg);
+    OSSL_ERR_STATE_save_to_mark(qtls->error_state);
+
+    /*
+     * We record the error information reported via the QUIC protocol
+     * separately.
+     */
     qtls->error_code        = error_code;
     qtls->error_msg         = error_msg;
-    qtls->error_src_file    = src_file;
-    qtls->error_src_line    = src_line;
-    qtls->error_src_func    = src_func;
     qtls->inerror           = 1;
+
+    ERR_pop_to_mark();
     return 0;
 }
 
@@ -669,7 +689,7 @@ static int raise_error(QUIC_TLS *qtls, uint64_t error_code,
 
 int ossl_quic_tls_tick(QUIC_TLS *qtls)
 {
-    int ret;
+    int ret, err;
     const unsigned char *alpn;
     unsigned int alpnlen;
 
@@ -683,6 +703,29 @@ int ossl_quic_tls_tick(QUIC_TLS *qtls)
     if (qtls->inerror)
         return 0;
 
+    /*
+     * SSL_get_error does not truly know what the cause of an SSL_read failure
+     * is and to some extent guesses based on contextual information. In
+     * particular, if there is _any_ ERR on the error stack, SSL_ERROR_SSL or
+     * SSL_ERROR_SYSCALL will be returned no matter what and there is no
+     * possibility of SSL_ERROR_WANT_READ/WRITE being returned, even if that was
+     * the actual cause of the SSL_read() failure.
+     *
+     * This means that ordinarily, the below code might not work right if the
+     * application has any ERR on the error stack. In order to make this code
+     * perform correctly regardless of prior ERR state, we use a variant of
+     * SSL_get_error() which ignores the error stack. However, some ERRs are
+     * raised by SSL_read() and actually indicate that something has gone wrong
+     * during the call to SSL_read(). We therefore adopt a strategy of marking
+     * the ERR stack and seeing if any errors get appended during the call to
+     * SSL_read(). If they are, we assume SSL_read() has raised an error and
+     * that we should use normal SSL_get_error() handling.
+     *
+     * NOTE: Ensure all escape paths from this function call
+     * ERR_clear_to_mark(). The RAISE macros handle this in failure cases.
+     */
+    ERR_set_mark();
+
     if (!qtls->configured) {
         SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(qtls->args.s);
         SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(sc);
@@ -745,11 +788,17 @@ int ossl_quic_tls_tick(QUIC_TLS *qtls)
         ret = SSL_read(qtls->args.s, NULL, 0);
     else
         ret = SSL_do_handshake(qtls->args.s);
+
     if (ret <= 0) {
-        switch (SSL_get_error(qtls->args.s, ret)) {
+        err = ossl_ssl_get_error(qtls->args.s, ret,
+                                 /*check_err=*/ERR_count_to_mark() > 0);
+
+        switch (err) {
         case SSL_ERROR_WANT_READ:
         case SSL_ERROR_WANT_WRITE:
+            ERR_pop_to_mark();
             return 1;
+
         default:
             return RAISE_INTERNAL_ERROR(qtls);
         }
@@ -763,9 +812,11 @@ int ossl_quic_tls_tick(QUIC_TLS *qtls)
                                "no application protocol negotiated");
 
         qtls->complete = 1;
+        ERR_pop_to_mark();
         return qtls->args.handshake_complete_cb(qtls->args.handshake_complete_cb_arg);
     }
 
+    ERR_pop_to_mark();
     return 1;
 }
 
@@ -781,16 +832,12 @@ int ossl_quic_tls_set_transport_params(QUIC_TLS *qtls,
 int ossl_quic_tls_get_error(QUIC_TLS *qtls,
                             uint64_t *error_code,
                             const char **error_msg,
-                            const char **error_src_file,
-                            int *error_src_line,
-                            const char **error_src_func)
+                            ERR_STATE **error_state)
 {
     if (qtls->inerror) {
         *error_code     = qtls->error_code;
         *error_msg      = qtls->error_msg;
-        *error_src_file = qtls->error_src_file;
-        *error_src_line = qtls->error_src_line;
-        *error_src_func = qtls->error_src_func;
+        *error_state    = qtls->error_state;
     }
 
     return qtls->inerror;
index 9d24bc8014bf9728b6a97998bff026c16dd30cb5..55694569d6cf1fccf0056385265ee00a1ab9d130 100644 (file)
@@ -355,6 +355,8 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
     "psk identity not found"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PSK_NO_CLIENT_CB), "psk no client cb"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_PSK_NO_SERVER_CB), "psk no server cb"},
+    {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_QUIC_HANDSHAKE_LAYER_ERROR),
+    "quic handshake layer error"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_QUIC_NETWORK_ERROR), "quic network error"},
     {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_QUIC_PROTOCOL_ERROR),
     "quic protocol error"},
index aefdba2ae566e54e9dd5d6b605882b8a5b0513bb..93c0b00bb5762f0b996bf6065e88a36de2d61860 100644 (file)
@@ -4559,6 +4559,11 @@ int SSL_set_ssl_method(SSL *s, const SSL_METHOD *meth)
 }
 
 int SSL_get_error(const SSL *s, int i)
+{
+    return ossl_ssl_get_error(s, i, /*check_err=*/1);
+}
+
+int ossl_ssl_get_error(const SSL *s, int i, int check_err)
 {
     int reason;
     unsigned long l;
@@ -4583,7 +4588,7 @@ int SSL_get_error(const SSL *s, int i)
      * Make things return SSL_ERROR_SYSCALL when doing SSL_do_handshake etc,
      * where we do encode the error
      */
-    if ((l = ERR_peek_error()) != 0) {
+    if (check_err && (l = ERR_peek_error()) != 0) {
         if (ERR_GET_LIB(l) == ERR_LIB_SYS)
             return SSL_ERROR_SYSCALL;
         else
index 9871821a6f6bce6b00ab5e1ede8d3d680fbe94eb..b935455974047756cbe94f57fdecfd3f8cd3452e 100644 (file)
@@ -5528,3 +5528,5 @@ OSSL_ERR_STATE_new                      ? 3_2_0   EXIST::FUNCTION:
 OSSL_ERR_STATE_save                     ?      3_2_0   EXIST::FUNCTION:
 OSSL_ERR_STATE_restore                  ?      3_2_0   EXIST::FUNCTION:
 OSSL_ERR_STATE_free                     ?      3_2_0   EXIST::FUNCTION:
+ERR_count_to_mark                       ?      3_2_0   EXIST::FUNCTION:
+OSSL_ERR_STATE_save_to_mark             ?      3_2_0   EXIST::FUNCTION: