Reinstate the KDF error macros
[openssl.git] / crypto / err / err.c
index 7a35512f879802ea08b18a1f3258f94856b32085..bc33a06b7e6139bbe3a4cfa378377be16361a7fd 100644 (file)
@@ -7,21 +7,28 @@
  * https://www.openssl.org/source/license.html
  */
 
+/* TODO: When ERR_STATE becomes opaque, this musts be removed */
+#define OSSL_FORCE_ERR_STATE
+
 #include <stdio.h>
 #include <stdarg.h>
 #include <string.h>
-#include "internal/cryptlib_int.h"
+#include "crypto/cryptlib.h"
 #include "internal/err.h"
-#include "internal/err_int.h"
+#include "crypto/err.h"
 #include <openssl/err.h>
 #include <openssl/crypto.h>
 #include <openssl/buffer.h>
 #include <openssl/bio.h>
 #include <openssl/opensslconf.h>
 #include "internal/thread_once.h"
-#include "internal/ctype.h"
-#include "internal/constant_time_locl.h"
+#include "crypto/ctype.h"
+#include "internal/constant_time.h"
 #include "e_os.h"
+#include "err_local.h"
+
+/* Forward declaration in case it's not published because of configuration */
+ERR_STATE *ERR_get_state(void);
 
 static int err_load_strings(const ERR_STRING_DATA *str);
 
@@ -125,8 +132,13 @@ static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *);
 static LHASH_OF(ERR_STRING_DATA) *int_error_hash = NULL;
 static int int_err_library_number = ERR_LIB_USER;
 
-static unsigned long get_error_values(int inc, int top, const char **file,
-                                      int *line, const char **data,
+typedef enum ERR_GET_ACTION_e {
+    EV_POP, EV_PEEK, EV_PEEK_LAST
+} ERR_GET_ACTION;
+
+static unsigned long get_error_values(ERR_GET_ACTION g,
+                                      const char **file, int *line,
+                                      const char **func, const char **data,
                                       int *flags);
 
 static unsigned long err_string_data_hash(const ERR_STRING_DATA *a)
@@ -235,40 +247,6 @@ static void build_SYS_str_reasons(void)
 }
 #endif
 
-#define err_get_slot(p) \
-    do { \
-        (p)->top = ((p)->top + 1) % ERR_NUM_ERRORS; \
-        if ((p)->top == (p)->bottom) \
-            (p)->bottom = ((p)->bottom + 1) % ERR_NUM_ERRORS; \
-    } while (0)
-
-#define err_clear_data(p, i, deall)                             \
-        do {                                                    \
-            if ((p)->err_data_flags[i] & ERR_TXT_MALLOCED) {    \
-                if (deall) {                                    \
-                    OPENSSL_free((p)->err_data[i]);             \
-                    (p)->err_data[i] = NULL;                    \
-                    (p)->err_data_size[i] = 0;                  \
-                    (p)->err_data_flags[i] = 0;                 \
-                } else if ((p)->err_data[i] != NULL) {          \
-                    (p)->err_data[i][0] = '\0';                 \
-                }                                               \
-            } else {                                            \
-                (p)->err_data[i] = NULL;                        \
-                (p)->err_data_size[i] = 0;                      \
-                (p)->err_data_flags[i] = 0;                     \
-            }                                                   \
-        } while (0)
-
-#define err_clear(p, i, deall) \
-        do { \
-            err_clear_data((p), (i), (deall)); \
-            (p)->err_flags[i] = 0; \
-            (p)->err_buffer[i] = 0; \
-            (p)->err_file[i] = NULL; \
-            (p)->err_line[i] = -1; \
-        } while (0)
-
 static void ERR_STATE_free(ERR_STATE *s)
 {
     int i;
@@ -388,53 +366,12 @@ void err_free_strings_int(void)
 
 /********************************************************/
 
-void ERR_put_func_error(int lib, const char *func, int reason,
-                        const char *file, int line)
-{
-    ERR_put_error(lib, 0, reason, file, line);
-    ERR_add_error_data(2, "calling function ", func);
-}
-
-void ERR_put_error(int lib, int func, int reason, const char *file, int line)
-{
-    ERR_STATE *es;
-
-#ifdef _OSD_POSIX
-    /*
-     * In the BS2000-OSD POSIX subsystem, the compiler generates path names
-     * in the form "*POSIX(/etc/passwd)". This dirty hack strips them to
-     * something sensible. @@@ We shouldn't modify a const string, though.
-     */
-    if (strncmp(file, "*POSIX(", sizeof("*POSIX(") - 1) == 0) {
-        char *end;
-
-        /* Skip the "*POSIX(" prefix */
-        file += sizeof("*POSIX(") - 1;
-        end = &file[strlen(file) - 1];
-        if (*end == ')')
-            *end = '\0';
-        /* Optional: use the basename of the path only. */
-        if ((end = strrchr(file, '/')) != NULL)
-            file = &end[1];
-    }
-#endif
-    es = ERR_get_state();
-    if (es == NULL)
-        return;
-
-    err_get_slot(es);
-    err_clear(es, es->top, 0);
-    es->err_buffer[es->top] = ERR_PACK(lib, func, reason);
-    es->err_file[es->top] = file;
-    es->err_line[es->top] = line;
-}
-
 void ERR_clear_error(void)
 {
     int i;
     ERR_STATE *es;
 
-    es = ERR_get_state();
+    es = err_get_state_int();
     if (es == NULL)
         return;
 
@@ -446,77 +383,126 @@ void ERR_clear_error(void)
 
 unsigned long ERR_get_error(void)
 {
-    return get_error_values(1, 0, NULL, NULL, NULL, NULL);
+    return get_error_values(EV_POP, NULL, NULL, NULL, NULL, NULL);
 }
 
 unsigned long ERR_get_error_line(const char **file, int *line)
 {
-    return get_error_values(1, 0, file, line, NULL, NULL);
+    return get_error_values(EV_POP, file, line, NULL, NULL, NULL);
 }
 
+unsigned long ERR_get_error_func(const char **func)
+{
+    return get_error_values(EV_POP, NULL, NULL, func, NULL, NULL);
+}
+
+unsigned long ERR_get_error_data(const char **data, int *flags)
+{
+    return get_error_values(EV_POP, NULL, NULL, NULL, data, flags);
+}
+
+unsigned long ERR_get_error_all(const char **file, int *line,
+                                const char **func,
+                                const char **data, int *flags)
+{
+    return get_error_values(EV_POP, file, line, func, data, flags);
+}
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
 unsigned long ERR_get_error_line_data(const char **file, int *line,
                                       const char **data, int *flags)
 {
-    return get_error_values(1, 0, file, line, data, flags);
+    return get_error_values(EV_POP, file, line, NULL, data, flags);
 }
+#endif
 
 unsigned long ERR_peek_error(void)
 {
-    return get_error_values(0, 0, NULL, NULL, NULL, NULL);
+    return get_error_values(EV_PEEK, NULL, NULL, NULL, NULL, NULL);
 }
 
 unsigned long ERR_peek_error_line(const char **file, int *line)
 {
-    return get_error_values(0, 0, file, line, NULL, NULL);
+    return get_error_values(EV_PEEK, file, line, NULL, NULL, NULL);
 }
 
+unsigned long ERR_peek_error_func(const char **func)
+{
+    return get_error_values(EV_PEEK, NULL, NULL, func, NULL, NULL);
+}
+
+unsigned long ERR_peek_error_data(const char **data, int *flags)
+{
+    return get_error_values(EV_PEEK, NULL, NULL, NULL, data, flags);
+}
+
+unsigned long ERR_peek_error_all(const char **file, int *line,
+                                 const char **func,
+                                 const char **data, int *flags)
+{
+    return get_error_values(EV_PEEK, file, line, func, data, flags);
+}
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
 unsigned long ERR_peek_error_line_data(const char **file, int *line,
                                        const char **data, int *flags)
 {
-    return get_error_values(0, 0, file, line, data, flags);
+    return get_error_values(EV_PEEK, file, line, NULL, data, flags);
 }
+#endif
 
 unsigned long ERR_peek_last_error(void)
 {
-    return get_error_values(0, 1, NULL, NULL, NULL, NULL);
+    return get_error_values(EV_PEEK_LAST, NULL, NULL, NULL, NULL, NULL);
 }
 
 unsigned long ERR_peek_last_error_line(const char **file, int *line)
 {
-    return get_error_values(0, 1, file, line, NULL, NULL);
+    return get_error_values(EV_PEEK_LAST, file, line, NULL, NULL, NULL);
 }
 
+unsigned long ERR_peek_last_error_func(const char **func)
+{
+    return get_error_values(EV_PEEK_LAST, NULL, NULL, func, NULL, NULL);
+}
+
+unsigned long ERR_peek_last_error_data(const char **data, int *flags)
+{
+    return get_error_values(EV_PEEK_LAST, NULL, NULL, NULL, data, flags);
+}
+
+unsigned long ERR_peek_last_error_all(const char **file, int *line,
+                                      const char **func,
+                                      const char **data, int *flags)
+{
+    return get_error_values(EV_PEEK_LAST, file, line, func, data, flags);
+}
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
 unsigned long ERR_peek_last_error_line_data(const char **file, int *line,
                                             const char **data, int *flags)
 {
-    return get_error_values(0, 1, file, line, data, flags);
+    return get_error_values(EV_PEEK_LAST, file, line, NULL, data, flags);
 }
+#endif
 
-static unsigned long get_error_values(int inc, int top, const char **file,
-                                      int *line, const char **data,
-                                      int *flags)
+static unsigned long get_error_values(ERR_GET_ACTION g,
+                                      const char **file, int *line,
+                                      const char **func,
+                                      const char **data, int *flags)
 {
     int i = 0;
     ERR_STATE *es;
     unsigned long ret;
 
-    es = ERR_get_state();
+    es = err_get_state_int();
     if (es == NULL)
         return 0;
 
-    if (inc && top) {
-        if (file)
-            *file = "";
-        if (line)
-            *line = 0;
-        if (data)
-            *data = "";
-        if (flags)
-            *flags = 0;
-
-        return ERR_R_INTERNAL_ERROR;
-    }
-
+    /*
+     * Clear anything that should have been cleared earlier. We do this
+     * here because this doesn't have constant-time issues.
+     */
     while (es->bottom != es->top) {
         if (es->err_flags[es->top] & ERR_FLAG_CLEAR) {
             err_clear(es, es->top, 0);
@@ -532,43 +518,46 @@ static unsigned long get_error_values(int inc, int top, const char **file,
         break;
     }
 
+    /* If everything has been cleared, the stack is empty. */
     if (es->bottom == es->top)
         return 0;
 
-    if (top)
-        i = es->top;            /* last error */
+    /* Which error, the top of stack (latest one) or the first one? */
+    if (g == EV_PEEK_LAST)
+        i = es->top;
     else
-        i = (es->bottom + 1) % ERR_NUM_ERRORS; /* first error */
+        i = (es->bottom + 1) % ERR_NUM_ERRORS;
 
     ret = es->err_buffer[i];
-    if (inc) {
+    if (g == EV_POP) {
         es->bottom = i;
         es->err_buffer[i] = 0;
     }
 
-    if (file != NULL && line != NULL) {
-        if (es->err_file[i] == NULL) {
-            *file = "NA";
-            *line = 0;
-        } else {
-            *file = es->err_file[i];
-            *line = es->err_line[i];
-        }
+    if (file != NULL) {
+        *file = es->err_file[i];
+        if (*file == NULL)
+            *file = "";
     }
-
+    if (line != NULL)
+        *line = es->err_line[i];
+    if (func != NULL) {
+        *func = es->err_func[i];
+        if (*func == NULL)
+            *func = "";
+    }
+    if (flags != NULL)
+        *flags = es->err_data_flags[i];
     if (data == NULL) {
-        if (inc) {
+        if (g == EV_POP) {
             err_clear_data(es, i, 0);
         }
     } else {
-        if (es->err_data[i] == NULL) {
+        *data = es->err_data[i];
+        if (*data == NULL) {
             *data = "";
             if (flags != NULL)
                 *flags = 0;
-        } else {
-            *data = es->err_data[i];
-            if (flags != NULL)
-                *flags = es->err_data_flags[i];
         }
     }
     return ret;
@@ -633,12 +622,12 @@ const char *ERR_lib_error_string(unsigned long e)
     return ((p == NULL) ? NULL : p->string);
 }
 
+#ifndef OPENSSL_NO_DEPRECATED_3_0
 const char *ERR_func_error_string(unsigned long e)
 {
-    if (!RUN_ONCE(&err_string_init, do_err_strings_init))
-        return NULL;
-    return ERR_GET_LIB(e) == ERR_LIB_SYS ? "system library" : NULL;
+    return NULL;
 }
+#endif
 
 const char *ERR_reason_error_string(unsigned long e)
 {
@@ -653,7 +642,7 @@ const char *ERR_reason_error_string(unsigned long e)
     r = ERR_GET_REASON(e);
     d.error = ERR_PACK(l, 0, r);
     p = int_err_get_item(&d);
-    if (!p) {
+    if (p == NULL) {
         d.error = ERR_PACK(0, 0, r);
         p = int_err_get_item(&d);
     }
@@ -671,13 +660,13 @@ static void err_delete_thread_state(void *arg)
     ERR_STATE_free(state);
 }
 
-#if !OPENSSL_API_1_1_0
+#ifndef OPENSSL_NO_DEPRECATED_1_1_0
 void ERR_remove_thread_state(void *dummy)
 {
 }
 #endif
 
-#if !OPENSSL_API_1_0_0
+#ifndef OPENSSL_NO_DEPRECATED_1_0_0
 void ERR_remove_state(unsigned long pid)
 {
 }
@@ -689,7 +678,7 @@ DEFINE_RUN_ONCE_STATIC(err_do_init)
     return CRYPTO_THREAD_init_local(&err_thread_local, NULL);
 }
 
-ERR_STATE *ERR_get_state(void)
+ERR_STATE *err_get_state_int(void)
 {
     ERR_STATE *state;
     int saveerrno = get_last_sys_error();
@@ -728,6 +717,14 @@ ERR_STATE *ERR_get_state(void)
     return state;
 }
 
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ERR_STATE *ERR_get_state(void)
+{
+    return err_get_state_int();
+}
+#endif
+
+
 /*
  * err_shelve_state returns the current thread local error state
  * and freezes the error module until err_unshelve_state is called.
@@ -789,18 +786,13 @@ static int err_set_error_data_int(char *data, size_t size, int flags,
                                   int deallocate)
 {
     ERR_STATE *es;
-    int i;
 
-    es = ERR_get_state();
+    es = err_get_state_int();
     if (es == NULL)
         return 0;
 
-    i = es->top;
-
     err_clear_data(es, es->top, deallocate);
-    es->err_data[i] = data;
-    es->err_data_size[i] = size;
-    es->err_data_flags[i] = flags;
+    err_set_data(es, es->top, data, size, flags);
 
     return 1;
 }
@@ -840,7 +832,7 @@ void ERR_add_error_vdata(int num, va_list args)
     ERR_STATE *es;
 
     /* Get the current error data; if an allocated string get it. */
-    es = ERR_get_state();
+    es = err_get_state_int();
     if (es == NULL)
         return;
     i = es->top;
@@ -869,23 +861,23 @@ void ERR_add_error_vdata(int num, va_list args)
     }
     len = strlen(str);
 
-    for (len = 0; --num >= 0; ) {
+    while (--num >= 0) {
         arg = va_arg(args, char *);
         if (arg == NULL)
             arg = "<NULL>";
         len += strlen(arg);
-        if (len > size) {
+        if (len >= size) {
             char *p;
 
             size = len + 20;
-            p = OPENSSL_realloc(str, size + 1);
+            p = OPENSSL_realloc(str, size);
             if (p == NULL) {
                 OPENSSL_free(str);
                 return;
             }
             str = p;
         }
-        OPENSSL_strlcat(str, arg, (size_t)size + 1);
+        OPENSSL_strlcat(str, arg, (size_t)size);
     }
     if (!err_set_error_data_int(str, size, flags, 0))
         OPENSSL_free(str);
@@ -895,7 +887,7 @@ int ERR_set_mark(void)
 {
     ERR_STATE *es;
 
-    es = ERR_get_state();
+    es = err_get_state_int();
     if (es == NULL)
         return 0;
 
@@ -909,7 +901,7 @@ int ERR_pop_to_mark(void)
 {
     ERR_STATE *es;
 
-    es = ERR_get_state();
+    es = err_get_state_int();
     if (es == NULL)
         return 0;
 
@@ -930,7 +922,7 @@ int ERR_clear_last_mark(void)
     ERR_STATE *es;
     int top;
 
-    es = ERR_get_state();
+    es = err_get_state_int();
     if (es == NULL)
         return 0;
 
@@ -951,7 +943,7 @@ void err_clear_last_constant_time(int clear)
     ERR_STATE *es;
     int top;
 
-    es = ERR_get_state();
+    es = err_get_state_int();
     if (es == NULL)
         return;