Fix CMP -days option range checking and test failing with enable-ubsan
[openssl.git] / crypto / err / err.c
index 25426be730911b22b23ca7e0cfe9aea5cb057ff5..9a37c426252f33367039f0be4b548c2103024197 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
 #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_locl.h"
+#include "err_local.h"
 
 /* Forward declaration in case it's not published because of configuration */
 ERR_STATE *ERR_get_state(void);
@@ -70,10 +70,13 @@ static ERR_STRING_DATA ERR_str_libraries[] = {
     {ERR_PACK(ERR_LIB_HMAC, 0, 0), "HMAC routines"},
     {ERR_PACK(ERR_LIB_CT, 0, 0), "CT routines"},
     {ERR_PACK(ERR_LIB_ASYNC, 0, 0), "ASYNC routines"},
+    {ERR_PACK(ERR_LIB_KDF, 0, 0), "KDF routines"},
     {ERR_PACK(ERR_LIB_OSSL_STORE, 0, 0), "STORE routines"},
     {ERR_PACK(ERR_LIB_SM2, 0, 0), "SM2 routines"},
     {ERR_PACK(ERR_LIB_ESS, 0, 0), "ESS routines"},
     {ERR_PACK(ERR_LIB_PROV, 0, 0), "Provider routines"},
+    {ERR_PACK(ERR_LIB_OSSL_SERIALIZER, 0, 0), "SERIALIZER routines"},
+    {ERR_PACK(ERR_LIB_HTTP, 0, 0), "HTTP routines"},
     {0, NULL},
 };
 
@@ -110,6 +113,8 @@ static ERR_STRING_DATA ERR_str_reasons[] = {
     {ERR_R_DISABLED, "called a function that was disabled at compile-time"},
     {ERR_R_INIT_FAIL, "init fail"},
     {ERR_R_OPERATION_FAIL, "operation fail"},
+    {ERR_R_INVALID_PROVIDER_FUNCTIONS, "invalid provider functions"},
+    {ERR_R_INTERRUPTED_OR_CANCELLED, "interrupted or cancelled"},
 
     {0, NULL},
 };
@@ -131,9 +136,14 @@ 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 **func,
-                                      const char **data, int *flags);
+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)
 {
@@ -365,7 +375,7 @@ void ERR_clear_error(void)
     int i;
     ERR_STATE *es;
 
-    es = ERR_get_state();
+    es = err_get_state_int();
     if (es == NULL)
         return;
 
@@ -377,136 +387,126 @@ void ERR_clear_error(void)
 
 unsigned long ERR_get_error(void)
 {
-    return get_error_values(1, 0, NULL, 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, 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(1, 0, NULL, NULL, func, NULL, NULL);
+    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(1, 0, NULL, NULL, NULL, data, 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(1, 0, file, line, func, data, flags);
+    return get_error_values(EV_POP, file, line, func, data, flags);
 }
 
-#if !OPENSSL_API_3
+#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, NULL, 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, 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, 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(0, 0, NULL, NULL, func, NULL, NULL);
+    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(0, 0, NULL, NULL, NULL, data, 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(0, 0, file, line, func, data, flags);
+    return get_error_values(EV_PEEK, file, line, func, data, flags);
 }
 
-#if !OPENSSL_API_3
+#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, NULL, 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, 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, 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(0, 1, NULL, NULL, func, NULL, NULL);
+    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(0, 1, NULL, NULL, NULL, data, 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(0, 1, file, line, func, data, flags);
+    return get_error_values(EV_PEEK_LAST, file, line, func, data, flags);
 }
 
-#if !OPENSSL_API_3
+#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, NULL, 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 **func,
+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 != NULL)
-            *file = "";
-        if (line != NULL)
-            *line = 0;
-        if (func != NULL)
-            *func = "";
-        if (data != NULL)
-            *data = "";
-        if (flags != NULL)
-            *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);
@@ -522,49 +522,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 = "N/A";
+            *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;
@@ -629,7 +626,7 @@ const char *ERR_lib_error_string(unsigned long e)
     return ((p == NULL) ? NULL : p->string);
 }
 
-#if !OPENSSL_API_3
+#ifndef OPENSSL_NO_DEPRECATED_3_0
 const char *ERR_func_error_string(unsigned long e)
 {
     return NULL;
@@ -649,7 +646,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);
     }
@@ -667,13 +664,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)
 {
 }
@@ -685,7 +682,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();
@@ -724,6 +721,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.
@@ -786,7 +791,7 @@ static int err_set_error_data_int(char *data, size_t size, int flags,
 {
     ERR_STATE *es;
 
-    es = ERR_get_state();
+    es = err_get_state_int();
     if (es == NULL)
         return 0;
 
@@ -831,7 +836,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;
@@ -886,7 +891,7 @@ int ERR_set_mark(void)
 {
     ERR_STATE *es;
 
-    es = ERR_get_state();
+    es = err_get_state_int();
     if (es == NULL)
         return 0;
 
@@ -900,7 +905,7 @@ int ERR_pop_to_mark(void)
 {
     ERR_STATE *es;
 
-    es = ERR_get_state();
+    es = err_get_state_int();
     if (es == NULL)
         return 0;
 
@@ -921,7 +926,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;
 
@@ -942,7 +947,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;