aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/utils/exceptn.h
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2018-11-17 16:23:51 -0500
committerJack Lloyd <[email protected]>2018-11-23 11:15:25 -0500
commitb909778857b3e0b7eb86ac26c818e5f25baaddbd (patch)
treef8a5c9cbec26310bbfc9077563892b04db158a48 /src/lib/utils/exceptn.h
parentc20a428ca2f7c1ef96e642f55bb898010444c499 (diff)
Make exceptions easier to translate to error codes
Avoid throwing base Botan::Exception type, as it is difficult to determine what the error is in that case. Add Exception::error_code and Exception::error_type which allows (for error code) more information about the error and (for error type) allows knowing the error type without requiring a sequence of catches. See GH #1742
Diffstat (limited to 'src/lib/utils/exceptn.h')
-rw-r--r--src/lib/utils/exceptn.h306
1 files changed, 238 insertions, 68 deletions
diff --git a/src/lib/utils/exceptn.h b/src/lib/utils/exceptn.h
index dfe428d72..bfff85618 100644
--- a/src/lib/utils/exceptn.h
+++ b/src/lib/utils/exceptn.h
@@ -1,6 +1,6 @@
/*
* Exceptions
-* (C) 1999-2009 Jack Lloyd
+* (C) 1999-2009,2018 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -15,22 +15,104 @@
namespace Botan {
/**
+* Different types of errors that might occur
+*/
+enum class ErrorType {
+ /** Some unknown error */
+ Unknown = 1,
+ /** An error while calling a system interface */
+ SystemError,
+ /** An operation seems valid, but not supported by the current version */
+ NotImplemented,
+ /** Memory allocation failure */
+ OutOfMemory,
+ /** An internal error occurred */
+ InternalError,
+ /** An I/O error occurred */
+ IoError,
+
+ /** Invalid object state */
+ InvalidObjectState = 100,
+ /** A key was not set on an object when this is required */
+ KeyNotSet,
+ /** The application provided an argument which is invalid */
+ InvalidArgument,
+ /** A key with invalid length was provided */
+ InvalidKeyLength,
+ /** A nonce with invalid length was provided */
+ InvalidNonceLength,
+ /** An object type was requested but cannot be found */
+ LookupError,
+ /** Encoding a message or datum failed */
+ EncodingFailure,
+ /** Decoding a message or datum failed */
+ DecodingFailure,
+ /** A TLS error (error_code will be the alert type) */
+ TLSError,
+ /** An error during an HTTP operation */
+ HttpError,
+
+ /** An error when calling OpenSSL */
+ OpenSSLError = 200,
+ /** An error when interacting with CommonCrypto API */
+ CommonCryptoError,
+ /** An error when interacting with a PKCS11 device */
+ Pkcs11Error,
+ /** An error when interacting with a TPM device */
+ TPMError,
+
+ /** An error when interacting with zlib */
+ ZlibError = 300,
+ /** An error when interacting with bzip2 */
+ Bzip2Error,
+ /** An error when interacting with lzma */
+ LzmaError,
+
+};
+
+/**
* Base class for all exceptions thrown by the library
*/
class BOTAN_PUBLIC_API(2,0) Exception : public std::exception
{
public:
- Exception(const char* prefix, const std::string& msg);
- explicit Exception(const std::string& msg);
+ /**
+ * Return a descriptive string which is hopefully comprehensible to
+ * a developer. It will likely not be useful for an end user.
+ *
+ * The string has no particular format, and the content of exception
+ * messages may change from release to release. Thus the main use of this
+ * function is for logging or debugging.
+ */
const char* what() const noexcept override { return m_msg.c_str(); }
+
+ /**
+ * Return the "type" of error which occurred.
+ */
+ virtual ErrorType error_type() const noexcept { return Botan::ErrorType::Unknown; }
+
+ /**
+ * Return an error code associated with this exception, or otherwise 0.
+ *
+ * The domain of this error varies depending on the source, for example on
+ * POSIX systems it might be errno, while on a Windows system it might be
+ * the result of GetLastError or WSAGetLastError. For error_type() is
+ * OpenSSLError, it will (if nonzero) be an OpenSSL error code from
+ * ERR_get_error.
+ */
+ virtual int error_code() const noexcept { return 0; }
+
protected:
+ explicit Exception(const std::string& msg);
+ Exception(const char* prefix, const std::string& msg);
Exception(const std::string& msg, const std::exception& e);
+
private:
std::string m_msg;
};
/**
-* An invalid argument
+* An invalid argument was provided to an API call.
*/
class BOTAN_PUBLIC_API(2,0) Invalid_Argument : public Exception
{
@@ -40,95 +122,126 @@ class BOTAN_PUBLIC_API(2,0) Invalid_Argument : public Exception
explicit Invalid_Argument(const std::string& msg, const std::string& where);
Invalid_Argument(const std::string& msg, const std::exception& e);
+
+ ErrorType error_type() const noexcept override { return ErrorType::InvalidArgument; }
};
/**
-* Unsupported_Argument Exception
-*
-* An argument that is invalid because it is not supported by Botan.
-* It might or might not be valid in another context like a standard.
+* An invalid key length was used
*/
-class BOTAN_PUBLIC_API(2,0) Unsupported_Argument final : public Invalid_Argument
+class BOTAN_PUBLIC_API(2,0) Invalid_Key_Length final : public Invalid_Argument
{
public:
- explicit Unsupported_Argument(const std::string& msg) : Invalid_Argument(msg) {}
+ Invalid_Key_Length(const std::string& name, size_t length);
+ ErrorType error_type() const noexcept override { return ErrorType::InvalidKeyLength; }
};
/**
-* Invalid_State Exception
+* An invalid nonce length was used
*/
-class BOTAN_PUBLIC_API(2,0) Invalid_State : public Exception
+class BOTAN_PUBLIC_API(2,0) Invalid_IV_Length final : public Invalid_Argument
{
public:
- explicit Invalid_State(const std::string& err) : Exception(err) {}
+ Invalid_IV_Length(const std::string& mode, size_t bad_len);
+ ErrorType error_type() const noexcept override { return ErrorType::InvalidNonceLength; }
};
-class BOTAN_PUBLIC_API(2,4) Key_Not_Set : public Invalid_State
+/**
+* Invalid_Algorithm_Name Exception
+*/
+class BOTAN_PUBLIC_API(2,0) Invalid_Algorithm_Name final : public Invalid_Argument
{
public:
- explicit Key_Not_Set(const std::string& algo);
+ explicit Invalid_Algorithm_Name(const std::string& name);
};
/**
-* Lookup_Error Exception
+* Encoding_Error Exception
+*
+* This exception derives from Invalid_Argument for historical reasons, and it
+* does not make any real sense for it to do so. In a future major release this
+* exception type will derive directly from Exception instead.
*/
-class BOTAN_PUBLIC_API(2,0) Lookup_Error : public Exception
+class BOTAN_PUBLIC_API(2,0) Encoding_Error final : public Invalid_Argument
{
public:
- explicit Lookup_Error(const std::string& err) : Exception(err) {}
+ explicit Encoding_Error(const std::string& name);
- Lookup_Error(const std::string& type,
- const std::string& algo,
- const std::string& provider);
+ ErrorType error_type() const noexcept override { return ErrorType::EncodingFailure; }
};
/**
-* Internal_Error Exception
+* A decoding error occurred.
+*
+* This exception derives from Invalid_Argument for historical reasons, and it
+* does not make any real sense for it to do so. In a future major release this
+* exception type will derive directly from Exception instead.
*/
-class BOTAN_PUBLIC_API(2,0) Internal_Error : public Exception
+class BOTAN_PUBLIC_API(2,0) Decoding_Error : public Invalid_Argument
{
public:
- explicit Internal_Error(const std::string& err);
+ explicit Decoding_Error(const std::string& name);
+
+ Decoding_Error(const std::string& name, const char* exception_message);
+
+ Decoding_Error(const std::string& msg, const std::exception& e);
+
+ ErrorType error_type() const noexcept override { return ErrorType::DecodingFailure; }
};
/**
-* Invalid_Key_Length Exception
+* Invalid state was encountered. A request was made on an object while the
+* object was in a state where the operation cannot be performed.
*/
-class BOTAN_PUBLIC_API(2,0) Invalid_Key_Length final : public Invalid_Argument
+class BOTAN_PUBLIC_API(2,0) Invalid_State : public Exception
{
public:
- Invalid_Key_Length(const std::string& name, size_t length);
+ explicit Invalid_State(const std::string& err) : Exception(err) {}
+
+ ErrorType error_type() const noexcept override { return ErrorType::InvalidObjectState; }
};
/**
-* Invalid_IV_Length Exception
+* A PRNG was called on to produce output while still unseeded
*/
-class BOTAN_PUBLIC_API(2,0) Invalid_IV_Length final : public Invalid_Argument
+class BOTAN_PUBLIC_API(2,0) PRNG_Unseeded final : public Invalid_State
{
public:
- Invalid_IV_Length(const std::string& mode, size_t bad_len);
+ explicit PRNG_Unseeded(const std::string& algo);
};
/**
-* PRNG_Unseeded Exception
+* The key was not set on an object. This occurs with symmetric objects where
+* an operation which requires the key is called prior to set_key being called.
*/
-class BOTAN_PUBLIC_API(2,0) PRNG_Unseeded final : public Invalid_State
+class BOTAN_PUBLIC_API(2,4) Key_Not_Set : public Invalid_State
{
public:
- explicit PRNG_Unseeded(const std::string& algo);
+ explicit Key_Not_Set(const std::string& algo);
+
+ ErrorType error_type() const noexcept override { return ErrorType::KeyNotSet; }
};
/**
-* Policy_Violation Exception
+* A request was made for some kind of object which could not be located
*/
-class BOTAN_PUBLIC_API(2,0) Policy_Violation final : public Invalid_State
+class BOTAN_PUBLIC_API(2,0) Lookup_Error : public Exception
{
public:
- BOTAN_DEPRECATED("deprecated") explicit Policy_Violation(const std::string& err);
+ explicit Lookup_Error(const std::string& err) : Exception(err) {}
+
+ Lookup_Error(const std::string& type,
+ const std::string& algo,
+ const std::string& provider);
+
+ ErrorType error_type() const noexcept override { return ErrorType::LookupError; }
};
/**
* Algorithm_Not_Found Exception
+*
+* @warning This exception type will be removed in the future. Instead
+* just catch Lookup_Error.
*/
class BOTAN_PUBLIC_API(2,0) Algorithm_Not_Found final : public Lookup_Error
{
@@ -137,66 +250,98 @@ class BOTAN_PUBLIC_API(2,0) Algorithm_Not_Found final : public Lookup_Error
};
/**
-* No_Provider_Found Exception
+* Provider_Not_Found is thrown when a specific provider was requested
+* but that provider is not available.
+*
+* @warning This exception type will be removed in the future. Instead
+* just catch Lookup_Error.
*/
-class BOTAN_PUBLIC_API(2,0) No_Provider_Found final : public Exception
+class BOTAN_PUBLIC_API(2,0) Provider_Not_Found final : public Lookup_Error
{
public:
- BOTAN_DEPRECATED("deprecated") explicit No_Provider_Found(const std::string& name);
+ Provider_Not_Found(const std::string& algo, const std::string& provider);
};
/**
-* Provider_Not_Found is thrown when a specific provider was requested
-* but that provider is not available.
+* An AEAD or MAC check detected a message modification
*/
-class BOTAN_PUBLIC_API(2,0) Provider_Not_Found final : public Lookup_Error
+class BOTAN_PUBLIC_API(2,0) Integrity_Failure final : public Exception
{
public:
- Provider_Not_Found(const std::string& algo, const std::string& provider);
+ explicit Integrity_Failure(const std::string& msg);
+
+ ErrorType error_type() const noexcept override { return ErrorType::DecodingFailure; }
};
/**
-* Invalid_Algorithm_Name Exception
+* An error occurred while operating on an IO stream
*/
-class BOTAN_PUBLIC_API(2,0) Invalid_Algorithm_Name final : public Invalid_Argument
+class BOTAN_PUBLIC_API(2,0) Stream_IO_Error final : public Exception
{
public:
- explicit Invalid_Algorithm_Name(const std::string& name);
+ explicit Stream_IO_Error(const std::string& err);
+
+ ErrorType error_type() const noexcept override { return ErrorType::IoError; }
};
/**
-* Encoding_Error Exception
+* System_Error
+*
+* This exception is thrown in the event of an error related to interacting
+* with the operating system.
+*
+* This exception type also (optionally) captures an integer error code eg
+* POSIX errno or Windows GetLastError.
*/
-class BOTAN_PUBLIC_API(2,0) Encoding_Error final : public Invalid_Argument
+class BOTAN_PUBLIC_API(2,9) System_Error : public Exception
{
public:
- explicit Encoding_Error(const std::string& name);
+ System_Error(const std::string& msg) : Exception(msg), m_error_code(0) {}
+
+ System_Error(const std::string& msg, int err_code);
+
+ ErrorType error_type() const noexcept override { return ErrorType::SystemError; }
+
+ int error_code() const noexcept override { return m_error_code; }
+
+ private:
+ int m_error_code;
};
/**
-* Decoding_Error Exception
+* An internal error occurred. If observed, please file a bug.
*/
-class BOTAN_PUBLIC_API(2,0) Decoding_Error : public Invalid_Argument
+class BOTAN_PUBLIC_API(2,0) Internal_Error : public Exception
{
public:
- explicit Decoding_Error(const std::string& name);
-
- Decoding_Error(const std::string& name, const char* exception_message);
+ explicit Internal_Error(const std::string& err);
- Decoding_Error(const std::string& msg, const std::exception& e);
+ ErrorType error_type() const noexcept override { return ErrorType::InternalError; }
};
/**
-* Integrity_Failure Exception
+* Not Implemented Exception
+*
+* This is thrown in the situation where a requested operation is
+* logically valid but is not implemented by this version of the library.
*/
-class BOTAN_PUBLIC_API(2,0) Integrity_Failure final : public Exception
+class BOTAN_PUBLIC_API(2,0) Not_Implemented final : public Exception
{
public:
- explicit Integrity_Failure(const std::string& msg);
+ explicit Not_Implemented(const std::string& err);
+
+ ErrorType error_type() const noexcept override { return ErrorType::NotImplemented; }
};
+/*
+ The following exception types are still in use for compatability reasons,
+ but are deprecated and will be removed in a future major release
+*/
+
/**
-* Invalid_OID Exception
+* An invalid OID string was used.
+*
+* This exception will be removed in a future major release.
*/
class BOTAN_PUBLIC_API(2,0) Invalid_OID final : public Decoding_Error
{
@@ -204,33 +349,58 @@ class BOTAN_PUBLIC_API(2,0) Invalid_OID final : public Decoding_Error
explicit Invalid_OID(const std::string& oid);
};
+/*
+ The following exception types are deprecated, no longer used,
+ and will be removed in a future major release
+*/
+
/**
-* Stream_IO_Error Exception
+* Self Test Failure Exception
*/
-class BOTAN_PUBLIC_API(2,0) Stream_IO_Error final : public Exception
+class BOTAN_PUBLIC_API(2,0) Self_Test_Failure final : public Internal_Error
{
public:
- explicit Stream_IO_Error(const std::string& err);
+ BOTAN_DEPRECATED("no longer used") explicit Self_Test_Failure(const std::string& err);
};
/**
-* Self Test Failure Exception
+* No_Provider_Found Exception
*/
-class BOTAN_PUBLIC_API(2,0) Self_Test_Failure final : public Internal_Error
+class BOTAN_PUBLIC_API(2,0) No_Provider_Found final : public Exception
{
public:
- BOTAN_DEPRECATED("deprecated") explicit Self_Test_Failure(const std::string& err);
+ BOTAN_DEPRECATED("no longer used") explicit No_Provider_Found(const std::string& name);
};
/**
-* Not Implemented Exception
+* Policy_Violation Exception
*/
-class BOTAN_PUBLIC_API(2,0) Not_Implemented final : public Exception
+class BOTAN_PUBLIC_API(2,0) Policy_Violation final : public Invalid_State
{
public:
- explicit Not_Implemented(const std::string& err);
+ BOTAN_DEPRECATED("no longer used") explicit Policy_Violation(const std::string& err);
+ };
+
+/**
+* Unsupported_Argument Exception
+*
+* An argument that is invalid because it is not supported by Botan.
+* It might or might not be valid in another context like a standard.
+*
+* This exception is no longer used, instead Not_Implemented is thrown.
+*/
+class BOTAN_PUBLIC_API(2,0) Unsupported_Argument final : public Invalid_Argument
+ {
+ public:
+ BOTAN_DEPRECATED("no longer used") explicit Unsupported_Argument(const std::string& msg) : Invalid_Argument(msg) {}
};
+template<typename E, typename... Args>
+inline void do_throw_error(const char* file, int line, const char* func, Args... args)
+ {
+ throw E(file, line, func, args...);
+ }
+
}
#endif