aboutsummaryrefslogtreecommitdiffstats
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
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
-rw-r--r--src/lib/compression/bzip2/bzip2.cpp24
-rw-r--r--src/lib/compression/compress_utils.cpp4
-rw-r--r--src/lib/compression/compression.h32
-rw-r--r--src/lib/compression/lzma/lzma.cpp18
-rw-r--r--src/lib/compression/zlib/zlib.cpp22
-rw-r--r--src/lib/entropy/dev_random/dev_random.cpp5
-rw-r--r--src/lib/ffi/ffi.cpp88
-rw-r--r--src/lib/ffi/ffi.h12
-rw-r--r--src/lib/ffi/ffi_util.h4
-rw-r--r--src/lib/filters/buf_filt.cpp2
-rw-r--r--src/lib/math/bigint/big_io.cpp2
-rw-r--r--src/lib/math/bigint/bigint.h7
-rw-r--r--src/lib/math/numbertheory/numthry.cpp2
-rw-r--r--src/lib/misc/fpe_fe1/fpe_fe1.cpp4
-rw-r--r--src/lib/misc/srp6/srp6.cpp10
-rw-r--r--src/lib/modes/aead/gcm/gcm.cpp2
-rw-r--r--src/lib/modes/cbc/cbc.cpp2
-rw-r--r--src/lib/pbkdf/pbkdf2/pbkdf2.cpp2
-rw-r--r--src/lib/pbkdf/scrypt/scrypt.cpp2
-rw-r--r--src/lib/prov/commoncrypto/commoncrypto.h17
-rw-r--r--src/lib/prov/openssl/openssl.h13
-rw-r--r--src/lib/prov/openssl/openssl_block.cpp40
-rw-r--r--src/lib/prov/openssl/openssl_ec.cpp20
-rw-r--r--src/lib/prov/openssl/openssl_hash.cpp12
-rw-r--r--src/lib/prov/openssl/openssl_mode.cpp26
-rw-r--r--src/lib/prov/openssl/openssl_rc4.cpp2
-rw-r--r--src/lib/prov/openssl/openssl_rsa.cpp22
-rw-r--r--src/lib/prov/pkcs11/p11.h2
-rw-r--r--src/lib/prov/pkcs11/p11_ecc_key.h2
-rw-r--r--src/lib/prov/pkcs11/p11_object.h10
-rw-r--r--src/lib/prov/tpm/tpm.h1
-rw-r--r--src/lib/pubkey/blinding.cpp4
-rw-r--r--src/lib/pubkey/ec_group/point_gfp.h17
-rw-r--r--src/lib/pubkey/mce/gf2m_small_m.cpp4
-rw-r--r--src/lib/pubkey/mceies/mceies.cpp4
-rw-r--r--src/lib/pubkey/pk_ops_impl.h4
-rw-r--r--src/lib/pubkey/pkcs8.cpp13
-rw-r--r--src/lib/pubkey/xmss/xmss_parameters.cpp3
-rw-r--r--src/lib/pubkey/xmss/xmss_wots_parameters.cpp3
-rw-r--r--src/lib/rng/auto_rng/auto_rng.cpp2
-rw-r--r--src/lib/rng/rdrand_rng/rdrand_rng.cpp2
-rw-r--r--src/lib/rng/rng.cpp4
-rw-r--r--src/lib/rng/stateful_rng/stateful_rng.cpp2
-rw-r--r--src/lib/rng/system_rng/system_rng.cpp16
-rw-r--r--src/lib/stream/rc4/rc4.cpp2
-rw-r--r--src/lib/tls/msg_client_hello.cpp2
-rw-r--r--src/lib/tls/sessions_sql/tls_session_manager_sql.cpp4
-rw-r--r--src/lib/tls/tls_callbacks.cpp5
-rw-r--r--src/lib/tls/tls_cbc/tls_cbc.cpp2
-rw-r--r--src/lib/tls/tls_channel.cpp20
-rw-r--r--src/lib/tls/tls_exceptn.h6
-rw-r--r--src/lib/tls/tls_policy.cpp2
-rw-r--r--src/lib/tls/tls_record.cpp2
-rw-r--r--src/lib/tls/tls_seq_numbers.h2
-rw-r--r--src/lib/tls/tls_text_policy.cpp2
-rw-r--r--src/lib/utils/assert.cpp2
-rw-r--r--src/lib/utils/dyn_load/dyn_load.cpp11
-rw-r--r--src/lib/utils/exceptn.cpp4
-rw-r--r--src/lib/utils/exceptn.h306
-rw-r--r--src/lib/utils/http_util/http_util.cpp2
-rw-r--r--src/lib/utils/http_util/http_util.h27
-rw-r--r--src/lib/utils/os_utils.cpp4
-rw-r--r--src/lib/utils/read_cfg.cpp2
-rw-r--r--src/lib/utils/safeint.h2
-rw-r--r--src/lib/utils/socket/socket.cpp31
-rw-r--r--src/lib/x509/key_constraint.cpp2
-rw-r--r--src/lib/x509/key_constraint.h2
-rw-r--r--src/lib/x509/ocsp.cpp5
-rw-r--r--src/lib/x509/x509_crl.h7
-rw-r--r--src/lib/x509/x509_ext.h2
-rw-r--r--src/lib/x509/x509_obj.cpp2
-rw-r--r--src/lib/x509/x509path.cpp8
-rw-r--r--src/tests/main.cpp2
-rw-r--r--src/tests/test_ffi.cpp4
-rw-r--r--src/tests/test_pkcs11_low_level.cpp12
-rw-r--r--src/tests/test_rng.cpp2
-rw-r--r--src/tests/test_rng.h4
-rw-r--r--src/tests/test_tests.cpp2
-rw-r--r--src/tests/test_tss.cpp8
-rw-r--r--src/tests/test_x509_path.cpp22
-rw-r--r--src/tests/tests.h1
81 files changed, 655 insertions, 359 deletions
diff --git a/src/lib/compression/bzip2/bzip2.cpp b/src/lib/compression/bzip2/bzip2.cpp
index 02d17ea07..c9dfc2ce8 100644
--- a/src/lib/compression/bzip2/bzip2.cpp
+++ b/src/lib/compression/bzip2/bzip2.cpp
@@ -48,10 +48,8 @@ class Bzip2_Compression_Stream final : public Bzip2_Stream
int rc = BZ2_bzCompressInit(streamp(), block_size, 0, 0);
- if(rc == BZ_MEM_ERROR)
- throw Exception("bzip memory allocation failure");
- else if(rc != BZ_OK)
- throw Exception("bzip compress initialization failed");
+ if(rc != BZ_OK)
+ throw Compression_Error("BZ2_bzCompressInit", ErrorType::Bzip2Error, rc);
}
~Bzip2_Compression_Stream()
@@ -63,10 +61,8 @@ class Bzip2_Compression_Stream final : public Bzip2_Stream
{
int rc = BZ2_bzCompress(streamp(), flags);
- if(rc == BZ_MEM_ERROR)
- throw Exception("bzip memory allocation failure");
- else if(rc < 0)
- throw Exception("bzip compress error " + std::to_string(-rc));
+ if(rc < 0)
+ throw Compression_Error("BZ2_bzCompress", ErrorType::Bzip2Error, rc);
return (rc == BZ_STREAM_END);
}
@@ -79,10 +75,8 @@ class Bzip2_Decompression_Stream final : public Bzip2_Stream
{
int rc = BZ2_bzDecompressInit(streamp(), 0, 0);
- if(rc == BZ_MEM_ERROR)
- throw Exception("bzip memory allocation failure");
- else if(rc != BZ_OK)
- throw Exception("bzip decompress initialization failed");
+ if(rc != BZ_OK)
+ throw Compression_Error("BZ2_bzDecompressInit", ErrorType::Bzip2Error, rc);
}
~Bzip2_Decompression_Stream()
@@ -94,10 +88,8 @@ class Bzip2_Decompression_Stream final : public Bzip2_Stream
{
int rc = BZ2_bzDecompress(streamp());
- if(rc == BZ_MEM_ERROR)
- throw Exception("bzip memory allocation failure");
- else if(rc != BZ_OK && rc != BZ_STREAM_END)
- throw Exception("bzip decompress error " + std::to_string(-rc));
+ if(rc != BZ_OK && rc != BZ_STREAM_END)
+ throw Compression_Error("BZ2_bzDecompress", ErrorType::Bzip2Error, rc);
return (rc == BZ_STREAM_END);
}
diff --git a/src/lib/compression/compress_utils.cpp b/src/lib/compression/compress_utils.cpp
index 6bdf3d0fd..f49a0ede1 100644
--- a/src/lib/compression/compress_utils.cpp
+++ b/src/lib/compression/compress_utils.cpp
@@ -39,7 +39,7 @@ void Compression_Alloc_Info::do_free(void* ptr)
auto i = m_current_allocs.find(ptr);
if(i == m_current_allocs.end())
- throw Exception("Compression_Alloc_Info::free got pointer not allocated by us");
+ throw Internal_Error("Compression_Alloc_Info::free got pointer not allocated by us");
secure_scrub_memory(ptr, i->second);
std::free(ptr);
@@ -190,7 +190,7 @@ void Stream_Decompression::finish(secure_vector<uint8_t>& buf, size_t offset)
process(buf, offset, m_stream->finish_flag());
if(m_stream.get())
- throw Exception(name() + " finished but not at stream end");
+ throw Invalid_State(name() + " finished but not at stream end");
}
}
diff --git a/src/lib/compression/compression.h b/src/lib/compression/compression.h
index f331874cf..1365894e2 100644
--- a/src/lib/compression/compression.h
+++ b/src/lib/compression/compression.h
@@ -9,11 +9,12 @@
#define BOTAN_COMPRESSION_TRANSFORM_H_
#include <botan/secmem.h>
+#include <botan/exceptn.h>
#include <string>
namespace Botan {
-/*
+/**
* Interface for a compression algorithm.
*/
class BOTAN_PUBLIC_API(2,0) Compression_Algorithm
@@ -134,6 +135,35 @@ BOTAN_PUBLIC_API(2,0) Compression_Algorithm* make_compressor(const std::string&
BOTAN_PUBLIC_API(2,0) Decompression_Algorithm* make_decompressor(const std::string& type);
/**
+* An error that occurred during compression (or decompression)
+*/
+class BOTAN_PUBLIC_API(2,9) Compression_Error : public Exception
+ {
+ public:
+
+ /**
+ * @param func_name the name of the compression API that was called
+ * (eg "BZ2_bzCompressInit" or "lzma_code")
+ * @param rc the error return code from the compression API. The
+ * interpretation of this value will depend on the library.
+ */
+ Compression_Error(const char* func_name, ErrorType type, int rc) :
+ Exception("Compression API " + std::string(func_name) +
+ " failed with return code " + std::to_string(rc)),
+ m_type(type),
+ m_rc(rc)
+ {}
+
+ ErrorType error_type() const noexcept override { return m_type; }
+
+ int error_code() const noexcept override { return m_rc; }
+
+ private:
+ ErrorType m_type;
+ int m_rc;
+ };
+
+/**
* Adapts a zlib style API
*/
class Compression_Stream
diff --git a/src/lib/compression/lzma/lzma.cpp b/src/lib/compression/lzma/lzma.cpp
index 92c61840a..73bb9eb89 100644
--- a/src/lib/compression/lzma/lzma.cpp
+++ b/src/lib/compression/lzma/lzma.cpp
@@ -37,10 +37,8 @@ class LZMA_Stream : public Zlib_Style_Stream<lzma_stream, uint8_t>
{
lzma_ret rc = ::lzma_code(streamp(), static_cast<lzma_action>(flags));
- if(rc == LZMA_MEM_ERROR)
- throw Exception("lzma memory allocation failed");
- else if (rc != LZMA_OK && rc != LZMA_STREAM_END)
- throw Exception("Lzma error");
+ if(rc != LZMA_OK && rc != LZMA_STREAM_END)
+ throw Compression_Error("lzma_code", ErrorType::LzmaError, rc);
return (rc == LZMA_STREAM_END);
}
@@ -64,10 +62,8 @@ class LZMA_Compression_Stream final : public LZMA_Stream
lzma_ret rc = ::lzma_easy_encoder(streamp(), level, LZMA_CHECK_CRC64);
- if(rc == LZMA_MEM_ERROR)
- throw Exception("lzma memory allocation failed");
- else if(rc != LZMA_OK)
- throw Exception("lzma compress initialization failed");
+ if(rc != LZMA_OK)
+ throw Compression_Error("lzam_easy_encoder", ErrorType::LzmaError, rc);
}
};
@@ -79,10 +75,8 @@ class LZMA_Decompression_Stream final : public LZMA_Stream
lzma_ret rc = ::lzma_stream_decoder(streamp(), UINT64_MAX,
LZMA_TELL_UNSUPPORTED_CHECK);
- if(rc == LZMA_MEM_ERROR)
- throw Exception("lzma memory allocation failed");
- else if(rc != LZMA_OK)
- throw Exception("Bad setting in lzma_stream_decoder");
+ if(rc != LZMA_OK)
+ throw Compression_Error("lzma_stream_decoder", ErrorType::LzmaError, rc);
}
};
diff --git a/src/lib/compression/zlib/zlib.cpp b/src/lib/compression/zlib/zlib.cpp
index 57494e225..285bc4e91 100644
--- a/src/lib/compression/zlib/zlib.cpp
+++ b/src/lib/compression/zlib/zlib.cpp
@@ -54,7 +54,7 @@ class Zlib_Compression_Stream : public Zlib_Stream
int rc = ::deflateInit2(streamp(), level, Z_DEFLATED, wbits, 8, Z_DEFAULT_STRATEGY);
if(rc != Z_OK)
- throw Exception("zlib deflate initialization failed");
+ throw Compression_Error("deflateInit2", ErrorType::ZlibError, rc);
}
~Zlib_Compression_Stream()
@@ -66,10 +66,8 @@ class Zlib_Compression_Stream : public Zlib_Stream
{
int rc = ::deflate(streamp(), flags);
- if(rc == Z_MEM_ERROR)
- throw Exception("zlib memory allocation failure");
- else if(rc != Z_OK && rc != Z_STREAM_END && rc != Z_BUF_ERROR)
- throw Exception("zlib deflate error " + std::to_string(rc));
+ if(rc != Z_OK && rc != Z_STREAM_END && rc != Z_BUF_ERROR)
+ throw Compression_Error("zlib deflate", ErrorType::ZlibError, rc);
return (rc == Z_STREAM_END);
}
@@ -82,10 +80,8 @@ class Zlib_Decompression_Stream : public Zlib_Stream
{
int rc = ::inflateInit2(streamp(), compute_window_bits(wbits, wbits_offset));
- if(rc == Z_MEM_ERROR)
- throw Exception("zlib memory allocation failure");
- else if(rc != Z_OK)
- throw Exception("zlib inflate initialization failed");
+ if(rc != Z_OK)
+ throw Compression_Error("inflateInit2", ErrorType::ZlibError, rc);
}
~Zlib_Decompression_Stream()
@@ -97,10 +93,8 @@ class Zlib_Decompression_Stream : public Zlib_Stream
{
int rc = ::inflate(streamp(), flags);
- if(rc == Z_MEM_ERROR)
- throw Exception("zlib memory allocation failure");
- else if(rc != Z_OK && rc != Z_STREAM_END && rc != Z_BUF_ERROR)
- throw Exception("zlib inflate error " + std::to_string(rc));
+ if(rc != Z_OK && rc != Z_STREAM_END && rc != Z_BUF_ERROR)
+ throw Compression_Error("zlib inflate", ErrorType::ZlibError, rc);
return (rc == Z_STREAM_END);
}
@@ -131,7 +125,7 @@ class Gzip_Compression_Stream final : public Zlib_Compression_Stream
int rc = deflateSetHeader(streamp(), &m_header);
if(rc != Z_OK)
- throw Exception("setting gzip header failed");
+ throw Compression_Error("deflateSetHeader", ErrorType::ZlibError, rc);
}
private:
diff --git a/src/lib/entropy/dev_random/dev_random.cpp b/src/lib/entropy/dev_random/dev_random.cpp
index 56552228a..44fcbace3 100644
--- a/src/lib/entropy/dev_random/dev_random.cpp
+++ b/src/lib/entropy/dev_random/dev_random.cpp
@@ -47,15 +47,14 @@ Device_EntropySource::Device_EntropySource(const std::vector<std::string>& fsnam
either a bug in the application or file descriptor exhaustion.
*/
if(errno != ENOENT && errno != EACCES)
- throw Exception("Opening OS RNG device failed with errno " +
- std::to_string(errno));
+ throw System_Error("Opening OS RNG device failed", errno);
}
else
{
if(fd > FD_SETSIZE)
{
::close(fd);
- throw Exception("Open of OS RNG succeeded but fd is too large for fd_set");
+ throw Invalid_State("Open of OS RNG succeeded but returned fd is too large for fd_set");
}
m_dev_fds.push_back(fd);
diff --git a/src/lib/ffi/ffi.cpp b/src/lib/ffi/ffi.cpp
index 74291199b..cfc2cb2d5 100644
--- a/src/lib/ffi/ffi.cpp
+++ b/src/lib/ffi/ffi.cpp
@@ -25,6 +25,59 @@ int ffi_error_exception_thrown(const char* func_name, const char* exn, int rc)
return rc;
}
+namespace {
+
+int ffi_map_error_type(Botan::ErrorType err)
+ {
+ switch(err)
+ {
+ case Botan::ErrorType::Unknown:
+ return BOTAN_FFI_ERROR_UNKNOWN_ERROR;
+ case Botan::ErrorType::SystemError:
+ case Botan::ErrorType::IoError:
+ case Botan::ErrorType::OpenSSLError:
+ case Botan::ErrorType::Pkcs11Error:
+ case Botan::ErrorType::CommonCryptoError:
+ case Botan::ErrorType::TPMError:
+ case Botan::ErrorType::ZlibError:
+ case Botan::ErrorType::Bzip2Error:
+ case Botan::ErrorType::LzmaError:
+ return BOTAN_FFI_ERROR_SYSTEM_ERROR;
+
+ case Botan::ErrorType::NotImplemented:
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+ case Botan::ErrorType::OutOfMemory:
+ return BOTAN_FFI_ERROR_OUT_OF_MEMORY;
+ case Botan::ErrorType::InternalError:
+ return BOTAN_FFI_ERROR_INTERNAL_ERROR;
+ case Botan::ErrorType::InvalidObjectState:
+ return BOTAN_FFI_ERROR_INVALID_OBJECT_STATE;
+ case Botan::ErrorType::KeyNotSet:
+ return BOTAN_FFI_ERROR_KEY_NOT_SET;
+ case Botan::ErrorType::InvalidArgument:
+ case Botan::ErrorType::InvalidNonceLength:
+ return BOTAN_FFI_ERROR_BAD_PARAMETER;
+
+ case Botan::ErrorType::EncodingFailure:
+ case Botan::ErrorType::DecodingFailure:
+ return BOTAN_FFI_ERROR_INVALID_INPUT;
+
+ case Botan::ErrorType::InvalidKeyLength:
+ return BOTAN_FFI_ERROR_INVALID_KEY_LENGTH;
+ case Botan::ErrorType::LookupError:
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+
+ case Botan::ErrorType::HttpError:
+ return BOTAN_FFI_ERROR_HTTP_ERROR;
+ case Botan::ErrorType::TLSError:
+ return BOTAN_FFI_ERROR_TLS_ERROR;
+ }
+
+ return BOTAN_FFI_ERROR_UNKNOWN_ERROR;
+ }
+
+}
+
int ffi_guard_thunk(const char* func_name, std::function<int ()> thunk)
{
try
@@ -39,25 +92,9 @@ int ffi_guard_thunk(const char* func_name, std::function<int ()> thunk)
{
return ffi_error_exception_thrown(func_name, e.what(), e.error_code());
}
- catch(Botan::Lookup_Error& e)
- {
- return ffi_error_exception_thrown(func_name, e.what(), BOTAN_FFI_ERROR_NOT_IMPLEMENTED);
- }
- catch(Botan::Invalid_Key_Length& e)
- {
- return ffi_error_exception_thrown(func_name, e.what(), BOTAN_FFI_ERROR_INVALID_KEY_LENGTH);
- }
- catch(Botan::Key_Not_Set& e)
- {
- return ffi_error_exception_thrown(func_name, e.what(), BOTAN_FFI_ERROR_KEY_NOT_SET);
- }
- catch(Botan::Invalid_Argument& e)
- {
- return ffi_error_exception_thrown(func_name, e.what(), BOTAN_FFI_ERROR_BAD_PARAMETER);
- }
- catch(Botan::Not_Implemented& e)
+ catch(Botan::Exception& e)
{
- return ffi_error_exception_thrown(func_name, e.what(), BOTAN_FFI_ERROR_NOT_IMPLEMENTED);
+ return ffi_error_exception_thrown(func_name, e.what(), ffi_map_error_type(e.error_type()));
}
catch(std::exception& e)
{
@@ -102,6 +139,12 @@ const char* botan_error_description(int err)
case BOTAN_FFI_ERROR_OUT_OF_MEMORY:
return "Out of memory";
+ case BOTAN_FFI_ERROR_SYSTEM_ERROR:
+ return "Error while calling system API";
+
+ case BOTAN_FFI_ERROR_INTERNAL_ERROR:
+ return "Internal error";
+
case BOTAN_FFI_ERROR_BAD_FLAG:
return "Bad flag";
@@ -117,12 +160,21 @@ const char* botan_error_description(int err)
case BOTAN_FFI_ERROR_INVALID_KEY_LENGTH:
return "Invalid key length";
+ case BOTAN_FFI_ERROR_INVALID_OBJECT_STATE:
+ return "Invalid object state";
+
case BOTAN_FFI_ERROR_NOT_IMPLEMENTED:
return "Not implemented";
case BOTAN_FFI_ERROR_INVALID_OBJECT:
return "Invalid object handle";
+ case BOTAN_FFI_ERROR_TLS_ERROR:
+ return "TLS error";
+
+ case BOTAN_FFI_ERROR_HTTP_ERROR:
+ return "HTTP error";
+
case BOTAN_FFI_ERROR_UNKNOWN_ERROR:
return "Unknown error";
}
diff --git a/src/lib/ffi/ffi.h b/src/lib/ffi/ffi.h
index fbc396d12..c3712bd97 100644
--- a/src/lib/ffi/ffi.h
+++ b/src/lib/ffi/ffi.h
@@ -54,6 +54,9 @@ API follows a few simple rules:
/**
* Error codes
+*
+* If you add a new value here be sure to also add it in
+* botan_error_description
*/
enum BOTAN_FFI_ERROR {
BOTAN_FFI_SUCCESS = 0,
@@ -63,16 +66,25 @@ enum BOTAN_FFI_ERROR {
BOTAN_FFI_ERROR_BAD_MAC = -2,
BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE = -10,
+
BOTAN_FFI_ERROR_EXCEPTION_THROWN = -20,
BOTAN_FFI_ERROR_OUT_OF_MEMORY = -21,
+ BOTAN_FFI_ERROR_SYSTEM_ERROR = -22,
+ BOTAN_FFI_ERROR_INTERNAL_ERROR = -23,
+
BOTAN_FFI_ERROR_BAD_FLAG = -30,
BOTAN_FFI_ERROR_NULL_POINTER = -31,
BOTAN_FFI_ERROR_BAD_PARAMETER = -32,
BOTAN_FFI_ERROR_KEY_NOT_SET = -33,
BOTAN_FFI_ERROR_INVALID_KEY_LENGTH = -34,
+ BOTAN_FFI_ERROR_INVALID_OBJECT_STATE = -35,
+
BOTAN_FFI_ERROR_NOT_IMPLEMENTED = -40,
BOTAN_FFI_ERROR_INVALID_OBJECT = -50,
+ BOTAN_FFI_ERROR_TLS_ERROR = -75,
+ BOTAN_FFI_ERROR_HTTP_ERROR = -76,
+
BOTAN_FFI_ERROR_UNKNOWN_ERROR = -100,
};
diff --git a/src/lib/ffi/ffi_util.h b/src/lib/ffi/ffi_util.h
index d68baf699..2962b05e1 100644
--- a/src/lib/ffi/ffi_util.h
+++ b/src/lib/ffi/ffi_util.h
@@ -24,7 +24,9 @@ class BOTAN_UNSTABLE_API FFI_Error final : public Botan::Exception
m_err_code(err_code)
{}
- int error_code() const { return m_err_code; }
+ int error_code() const noexcept override { return m_err_code; }
+
+ Botan::ErrorType error_type() const noexcept override { return Botan::ErrorType::InvalidArgument; }
private:
int m_err_code;
diff --git a/src/lib/filters/buf_filt.cpp b/src/lib/filters/buf_filt.cpp
index 8acc6c74f..11ca9bbfe 100644
--- a/src/lib/filters/buf_filt.cpp
+++ b/src/lib/filters/buf_filt.cpp
@@ -82,7 +82,7 @@ void Buffered_Filter::write(const uint8_t input[], size_t input_size)
void Buffered_Filter::end_msg()
{
if(m_buffer_pos < m_final_minimum)
- throw Exception("Buffered filter end_msg without enough input");
+ throw Invalid_State("Buffered filter end_msg without enough input");
size_t spare_blocks = (m_buffer_pos - m_final_minimum) / m_main_block_mod;
diff --git a/src/lib/math/bigint/big_io.cpp b/src/lib/math/bigint/big_io.cpp
index 803e1cc4a..90c2253e9 100644
--- a/src/lib/math/bigint/big_io.cpp
+++ b/src/lib/math/bigint/big_io.cpp
@@ -20,7 +20,7 @@ std::ostream& operator<<(std::ostream& stream, const BigInt& n)
if(stream.flags() & std::ios::hex)
base = BigInt::Hexadecimal;
else if(stream.flags() & std::ios::oct)
- throw Exception("Octal output of BigInt not supported");
+ throw Invalid_Argument("Octal output of BigInt not supported");
if(n == 0)
stream.write("0", 1);
diff --git a/src/lib/math/bigint/bigint.h b/src/lib/math/bigint/bigint.h
index bd63425fd..64e408798 100644
--- a/src/lib/math/bigint/bigint.h
+++ b/src/lib/math/bigint/bigint.h
@@ -37,11 +37,14 @@ class BOTAN_PUBLIC_API(2,0) BigInt final
/**
* DivideByZero Exception
+ *
+ * In a future release this exception will be removed and its usage
+ * replaced by Invalid_Argument
*/
- class BOTAN_PUBLIC_API(2,0) DivideByZero final : public Exception
+ class BOTAN_PUBLIC_API(2,0) DivideByZero final : public Invalid_Argument
{
public:
- DivideByZero() : Exception("BigInt divide by zero") {}
+ DivideByZero() : Invalid_Argument("BigInt divide by zero") {}
};
/**
diff --git a/src/lib/math/numbertheory/numthry.cpp b/src/lib/math/numbertheory/numthry.cpp
index bb86f5ce0..a8dfe8eaf 100644
--- a/src/lib/math/numbertheory/numthry.cpp
+++ b/src/lib/math/numbertheory/numthry.cpp
@@ -351,7 +351,7 @@ BigInt inverse_euclid(const BigInt& n, const BigInt& mod)
word monty_inverse(word input)
{
if(input == 0)
- throw Exception("monty_inverse: divide by zero");
+ throw Invalid_Argument("monty_inverse: divide by zero");
word b = input;
word x2 = 1, x1 = 0, y2 = 0, y1 = 1;
diff --git a/src/lib/misc/fpe_fe1/fpe_fe1.cpp b/src/lib/misc/fpe_fe1/fpe_fe1.cpp
index 680967ea9..3bd01ce34 100644
--- a/src/lib/misc/fpe_fe1/fpe_fe1.cpp
+++ b/src/lib/misc/fpe_fe1/fpe_fe1.cpp
@@ -50,7 +50,7 @@ void factor(BigInt n, BigInt& a, BigInt& b)
a *= n;
if(a <= 1 || b <= 1)
- throw Exception("Could not factor n for use in FPE");
+ throw Internal_Error("Could not factor n for use in FPE");
}
}
@@ -69,7 +69,7 @@ FPE_FE1::FPE_FE1(const BigInt& n,
m_n_bytes = BigInt::encode(n);
if(m_n_bytes.size() > MAX_N_BYTES)
- throw Exception("N is too large for FPE encryption");
+ throw Invalid_Argument("N is too large for FPE encryption");
factor(n, m_a, m_b);
diff --git a/src/lib/misc/srp6/srp6.cpp b/src/lib/misc/srp6/srp6.cpp
index cb7e3c600..0ec4fd2bb 100644
--- a/src/lib/misc/srp6/srp6.cpp
+++ b/src/lib/misc/srp6/srp6.cpp
@@ -64,13 +64,13 @@ std::string srp6_group_identifier(const BigInt& N, const BigInt& g)
if(group.get_p() == N && group.get_g() == g)
return group_name;
-
- throw Exception("Unknown SRP params");
}
catch(...)
{
- throw Invalid_Argument("Bad SRP group parameters");
}
+
+ // If we didn't return, the group was unknown or did not match
+ throw Invalid_Argument("Invalid or unknown SRP group parameters");
}
std::pair<BigInt, SymmetricKey>
@@ -91,7 +91,7 @@ srp6_client_agree(const std::string& identifier,
const size_t p_bytes = group.p_bytes();
if(B <= 0 || B >= p)
- throw Exception("Invalid SRP parameter from server");
+ throw Decoding_Error("Invalid SRP parameter from server");
const BigInt k = hash_seq(hash_id, p_bytes, p, g);
@@ -150,7 +150,7 @@ BigInt SRP6_Server_Session::step1(const BigInt& v,
SymmetricKey SRP6_Server_Session::step2(const BigInt& A)
{
if(A <= 0 || A >= m_p)
- throw Exception("Invalid SRP parameter from client");
+ throw Decoding_Error("Invalid SRP parameter from client");
const BigInt u = hash_seq(m_hash_id, m_p_bytes, A, m_B);
diff --git a/src/lib/modes/aead/gcm/gcm.cpp b/src/lib/modes/aead/gcm/gcm.cpp
index 457c4831f..75768d851 100644
--- a/src/lib/modes/aead/gcm/gcm.cpp
+++ b/src/lib/modes/aead/gcm/gcm.cpp
@@ -150,7 +150,7 @@ void GCM_Decryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
uint8_t* buf = buffer.data() + offset;
if(sz < tag_size())
- throw Exception("Insufficient input for GCM decryption, tag missing");
+ throw Decoding_Error("Insufficient input for GCM decryption, tag missing");
const size_t remaining = sz - tag_size();
diff --git a/src/lib/modes/cbc/cbc.cpp b/src/lib/modes/cbc/cbc.cpp
index aa73eb884..a4af7f0bf 100644
--- a/src/lib/modes/cbc/cbc.cpp
+++ b/src/lib/modes/cbc/cbc.cpp
@@ -136,7 +136,7 @@ void CBC_Encryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
padding().add_padding(buffer, bytes_in_final_block, BS);
if((buffer.size()-offset) % BS)
- throw Exception("Did not pad to full block size in " + name());
+ throw Internal_Error("Did not pad to full block size in " + name());
update(buffer, offset);
}
diff --git a/src/lib/pbkdf/pbkdf2/pbkdf2.cpp b/src/lib/pbkdf/pbkdf2/pbkdf2.cpp
index 6fc007bf3..9d0be3a58 100644
--- a/src/lib/pbkdf/pbkdf2/pbkdf2.cpp
+++ b/src/lib/pbkdf/pbkdf2/pbkdf2.cpp
@@ -25,7 +25,7 @@ void pbkdf2_set_key(MessageAuthenticationCode& prf,
}
catch(Invalid_Key_Length&)
{
- throw Exception("PBKDF2 cannot accept passphrase of the given size");
+ throw Invalid_Argument("PBKDF2 cannot accept passphrase of the given size");
}
}
diff --git a/src/lib/pbkdf/scrypt/scrypt.cpp b/src/lib/pbkdf/scrypt/scrypt.cpp
index 826438926..c20225734 100644
--- a/src/lib/pbkdf/scrypt/scrypt.cpp
+++ b/src/lib/pbkdf/scrypt/scrypt.cpp
@@ -226,7 +226,7 @@ void scrypt(uint8_t output[], size_t output_len,
}
catch(Invalid_Key_Length&)
{
- throw Exception("Scrypt cannot accept passphrases of the provided length");
+ throw Invalid_Argument("Scrypt cannot accept passphrases of the provided length");
}
pbkdf2(*hmac_sha256.get(),
diff --git a/src/lib/prov/commoncrypto/commoncrypto.h b/src/lib/prov/commoncrypto/commoncrypto.h
index 958cbab7d..31fa110fc 100644
--- a/src/lib/prov/commoncrypto/commoncrypto.h
+++ b/src/lib/prov/commoncrypto/commoncrypto.h
@@ -24,14 +24,23 @@ typedef int32_t CCCryptorStatus;
class BOTAN_PUBLIC_API(2, 0) CommonCrypto_Error final : public Exception
{
- std::string ccryptorstatus_to_string(CCCryptorStatus status);
-
public:
CommonCrypto_Error(const std::string& what) :
- Exception(what + " failed.") {}
+ Exception(what + " failed."),
+ m_rc(0) {}
CommonCrypto_Error(const std::string& what, int32_t status) :
- Exception(what + std::string(" failed. Status: ") + ccryptorstatus_to_string(status)) {}
+ Exception(what + std::string(" failed. Status: ") + ccryptorstatus_to_string(status)),
+ m_rc(status) {}
+
+ ErrorType error_type() const noexcept override { return ErrorType::CommonCryptoError; }
+
+ int error_code() const noexcept override { return m_rc; }
+
+ private:
+ std::string ccryptorstatus_to_string(CCCryptorStatus status);
+
+ int32_t m_rc;
};
/* Cipher Modes */
diff --git a/src/lib/prov/openssl/openssl.h b/src/lib/prov/openssl/openssl.h
index 3db7b39af..a68dda5af 100644
--- a/src/lib/prov/openssl/openssl.h
+++ b/src/lib/prov/openssl/openssl.h
@@ -33,11 +33,16 @@ enum Cipher_Dir : int;
class BOTAN_PUBLIC_API(2,0) OpenSSL_Error final : public Exception
{
public:
- OpenSSL_Error(const std::string& what) :
- Exception(what + " failed: " + ERR_error_string(ERR_get_error(), nullptr)) {}
-
OpenSSL_Error(const std::string& what, int err) :
- Exception(what + " failed: " + ERR_error_string(err, nullptr)) {}
+ Exception(what + " failed: " + ERR_error_string(err, nullptr)),
+ m_err(err) {}
+
+ ErrorType error_type() const noexcept override { return ErrorType::OpenSSLError; }
+
+ int error_code() const noexcept override { return m_err; }
+
+ private:
+ int m_err;
};
/* Block Ciphers */
diff --git a/src/lib/prov/openssl/openssl_block.cpp b/src/lib/prov/openssl/openssl_block.cpp
index d785c3c8d..fdded7285 100644
--- a/src/lib/prov/openssl/openssl_block.cpp
+++ b/src/lib/prov/openssl/openssl_block.cpp
@@ -39,7 +39,7 @@ class OpenSSL_BlockCipher final : public BlockCipher
verify_key_set(m_key_set);
int out_len = 0;
if(!EVP_EncryptUpdate(m_encrypt, out, &out_len, in, blocks * m_block_sz))
- throw OpenSSL_Error("EVP_EncryptUpdate");
+ throw OpenSSL_Error("EVP_EncryptUpdate", ERR_get_error());
}
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
@@ -47,7 +47,7 @@ class OpenSSL_BlockCipher final : public BlockCipher
verify_key_set(m_key_set);
int out_len = 0;
if(!EVP_DecryptUpdate(m_decrypt, out, &out_len, in, blocks * m_block_sz))
- throw OpenSSL_Error("EVP_DecryptUpdate");
+ throw OpenSSL_Error("EVP_DecryptUpdate", ERR_get_error());
}
void key_schedule(const uint8_t key[], size_t key_len) override;
@@ -73,20 +73,20 @@ OpenSSL_BlockCipher::OpenSSL_BlockCipher(const std::string& algo_name,
m_encrypt = EVP_CIPHER_CTX_new();
m_decrypt = EVP_CIPHER_CTX_new();
if (m_encrypt == nullptr || m_decrypt == nullptr)
- throw OpenSSL_Error("Can't allocate new context");
+ throw OpenSSL_Error("Can't allocate new context", ERR_get_error());
EVP_CIPHER_CTX_init(m_encrypt);
EVP_CIPHER_CTX_init(m_decrypt);
if(!EVP_EncryptInit_ex(m_encrypt, algo, nullptr, nullptr, nullptr))
- throw OpenSSL_Error("EVP_EncryptInit_ex");
+ throw OpenSSL_Error("EVP_EncryptInit_ex", ERR_get_error());
if(!EVP_DecryptInit_ex(m_decrypt, algo, nullptr, nullptr, nullptr))
- throw OpenSSL_Error("EVP_DecryptInit_ex");
+ throw OpenSSL_Error("EVP_DecryptInit_ex", ERR_get_error());
if(!EVP_CIPHER_CTX_set_padding(m_encrypt, 0))
- throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding encrypt");
+ throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding encrypt", ERR_get_error());
if(!EVP_CIPHER_CTX_set_padding(m_decrypt, 0))
- throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding decrypt");
+ throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding decrypt", ERR_get_error());
}
OpenSSL_BlockCipher::OpenSSL_BlockCipher(const std::string& algo_name,
@@ -105,20 +105,20 @@ OpenSSL_BlockCipher::OpenSSL_BlockCipher(const std::string& algo_name,
m_encrypt = EVP_CIPHER_CTX_new();
m_decrypt = EVP_CIPHER_CTX_new();
if (m_encrypt == nullptr || m_decrypt == nullptr)
- throw OpenSSL_Error("Can't allocate new context");
+ throw OpenSSL_Error("Can't allocate new context", ERR_get_error());
EVP_CIPHER_CTX_init(m_encrypt);
EVP_CIPHER_CTX_init(m_decrypt);
if(!EVP_EncryptInit_ex(m_encrypt, algo, nullptr, nullptr, nullptr))
- throw OpenSSL_Error("EVP_EncryptInit_ex");
+ throw OpenSSL_Error("EVP_EncryptInit_ex", ERR_get_error());
if(!EVP_DecryptInit_ex(m_decrypt, algo, nullptr, nullptr, nullptr))
- throw OpenSSL_Error("EVP_DecryptInit_ex");
+ throw OpenSSL_Error("EVP_DecryptInit_ex", ERR_get_error());
if(!EVP_CIPHER_CTX_set_padding(m_encrypt, 0))
- throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding encrypt");
+ throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding encrypt", ERR_get_error());
if(!EVP_CIPHER_CTX_set_padding(m_decrypt, 0))
- throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding decrypt");
+ throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding decrypt", ERR_get_error());
}
OpenSSL_BlockCipher::~OpenSSL_BlockCipher()
@@ -150,9 +150,9 @@ void OpenSSL_BlockCipher::key_schedule(const uint8_t key[], size_t length)
}
if(!EVP_EncryptInit_ex(m_encrypt, nullptr, nullptr, full_key.data(), nullptr))
- throw OpenSSL_Error("EVP_EncryptInit_ex");
+ throw OpenSSL_Error("EVP_EncryptInit_ex", ERR_get_error());
if(!EVP_DecryptInit_ex(m_decrypt, nullptr, nullptr, full_key.data(), nullptr))
- throw OpenSSL_Error("EVP_DecryptInit_ex");
+ throw OpenSSL_Error("EVP_DecryptInit_ex", ERR_get_error());
m_key_set = true;
}
@@ -179,19 +179,19 @@ void OpenSSL_BlockCipher::clear()
m_key_set = false;
if(!EVP_CIPHER_CTX_cleanup(m_encrypt))
- throw OpenSSL_Error("EVP_CIPHER_CTX_cleanup encrypt");
+ throw OpenSSL_Error("EVP_CIPHER_CTX_cleanup encrypt", ERR_get_error());
if(!EVP_CIPHER_CTX_cleanup(m_decrypt))
- throw OpenSSL_Error("EVP_CIPHER_CTX_cleanup decrypt");
+ throw OpenSSL_Error("EVP_CIPHER_CTX_cleanup decrypt", ERR_get_error());
EVP_CIPHER_CTX_init(m_encrypt);
EVP_CIPHER_CTX_init(m_decrypt);
if(!EVP_EncryptInit_ex(m_encrypt, algo, nullptr, nullptr, nullptr))
- throw OpenSSL_Error("EVP_EncryptInit_ex");
+ throw OpenSSL_Error("EVP_EncryptInit_ex", ERR_get_error());
if(!EVP_DecryptInit_ex(m_decrypt, algo, nullptr, nullptr, nullptr))
- throw OpenSSL_Error("EVP_DecryptInit_ex");
+ throw OpenSSL_Error("EVP_DecryptInit_ex", ERR_get_error());
if(!EVP_CIPHER_CTX_set_padding(m_encrypt, 0))
- throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding encrypt");
+ throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding encrypt", ERR_get_error());
if(!EVP_CIPHER_CTX_set_padding(m_decrypt, 0))
- throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding decrypt");
+ throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding decrypt", ERR_get_error());
}
}
diff --git a/src/lib/prov/openssl/openssl_ec.cpp b/src/lib/prov/openssl/openssl_ec.cpp
index e044d552a..026dfa5e0 100644
--- a/src/lib/prov/openssl/openssl_ec.cpp
+++ b/src/lib/prov/openssl/openssl_ec.cpp
@@ -142,16 +142,16 @@ class OpenSSL_ECDSA_Verification_Operation final : public PK_Ops::Verification_w
::EC_GROUP_free);
if(!grp)
- throw OpenSSL_Error("EC_GROUP_new_by_curve_name");
+ throw OpenSSL_Error("EC_GROUP_new_by_curve_name", ERR_get_error());
if(!::EC_KEY_set_group(m_ossl_ec.get(), grp.get()))
- throw OpenSSL_Error("EC_KEY_set_group");
+ throw OpenSSL_Error("EC_KEY_set_group", ERR_get_error());
const std::vector<uint8_t> enc = ecdsa.public_point().encode(PointGFp::UNCOMPRESSED);
const uint8_t* enc_ptr = enc.data();
EC_KEY* key_ptr = m_ossl_ec.get();
if(!::o2i_ECPublicKey(&key_ptr, &enc_ptr, enc.size()))
- throw OpenSSL_Error("o2i_ECPublicKey");
+ throw OpenSSL_Error("o2i_ECPublicKey", ERR_get_error());
const EC_GROUP* group = ::EC_KEY_get0_group(m_ossl_ec.get());
m_order_bits = ::EC_GROUP_get_degree(group);
@@ -178,7 +178,7 @@ class OpenSSL_ECDSA_Verification_Operation final : public PK_Ops::Verification_w
BIGNUM* r = BN_bin2bn(sig_bytes , sig_len / 2, nullptr);
BIGNUM* s = BN_bin2bn(sig_bytes + sig_len / 2, sig_len / 2, nullptr);
if(r == nullptr || s == nullptr)
- throw OpenSSL_Error("BN_bin2bn sig s");
+ throw OpenSSL_Error("BN_bin2bn sig s", ERR_get_error());
ECDSA_SIG_set0(sig.get(), r, s);
#endif
@@ -225,7 +225,7 @@ class OpenSSL_ECDSA_Signing_Operation final : public PK_Ops::Signature_with_EMSA
const uint8_t* der_ptr = der.data();
m_ossl_ec.reset(d2i_ECPrivateKey(nullptr, &der_ptr, der.size()));
if(!m_ossl_ec)
- throw OpenSSL_Error("d2i_ECPrivateKey");
+ throw OpenSSL_Error("d2i_ECPrivateKey", ERR_get_error());
const EC_GROUP* group = ::EC_KEY_get0_group(m_ossl_ec.get());
m_order_bits = ::EC_GROUP_get_degree(group);
@@ -241,7 +241,7 @@ class OpenSSL_ECDSA_Signing_Operation final : public PK_Ops::Signature_with_EMSA
sig.reset(::ECDSA_do_sign(msg, msg_len, m_ossl_ec.get()));
if(!sig)
- throw OpenSSL_Error("ECDSA_do_sign");
+ throw OpenSSL_Error("ECDSA_do_sign", ERR_get_error());
#if OPENSSL_VERSION_NUMBER < 0x10100000L
const BIGNUM* r = sig->r;
@@ -318,7 +318,7 @@ class OpenSSL_ECDH_KA_Operation final : public PK_Ops::Key_Agreement_with_KDF
const uint8_t* der_ptr = der.data();
m_ossl_ec.reset(d2i_ECPrivateKey(nullptr, &der_ptr, der.size()));
if(!m_ossl_ec)
- throw OpenSSL_Error("d2i_ECPrivateKey");
+ throw OpenSSL_Error("d2i_ECPrivateKey", ERR_get_error());
}
size_t agreed_value_size() const override { return m_value_size; }
@@ -331,13 +331,13 @@ class OpenSSL_ECDH_KA_Operation final : public PK_Ops::Key_Agreement_with_KDF
EC_POINT* pub_key = ::EC_POINT_new(group);
if(!pub_key)
- throw OpenSSL_Error("EC_POINT_new");
+ throw OpenSSL_Error("EC_POINT_new", ERR_get_error());
const int os2ecp_rc =
::EC_POINT_oct2point(group, pub_key, w, w_len, nullptr);
if(os2ecp_rc != 1)
- throw OpenSSL_Error("EC_POINT_oct2point");
+ throw OpenSSL_Error("EC_POINT_oct2point", ERR_get_error());
const int ecdh_rc = ::ECDH_compute_key(out.data(),
out.size(),
@@ -346,7 +346,7 @@ class OpenSSL_ECDH_KA_Operation final : public PK_Ops::Key_Agreement_with_KDF
/*KDF*/nullptr);
if(ecdh_rc <= 0)
- throw OpenSSL_Error("ECDH_compute_key");
+ throw OpenSSL_Error("ECDH_compute_key", ERR_get_error());
const size_t ecdh_sz = static_cast<size_t>(ecdh_rc);
diff --git a/src/lib/prov/openssl/openssl_hash.cpp b/src/lib/prov/openssl/openssl_hash.cpp
index 1f4da0484..4eaca12b4 100644
--- a/src/lib/prov/openssl/openssl_hash.cpp
+++ b/src/lib/prov/openssl/openssl_hash.cpp
@@ -21,7 +21,7 @@ class OpenSSL_HashFunction final : public HashFunction
{
const EVP_MD* algo = EVP_MD_CTX_md(m_md);
if(!EVP_DigestInit_ex(m_md, algo, nullptr))
- throw OpenSSL_Error("EVP_DigestInit_ex");
+ throw OpenSSL_Error("EVP_DigestInit_ex", ERR_get_error());
}
std::string provider() const override { return "openssl"; }
@@ -59,10 +59,10 @@ class OpenSSL_HashFunction final : public HashFunction
#endif
if(m_md == nullptr)
- throw OpenSSL_Error("Can't allocate new context");
+ throw OpenSSL_Error("Can't allocate new context", ERR_get_error());
EVP_MD_CTX_init(m_md);
if(md && !EVP_DigestInit_ex(m_md, md, nullptr))
- throw OpenSSL_Error("EVP_DigestInit_ex");
+ throw OpenSSL_Error("EVP_DigestInit_ex", ERR_get_error());
}
OpenSSL_HashFunction(EVP_MD_CTX* ctx) : m_md(ctx)
@@ -82,16 +82,16 @@ class OpenSSL_HashFunction final : public HashFunction
void add_data(const uint8_t input[], size_t length) override
{
if(!EVP_DigestUpdate(m_md, input, length))
- throw OpenSSL_Error("EVP_DigestUpdate");
+ throw OpenSSL_Error("EVP_DigestUpdate", ERR_get_error());
}
void final_result(uint8_t output[]) override
{
if(!EVP_DigestFinal_ex(m_md, output, nullptr))
- throw OpenSSL_Error("EVP_DigestFinal_ex");
+ throw OpenSSL_Error("EVP_DigestFinal_ex", ERR_get_error());
const EVP_MD* algo = EVP_MD_CTX_md(m_md);
if(!EVP_DigestInit_ex(m_md, algo, nullptr))
- throw OpenSSL_Error("EVP_DigestInit_ex");
+ throw OpenSSL_Error("EVP_DigestInit_ex", ERR_get_error());
}
std::string m_name;
diff --git a/src/lib/prov/openssl/openssl_mode.cpp b/src/lib/prov/openssl/openssl_mode.cpp
index d1983949d..81f8413a2 100644
--- a/src/lib/prov/openssl/openssl_mode.cpp
+++ b/src/lib/prov/openssl/openssl_mode.cpp
@@ -65,14 +65,14 @@ OpenSSL_Cipher_Mode::OpenSSL_Cipher_Mode(const std::string& name,
m_cipher = EVP_CIPHER_CTX_new();
if (m_cipher == nullptr)
- throw OpenSSL_Error("Can't allocate new context");
+ throw OpenSSL_Error("Can't allocate new context", ERR_get_error());
EVP_CIPHER_CTX_init(m_cipher);
if(!EVP_CipherInit_ex(m_cipher, algo, nullptr, nullptr, nullptr,
m_direction == ENCRYPTION ? 1 : 0))
- throw OpenSSL_Error("EVP_CipherInit_ex");
+ throw OpenSSL_Error("EVP_CipherInit_ex", ERR_get_error());
if(!EVP_CIPHER_CTX_set_padding(m_cipher, 0))
- throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding");
+ throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding", ERR_get_error());
}
OpenSSL_Cipher_Mode::~OpenSSL_Cipher_Mode()
@@ -90,13 +90,13 @@ void OpenSSL_Cipher_Mode::start_msg(const uint8_t nonce[], size_t nonce_len)
if(nonce_len)
{
if(!EVP_CipherInit_ex(m_cipher, nullptr, nullptr, nullptr, nonce, -1))
- throw OpenSSL_Error("EVP_CipherInit_ex nonce");
+ throw OpenSSL_Error("EVP_CipherInit_ex nonce", ERR_get_error());
}
else if(m_nonce_set == false)
{
const std::vector<uint8_t> zeros(m_block_size);
if(!EVP_CipherInit_ex(m_cipher, nullptr, nullptr, nullptr, zeros.data(), -1))
- throw OpenSSL_Error("EVP_CipherInit_ex nonce");
+ throw OpenSSL_Error("EVP_CipherInit_ex nonce", ERR_get_error());
}
// otherwise existing CBC state left unchanged
@@ -116,7 +116,7 @@ size_t OpenSSL_Cipher_Mode::process(uint8_t msg[], size_t msg_len)
secure_vector<uint8_t> out(outl);
if(!EVP_CipherUpdate(m_cipher, out.data(), &outl, msg, msg_len))
- throw OpenSSL_Error("EVP_CipherUpdate");
+ throw OpenSSL_Error("EVP_CipherUpdate", ERR_get_error());
copy_mem(msg, out.data(), outl);
return outl;
}
@@ -136,7 +136,7 @@ void OpenSSL_Cipher_Mode::finish(secure_vector<uint8_t>& buffer,
secure_vector<uint8_t> out(outl);
if(!EVP_CipherFinal_ex(m_cipher, out.data(), &outl))
- throw OpenSSL_Error("EVP_CipherFinal_ex");
+ throw OpenSSL_Error("EVP_CipherFinal_ex", ERR_get_error());
copy_mem(buf + written, out.data(), outl);
written += outl;
buffer.resize(offset + written);
@@ -178,19 +178,19 @@ void OpenSSL_Cipher_Mode::clear()
const EVP_CIPHER* algo = EVP_CIPHER_CTX_cipher(m_cipher);
if(!EVP_CIPHER_CTX_cleanup(m_cipher))
- throw OpenSSL_Error("EVP_CIPHER_CTX_cleanup");
+ throw OpenSSL_Error("EVP_CIPHER_CTX_cleanup", ERR_get_error());
EVP_CIPHER_CTX_init(m_cipher);
if(!EVP_CipherInit_ex(m_cipher, algo, nullptr, nullptr, nullptr,
m_direction == ENCRYPTION ? 1 : 0))
- throw OpenSSL_Error("EVP_CipherInit_ex clear");
+ throw OpenSSL_Error("EVP_CipherInit_ex clear", ERR_get_error());
if(!EVP_CIPHER_CTX_set_padding(m_cipher, 0))
- throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding clear");
+ throw OpenSSL_Error("EVP_CIPHER_CTX_set_padding clear", ERR_get_error());
}
void OpenSSL_Cipher_Mode::reset()
{
if(!EVP_CipherInit_ex(m_cipher, nullptr, nullptr, nullptr, nullptr, -1))
- throw OpenSSL_Error("EVP_CipherInit_ex clear");
+ throw OpenSSL_Error("EVP_CipherInit_ex clear", ERR_get_error());
m_nonce_set = false;
}
@@ -202,9 +202,9 @@ Key_Length_Specification OpenSSL_Cipher_Mode::key_spec() const
void OpenSSL_Cipher_Mode::key_schedule(const uint8_t key[], size_t length)
{
if(!EVP_CIPHER_CTX_set_key_length(m_cipher, length))
- throw OpenSSL_Error("EVP_CIPHER_CTX_set_key_length");
+ throw OpenSSL_Error("EVP_CIPHER_CTX_set_key_length", ERR_get_error());
if(!EVP_CipherInit_ex(m_cipher, nullptr, nullptr, key, nullptr, -1))
- throw OpenSSL_Error("EVP_CipherInit_ex key");
+ throw OpenSSL_Error("EVP_CipherInit_ex key", ERR_get_error());
m_key_set = true;
m_nonce_set = false;
}
diff --git a/src/lib/prov/openssl/openssl_rc4.cpp b/src/lib/prov/openssl/openssl_rc4.cpp
index 0e00607de..dbda890f8 100644
--- a/src/lib/prov/openssl/openssl_rc4.cpp
+++ b/src/lib/prov/openssl/openssl_rc4.cpp
@@ -51,7 +51,7 @@ class OpenSSL_RC4 final : public StreamCipher
void set_iv(const uint8_t*, size_t len) override
{
if(len > 0)
- throw Exception("RC4 does not support an IV");
+ throw Invalid_IV_Length("RC4", len);
}
void seek(uint64_t) override
diff --git a/src/lib/prov/openssl/openssl_rsa.cpp b/src/lib/prov/openssl/openssl_rsa.cpp
index 4e9068ce4..6744b35b2 100644
--- a/src/lib/prov/openssl/openssl_rsa.cpp
+++ b/src/lib/prov/openssl/openssl_rsa.cpp
@@ -52,7 +52,7 @@ class OpenSSL_RSA_Encryption_Operation final : public PK_Ops::Encryption
const uint8_t* der_ptr = der.data();
m_openssl_rsa.reset(::d2i_RSAPublicKey(nullptr, &der_ptr, der.size()));
if(!m_openssl_rsa)
- throw OpenSSL_Error("d2i_RSAPublicKey");
+ throw OpenSSL_Error("d2i_RSAPublicKey", ERR_get_error());
m_bits = 8 * (n_size() - pad_overhead) - 1;
}
@@ -86,7 +86,7 @@ class OpenSSL_RSA_Encryption_Operation final : public PK_Ops::Encryption
int rc = ::RSA_public_encrypt(inbuf.size(), inbuf.data(), outbuf.data(),
m_openssl_rsa.get(), m_padding);
if(rc < 0)
- throw OpenSSL_Error("RSA_public_encrypt");
+ throw OpenSSL_Error("RSA_public_encrypt", ERR_get_error());
return outbuf;
}
@@ -109,7 +109,7 @@ class OpenSSL_RSA_Decryption_Operation final : public PK_Ops::Decryption
const uint8_t* der_ptr = der.data();
m_openssl_rsa.reset(d2i_RSAPrivateKey(nullptr, &der_ptr, der.size()));
if(!m_openssl_rsa)
- throw OpenSSL_Error("d2i_RSAPrivateKey");
+ throw OpenSSL_Error("d2i_RSAPrivateKey", ERR_get_error());
}
size_t plaintext_length(size_t) const override { return ::RSA_size(m_openssl_rsa.get()); }
@@ -155,7 +155,7 @@ class OpenSSL_RSA_Verification_Operation final : public PK_Ops::Verification_wit
const uint8_t* der_ptr = der.data();
m_openssl_rsa.reset(::d2i_RSAPublicKey(nullptr, &der_ptr, der.size()));
if(!m_openssl_rsa)
- throw OpenSSL_Error("d2i_RSAPublicKey");
+ throw OpenSSL_Error("d2i_RSAPublicKey", ERR_get_error());
}
size_t max_input_bits() const override
@@ -206,7 +206,7 @@ class OpenSSL_RSA_Signing_Operation final : public PK_Ops::Signature_with_EMSA
const uint8_t* der_ptr = der.data();
m_openssl_rsa.reset(d2i_RSAPrivateKey(nullptr, &der_ptr, der.size()));
if(!m_openssl_rsa)
- throw OpenSSL_Error("d2i_RSAPrivateKey");
+ throw OpenSSL_Error("d2i_RSAPrivateKey", ERR_get_error());
}
size_t signature_length() const override { return ::RSA_size(m_openssl_rsa.get()); }
@@ -227,7 +227,7 @@ class OpenSSL_RSA_Signing_Operation final : public PK_Ops::Signature_with_EMSA
int rc = ::RSA_private_encrypt(inbuf.size(), inbuf.data(), outbuf.data(),
m_openssl_rsa.get(), RSA_NO_PADDING);
if(rc < 0)
- throw OpenSSL_Error("RSA_private_encrypt");
+ throw OpenSSL_Error("RSA_private_encrypt", ERR_get_error());
return outbuf;
}
@@ -286,20 +286,20 @@ make_openssl_rsa_private_key(RandomNumberGenerator& rng, size_t rsa_bits)
std::unique_ptr<BIGNUM, std::function<void (BIGNUM*)>> bn(BN_new(), BN_free);
if(!bn)
- throw OpenSSL_Error("BN_new");
+ throw OpenSSL_Error("BN_new", ERR_get_error());
if(!BN_set_word(bn.get(), RSA_F4))
- throw OpenSSL_Error("BN_set_word");
+ throw OpenSSL_Error("BN_set_word", ERR_get_error());
std::unique_ptr<RSA, std::function<void (RSA*)>> rsa(RSA_new(), RSA_free);
if(!rsa)
- throw OpenSSL_Error("RSA_new");
+ throw OpenSSL_Error("RSA_new", ERR_get_error());
if(!RSA_generate_key_ex(rsa.get(), rsa_bits, bn.get(), nullptr))
- throw OpenSSL_Error("RSA_generate_key_ex");
+ throw OpenSSL_Error("RSA_generate_key_ex", ERR_get_error());
uint8_t* der = nullptr;
int bytes = i2d_RSAPrivateKey(rsa.get(), &der);
if(bytes < 0)
- throw OpenSSL_Error("i2d_RSAPrivateKey");
+ throw OpenSSL_Error("i2d_RSAPrivateKey", ERR_get_error());
const secure_vector<uint8_t> keydata(der, der + bytes);
secure_scrub_memory(der, bytes);
diff --git a/src/lib/prov/pkcs11/p11.h b/src/lib/prov/pkcs11/p11.h
index 597a8e125..99c2d0b33 100644
--- a/src/lib/prov/pkcs11/p11.h
+++ b/src/lib/prov/pkcs11/p11.h
@@ -2875,6 +2875,8 @@ class BOTAN_PUBLIC_API(2,0) PKCS11_Error : public Exception
Exception("PKCS11 error", what)
{
}
+
+ ErrorType error_type() const noexcept override { return ErrorType::Pkcs11Error; }
};
class BOTAN_PUBLIC_API(2,0) PKCS11_ReturnError final : public PKCS11_Error
diff --git a/src/lib/prov/pkcs11/p11_ecc_key.h b/src/lib/prov/pkcs11/p11_ecc_key.h
index 5522b07ca..9b6fe9240 100644
--- a/src/lib/prov/pkcs11/p11_ecc_key.h
+++ b/src/lib/prov/pkcs11/p11_ecc_key.h
@@ -186,7 +186,7 @@ class BOTAN_PUBLIC_API(2,0) PKCS11_EC_PrivateKey : public virtual Private_Key,
{
if(m_public_key.is_zero())
{
- throw Exception("Public point not set. Inferring the public key from a PKCS#11 ec private key is not possible.");
+ throw Invalid_State("Public point not set. Inferring the public key from a PKCS#11 ec private key is not possible.");
}
return m_public_key;
}
diff --git a/src/lib/prov/pkcs11/p11_object.h b/src/lib/prov/pkcs11/p11_object.h
index 4cacdbfa7..6d6c7b259 100644
--- a/src/lib/prov/pkcs11/p11_object.h
+++ b/src/lib/prov/pkcs11/p11_object.h
@@ -357,7 +357,7 @@ class BOTAN_PUBLIC_API(2,0) KeyProperties : public StorageObjectProperties
*/
inline void set_allowed_mechanisms(const std::vector<MechanismType>&)
{
- throw Exception("Not implemented (KeyProperties::set_allowed_mechanisms)");
+ throw Not_Implemented("KeyProperties::set_allowed_mechanisms");
}
/// @return the key type of this key object
@@ -424,7 +424,7 @@ class BOTAN_PUBLIC_API(2,0) PublicKeyProperties : public KeyProperties
*/
inline void set_wrap_template(const AttributeContainer&)
{
- throw Exception("Not implemented (PublicKeyProperties::set_wrap_template)");
+ throw Not_Implemented("PublicKeyProperties::set_wrap_template");
}
/// @param pubkey_info DER-encoding of the SubjectPublicKeyInfo for this public key
@@ -503,7 +503,7 @@ class BOTAN_PUBLIC_API(2,0) PrivateKeyProperties : public KeyProperties
*/
inline void set_unwrap_template(const AttributeContainer&)
{
- throw Exception("Not implemented (PrivateKeyProperties::set_unwrap_template)");
+ throw Not_Implemented("PrivateKeyProperties::set_unwrap_template");
}
/// @param pubkey_info DER-encoding of the SubjectPublicKeyInfo for this public key
@@ -603,7 +603,7 @@ class BOTAN_PUBLIC_API(2,0) SecretKeyProperties final : public KeyProperties
*/
inline void set_wrap_template(const AttributeContainer&)
{
- throw Exception("Not implemented (SecretKeyProperties::set_wrap_template)");
+ throw Not_Implemented("SecretKeyProperties::set_wrap_template");
}
/**
@@ -614,7 +614,7 @@ class BOTAN_PUBLIC_API(2,0) SecretKeyProperties final : public KeyProperties
*/
inline void set_unwrap_template(const AttributeContainer&)
{
- throw Exception("Not implemented (SecretKeyProperties::set_unwrap_template)");
+ throw Not_Implemented("SecretKeyProperties::set_unwrap_template");
}
};
diff --git a/src/lib/prov/tpm/tpm.h b/src/lib/prov/tpm/tpm.h
index 7eaf2140c..093bebd62 100644
--- a/src/lib/prov/tpm/tpm.h
+++ b/src/lib/prov/tpm/tpm.h
@@ -25,6 +25,7 @@ class BOTAN_PUBLIC_API(2,0) TPM_Error final : public Exception
{
public:
TPM_Error(const std::string& err) : Exception(err) {}
+ ErrorType error_type() const noexcept override { return ErrorType::TPMError; }
};
/**
diff --git a/src/lib/pubkey/blinding.cpp b/src/lib/pubkey/blinding.cpp
index ecd420780..d1f299229 100644
--- a/src/lib/pubkey/blinding.cpp
+++ b/src/lib/pubkey/blinding.cpp
@@ -35,7 +35,7 @@ BigInt Blinder::blinding_nonce() const
BigInt Blinder::blind(const BigInt& i) const
{
if(!m_reducer.initialized())
- throw Exception("Blinder not initialized, cannot blind");
+ throw Invalid_State("Blinder not initialized, cannot blind");
++m_counter;
@@ -58,7 +58,7 @@ BigInt Blinder::blind(const BigInt& i) const
BigInt Blinder::unblind(const BigInt& i) const
{
if(!m_reducer.initialized())
- throw Exception("Blinder not initialized, cannot unblind");
+ throw Invalid_State("Blinder not initialized, cannot unblind");
return m_reducer.multiply(i, m_d);
}
diff --git a/src/lib/pubkey/ec_group/point_gfp.h b/src/lib/pubkey/ec_group/point_gfp.h
index fa447bf87..222b5f474 100644
--- a/src/lib/pubkey/ec_group/point_gfp.h
+++ b/src/lib/pubkey/ec_group/point_gfp.h
@@ -19,23 +19,26 @@ namespace Botan {
/**
* Exception thrown if you try to convert a zero point to an affine
* coordinate
+*
+* In a future major release this exception type will be removed and its
+* usage replaced by Invalid_State
*/
-class BOTAN_PUBLIC_API(2,0) Illegal_Transformation final : public Exception
+class BOTAN_PUBLIC_API(2,0) Illegal_Transformation final : public Invalid_State
{
public:
- explicit Illegal_Transformation(const std::string& err =
- "Requested transformation is not possible") :
- Exception(err) {}
+ explicit Illegal_Transformation(const std::string& err) : Invalid_State(err) {}
};
/**
* Exception thrown if some form of illegal point is decoded
+*
+* In a future major release this exception type will be removed and its
+* usage replaced by Decoding_Error
*/
-class BOTAN_PUBLIC_API(2,0) Illegal_Point final : public Exception
+class BOTAN_PUBLIC_API(2,0) Illegal_Point final : public Decoding_Error
{
public:
- explicit Illegal_Point(const std::string& err = "Malformed ECP point detected") :
- Exception(err) {}
+ explicit Illegal_Point(const std::string& err) : Decoding_Error(err) {}
};
/**
diff --git a/src/lib/pubkey/mce/gf2m_small_m.cpp b/src/lib/pubkey/mce/gf2m_small_m.cpp
index 95187c7af..8a2632b10 100644
--- a/src/lib/pubkey/mce/gf2m_small_m.cpp
+++ b/src/lib/pubkey/mce/gf2m_small_m.cpp
@@ -59,7 +59,7 @@ const std::vector<gf2m>& exp_table(size_t deg)
static std::vector<gf2m> tabs[MAX_EXT_DEG + 1];
if(deg < 2 || deg > MAX_EXT_DEG)
- throw Exception("GF2m_Field does not support degree " + std::to_string(deg));
+ throw Invalid_Argument("GF2m_Field does not support degree " + std::to_string(deg));
if(tabs[deg].empty())
tabs[deg] = gf_exp_table(deg, prim_poly[deg]);
@@ -84,7 +84,7 @@ const std::vector<gf2m>& log_table(size_t deg)
static std::vector<gf2m> tabs[MAX_EXT_DEG + 1];
if(deg < 2 || deg > MAX_EXT_DEG)
- throw Exception("GF2m_Field does not support degree " + std::to_string(deg));
+ throw Invalid_Argument("GF2m_Field does not support degree " + std::to_string(deg));
if(tabs[deg].empty())
tabs[deg] = gf_log_table(deg, exp_table(deg));
diff --git a/src/lib/pubkey/mceies/mceies.cpp b/src/lib/pubkey/mceies/mceies.cpp
index 15706d430..875c9dd10 100644
--- a/src/lib/pubkey/mceies/mceies.cpp
+++ b/src/lib/pubkey/mceies/mceies.cpp
@@ -83,7 +83,7 @@ mceies_decrypt(const McEliece_PrivateKey& privkey,
const size_t nonce_len = aead->default_nonce_length();
if(ct_len < mce_code_bytes + nonce_len + aead->tag_size())
- throw Exception("Input message too small to be valid");
+ throw Decoding_Error("Input message too small to be valid");
const secure_vector<uint8_t> mce_key = kem_op.decrypt(ct, mce_code_bytes, 64);
@@ -102,7 +102,7 @@ mceies_decrypt(const McEliece_PrivateKey& privkey,
}
catch(std::exception& e)
{
- throw Exception("mce_decrypt failed: " + std::string(e.what()));
+ throw Decoding_Error("mce_decrypt failed: " + std::string(e.what()));
}
}
diff --git a/src/lib/pubkey/pk_ops_impl.h b/src/lib/pubkey/pk_ops_impl.h
index 1878a7417..6bab2143e 100644
--- a/src/lib/pubkey/pk_ops_impl.h
+++ b/src/lib/pubkey/pk_ops_impl.h
@@ -82,7 +82,7 @@ class Verification_with_EMSA : public Verification
* @return the message prefix if this signature scheme uses
* a message prefix, signaled via has_prefix()
*/
- virtual secure_vector<uint8_t> message_prefix() const { throw Exception( "No prefix" ); }
+ virtual secure_vector<uint8_t> message_prefix() const { throw Invalid_State("No prefix"); }
/**
* @return boolean specifying if this key type supports message
@@ -146,7 +146,7 @@ class Signature_with_EMSA : public Signature
* @return the message prefix if this signature scheme uses
* a message prefix, signaled via has_prefix()
*/
- virtual secure_vector<uint8_t> message_prefix() const { throw Exception( "No prefix" ); }
+ virtual secure_vector<uint8_t> message_prefix() const { throw Invalid_State("No prefix"); }
std::unique_ptr<EMSA> clone_emsa() const { return std::unique_ptr<EMSA>(m_emsa->clone()); }
diff --git a/src/lib/pubkey/pkcs8.cpp b/src/lib/pubkey/pkcs8.cpp
index f6d50256d..d299a98a4 100644
--- a/src/lib/pubkey/pkcs8.cpp
+++ b/src/lib/pubkey/pkcs8.cpp
@@ -105,7 +105,7 @@ secure_vector<uint8_t> PKCS8_decode(
if(is_encrypted)
{
if(OIDS::lookup(pbe_alg_id.get_oid()) != "PBE-PKCS5v20")
- throw Exception("Unknown PBE type " + pbe_alg_id.get_oid().as_string());
+ throw PKCS8_Exception("Unknown PBE type " + pbe_alg_id.get_oid().as_string());
#if defined(BOTAN_HAS_PKCS5_PBES2)
key = pbes2_decrypt(key_data, get_passphrase(), pbe_alg_id.get_parameters());
#else
@@ -167,10 +167,13 @@ choose_pbe_params(const std::string& pbe_algo, const std::string& key_algo)
}
SCAN_Name request(pbe_algo);
- if(request.arg_count() != 2)
- throw Exception("Unsupported PBE " + pbe_algo);
- if(request.algo_name() != "PBE-PKCS5v20" && request.algo_name() != "PBES2")
- throw Exception("Unsupported PBE " + pbe_algo);
+
+ if(request.arg_count() != 2 ||
+ (request.algo_name() != "PBE-PKCS5v20" && request.algo_name() != "PBES2"))
+ {
+ throw Invalid_Argument("Unsupported PBE " + pbe_algo);
+ }
+
return std::make_pair(request.arg(0), request.arg(1));
}
diff --git a/src/lib/pubkey/xmss/xmss_parameters.cpp b/src/lib/pubkey/xmss/xmss_parameters.cpp
index 288b50fdc..b67e5694e 100644
--- a/src/lib/pubkey/xmss/xmss_parameters.cpp
+++ b/src/lib/pubkey/xmss/xmss_parameters.cpp
@@ -177,8 +177,7 @@ XMSS_Parameters::XMSS_Parameters(xmss_algorithm_t oid)
m_wots_oid = XMSS_WOTS_Parameters::ots_algorithm_t::WOTSP_SHAKE256_W16;
break;
default:
- throw Unsupported_Argument(
- "Algorithm id does not match any XMSS algorithm id.");
+ throw Not_Implemented("Algorithm id does not match any known XMSS algorithm id.");
break;
}
}
diff --git a/src/lib/pubkey/xmss/xmss_wots_parameters.cpp b/src/lib/pubkey/xmss/xmss_wots_parameters.cpp
index 7ba3dad58..c2a324475 100644
--- a/src/lib/pubkey/xmss/xmss_wots_parameters.cpp
+++ b/src/lib/pubkey/xmss/xmss_wots_parameters.cpp
@@ -75,8 +75,7 @@ XMSS_WOTS_Parameters::XMSS_WOTS_Parameters(ots_algorithm_t oid)
m_strength = 512;
break;
default:
- throw Unsupported_Argument(
- "Algorithm id does not match any XMSS WOTS algorithm id.");
+ throw Not_Implemented("Algorithm id does not match any known XMSS WOTS algorithm id.");
break;
}
diff --git a/src/lib/rng/auto_rng/auto_rng.cpp b/src/lib/rng/auto_rng/auto_rng.cpp
index 8494f115a..a13429e9b 100644
--- a/src/lib/rng/auto_rng/auto_rng.cpp
+++ b/src/lib/rng/auto_rng/auto_rng.cpp
@@ -67,7 +67,7 @@ void AutoSeeded_RNG::force_reseed()
if(!m_rng->is_seeded())
{
- throw Exception("AutoSeeded_RNG reseeding failed");
+ throw Internal_Error("AutoSeeded_RNG reseeding failed");
}
}
diff --git a/src/lib/rng/rdrand_rng/rdrand_rng.cpp b/src/lib/rng/rdrand_rng/rdrand_rng.cpp
index a3ea25921..ba36c9aac 100644
--- a/src/lib/rng/rdrand_rng/rdrand_rng.cpp
+++ b/src/lib/rng/rdrand_rng/rdrand_rng.cpp
@@ -18,7 +18,7 @@ namespace Botan {
RDRAND_RNG::RDRAND_RNG()
{
if(!RDRAND_RNG::available())
- throw Exception("Current CPU does not support RDRAND instruction");
+ throw Invalid_State("Current CPU does not support RDRAND instruction");
}
//static
diff --git a/src/lib/rng/rng.cpp b/src/lib/rng/rng.cpp
index 2947ac629..743f7c7aa 100644
--- a/src/lib/rng/rng.cpp
+++ b/src/lib/rng/rng.cpp
@@ -71,7 +71,7 @@ RandomNumberGenerator* RandomNumberGenerator::make_rng()
#if defined(BOTAN_HAS_AUTO_SEEDING_RNG)
return new AutoSeeded_RNG;
#else
- throw Exception("make_rng failed, no AutoSeeded_RNG in this build");
+ throw Not_Implemented("make_rng failed, no AutoSeeded_RNG in this build");
#endif
}
@@ -82,7 +82,7 @@ Serialized_RNG::Serialized_RNG() : m_rng(new AutoSeeded_RNG) {}
#else
Serialized_RNG::Serialized_RNG()
{
- throw Exception("Serialized_RNG default constructor failed: AutoSeeded_RNG disabled in build");
+ throw Not_Implemented("Serialized_RNG default constructor failed: AutoSeeded_RNG disabled in build");
}
#endif
diff --git a/src/lib/rng/stateful_rng/stateful_rng.cpp b/src/lib/rng/stateful_rng/stateful_rng.cpp
index 058245d14..80442542f 100644
--- a/src/lib/rng/stateful_rng/stateful_rng.cpp
+++ b/src/lib/rng/stateful_rng/stateful_rng.cpp
@@ -112,7 +112,7 @@ void Stateful_RNG::reseed_check()
if(!is_seeded())
{
if(fork_detected)
- throw Exception("Detected use of fork but cannot reseed DRBG");
+ throw Invalid_State("Detected use of fork but cannot reseed DRBG");
else
throw PRNG_Unseeded(name());
}
diff --git a/src/lib/rng/system_rng/system_rng.cpp b/src/lib/rng/system_rng/system_rng.cpp
index ae027d021..8abf8afdc 100644
--- a/src/lib/rng/system_rng/system_rng.cpp
+++ b/src/lib/rng/system_rng/system_rng.cpp
@@ -50,7 +50,7 @@ class System_RNG_Impl final : public RandomNumberGenerator
{
bool success = m_rtlgenrandom(buf, ULONG(len)) == TRUE;
if(!success)
- throw Exception("RtlGenRandom failed");
+ throw System_Error("RtlGenRandom failed");
}
void add_entropy(const uint8_t[], size_t) override { /* ignored */ }
@@ -79,7 +79,7 @@ class System_RNG_Impl final : public RandomNumberGenerator
BCRYPT_RNG_ALGORITHM,
MS_PRIMITIVE_PROVIDER, 0);
if(ret != STATUS_SUCCESS)
- throw Exception("System_RNG failed to acquire crypto provider");
+ throw System_Error("System_RNG failed to acquire crypto provider", ret);
}
~System_RNG_Impl()
@@ -91,7 +91,7 @@ class System_RNG_Impl final : public RandomNumberGenerator
{
NTSTATUS ret = ::BCryptGenRandom(m_prov, static_cast<PUCHAR>(buf), static_cast<ULONG>(len), 0);
if(ret != STATUS_SUCCESS)
- throw Exception("System_RNG call to BCryptGenRandom failed");
+ throw System_Error("System_RNG call to BCryptGenRandom failed", ret);
}
void add_entropy(const uint8_t in[], size_t length) override
@@ -148,7 +148,7 @@ class System_RNG_Impl final : public RandomNumberGenerator
{
if(errno == EINTR)
continue;
- throw Exception("System_RNG getrandom failed error " + std::to_string(errno));
+ throw System_Error("System_RNG getrandom failed", errno);
}
buf += got;
@@ -194,7 +194,7 @@ class System_RNG_Impl final : public RandomNumberGenerator
}
if(m_fd < 0)
- throw Exception("System_RNG failed to open RNG device");
+ throw System_Error("System_RNG failed to open RNG device", errno);
}
~System_RNG_Impl()
@@ -224,10 +224,10 @@ void System_RNG_Impl::randomize(uint8_t buf[], size_t len)
{
if(errno == EINTR)
continue;
- throw Exception("System_RNG read failed error " + std::to_string(errno));
+ throw System_Error("System_RNG read failed", errno);
}
if(got == 0)
- throw Exception("System_RNG EOF on device"); // ?!?
+ throw System_Error("System_RNG EOF on device"); // ?!?
buf += got;
len -= got;
@@ -264,7 +264,7 @@ void System_RNG_Impl::add_entropy(const uint8_t input[], size_t len)
return;
// maybe just ignore any failure here and return?
- throw Exception("System_RNG write failed error " + std::to_string(errno));
+ throw System_Error("System_RNG write failed", errno);
}
input += got;
diff --git a/src/lib/stream/rc4/rc4.cpp b/src/lib/stream/rc4/rc4.cpp
index e427c0288..8bb01a238 100644
--- a/src/lib/stream/rc4/rc4.cpp
+++ b/src/lib/stream/rc4/rc4.cpp
@@ -42,7 +42,7 @@ Key_Length_Specification RC4::key_spec() const
void RC4::set_iv(const uint8_t*, size_t length)
{
if(length > 0)
- throw Exception("RC4 does not support an IV");
+ throw Invalid_IV_Length("RC4", length);
}
/*
diff --git a/src/lib/tls/msg_client_hello.cpp b/src/lib/tls/msg_client_hello.cpp
index a9da82f07..2d303a77e 100644
--- a/src/lib/tls/msg_client_hello.cpp
+++ b/src/lib/tls/msg_client_hello.cpp
@@ -212,7 +212,7 @@ Client_Hello::Client_Hello(Handshake_IO& io,
void Client_Hello::update_hello_cookie(const Hello_Verify_Request& hello_verify)
{
if(!m_version.is_datagram_protocol())
- throw Exception("Cannot use hello cookie with stream protocol");
+ throw Invalid_State("Cannot use hello cookie with stream protocol");
m_hello_cookie = hello_verify.cookie();
}
diff --git a/src/lib/tls/sessions_sql/tls_session_manager_sql.cpp b/src/lib/tls/sessions_sql/tls_session_manager_sql.cpp
index 45b3059f5..1959db266 100644
--- a/src/lib/tls/sessions_sql/tls_session_manager_sql.cpp
+++ b/src/lib/tls/sessions_sql/tls_session_manager_sql.cpp
@@ -69,14 +69,14 @@ Session_Manager_SQL::Session_Manager_SQL(std::shared_ptr<SQL_Database> db,
m_session_key.assign(x.begin() + 2, x.end());
if(check_val_created != check_val_db)
- throw Exception("Session database password not valid");
+ throw Invalid_Argument("Session database password not valid");
}
}
else
{
// maybe just zap the salts + sessions tables in this case?
if(salts != 0)
- throw Exception("Seemingly corrupted database, multiple salts found");
+ throw Internal_Error("Seemingly corrupted TLS session db, multiple salts found");
// new database case
diff --git a/src/lib/tls/tls_callbacks.cpp b/src/lib/tls/tls_callbacks.cpp
index 6919c36ca..28884c1e2 100644
--- a/src/lib/tls/tls_callbacks.cpp
+++ b/src/lib/tls/tls_callbacks.cpp
@@ -71,7 +71,10 @@ void TLS::Callbacks::tls_verify_cert_chain(
ocsp_responses);
if(!result.successful_validation())
- throw Exception("Certificate validation failure: " + result.result_string());
+ {
+ throw TLS_Exception(Alert::BAD_CERTIFICATE,
+ "Certificate validation failure: " + result.result_string());
+ }
}
std::vector<uint8_t> TLS::Callbacks::tls_sign_message(
diff --git a/src/lib/tls/tls_cbc/tls_cbc.cpp b/src/lib/tls/tls_cbc/tls_cbc.cpp
index 23127642d..7376e655b 100644
--- a/src/lib/tls/tls_cbc/tls_cbc.cpp
+++ b/src/lib/tls/tls_cbc/tls_cbc.cpp
@@ -129,7 +129,7 @@ std::vector<uint8_t> TLS_CBC_HMAC_AEAD_Mode::assoc_data_with_len(uint16_t len)
void TLS_CBC_HMAC_AEAD_Mode::set_associated_data(const uint8_t ad[], size_t ad_len)
{
if(ad_len != 13)
- throw Exception("Invalid TLS AEAD associated data length");
+ throw Invalid_Argument("Invalid TLS AEAD associated data length");
m_ad.assign(ad, ad + ad_len);
}
diff --git a/src/lib/tls/tls_channel.cpp b/src/lib/tls/tls_channel.cpp
index 37f3ec415..d3d8f899d 100644
--- a/src/lib/tls/tls_channel.cpp
+++ b/src/lib/tls/tls_channel.cpp
@@ -132,11 +132,11 @@ Handshake_State& Channel::create_handshake_state(Protocol_Version version)
Protocol_Version active_version = active->version();
if(active_version.is_datagram_protocol() != version.is_datagram_protocol())
- throw Exception("Active state using version " +
- active_version.to_string() +
- " cannot change to " +
- version.to_string() +
- " in pending");
+ {
+ throw TLS_Exception(Alert::PROTOCOL_VERSION,
+ "Active state using version " + active_version.to_string() +
+ " cannot change to " + version.to_string() + " in pending");
+ }
}
if(!m_sequence_numbers)
@@ -190,7 +190,7 @@ void Channel::renegotiate(bool force_full_renegotiation)
initiate_handshake(create_handshake_state(active->version()),
force_full_renegotiation);
else
- throw Exception("Cannot renegotiate on inactive connection");
+ throw Invalid_State("Cannot renegotiate on inactive connection");
}
void Channel::change_cipher_spec_reader(Connection_Side side)
@@ -550,7 +550,7 @@ void Channel::send_record_under_epoch(uint16_t epoch, uint8_t record_type,
void Channel::send(const uint8_t buf[], size_t buf_size)
{
if(!is_active())
- throw Exception("Data cannot be sent on inactive TLS connection");
+ throw Invalid_State("Data cannot be sent on inactive TLS connection");
send_record_array(sequence_numbers().current_write_epoch(),
APPLICATION_DATA, buf, buf_size);
@@ -679,7 +679,7 @@ SymmetricKey Channel::key_material_export(const std::string& label,
{
size_t context_size = context.length();
if(context_size > 0xFFFF)
- throw Exception("key_material_export context is too long");
+ throw Invalid_Argument("key_material_export context is too long");
salt.push_back(get_byte(0, static_cast<uint16_t>(context_size)));
salt.push_back(get_byte(1, static_cast<uint16_t>(context_size)));
salt += to_byte_vector(context);
@@ -688,7 +688,9 @@ SymmetricKey Channel::key_material_export(const std::string& label,
return prf->derive_key(length, master_secret, salt, to_byte_vector(label));
}
else
- throw Exception("Channel::key_material_export connection not active");
+ {
+ throw Invalid_State("Channel::key_material_export connection not active");
+ }
}
}
diff --git a/src/lib/tls/tls_exceptn.h b/src/lib/tls/tls_exceptn.h
index 572ff1885..e7d8c1963 100644
--- a/src/lib/tls/tls_exceptn.h
+++ b/src/lib/tls/tls_exceptn.h
@@ -16,7 +16,7 @@ namespace Botan {
namespace TLS {
/**
-* Exception Base Class
+* TLS Exception Base Class
*/
class BOTAN_PUBLIC_API(2,0) TLS_Exception : public Exception
{
@@ -27,6 +27,10 @@ class BOTAN_PUBLIC_API(2,0) TLS_Exception : public Exception
const std::string& err_msg = "Unknown error") :
Exception(err_msg), m_alert_type(type) {}
+ int error_code() const noexcept override { return static_cast<int>(m_alert_type); }
+
+ ErrorType error_type() const noexcept override { return ErrorType::TLSError; }
+
private:
Alert::Type m_alert_type;
};
diff --git a/src/lib/tls/tls_policy.cpp b/src/lib/tls/tls_policy.cpp
index c2d3ccf26..4c6c32d5d 100644
--- a/src/lib/tls/tls_policy.cpp
+++ b/src/lib/tls/tls_policy.cpp
@@ -486,7 +486,7 @@ std::vector<uint16_t> Policy::ciphersuite_list(Protocol_Version version,
if(ciphersuites.empty())
{
- throw Exception("Policy does not allow any available cipher suite");
+ throw Invalid_State("Policy does not allow any available cipher suite");
}
Ciphersuite_Preference_Ordering order(ciphers, macs, kex, sigs);
diff --git a/src/lib/tls/tls_record.cpp b/src/lib/tls/tls_record.cpp
index b5ea33c07..ae807fcdc 100644
--- a/src/lib/tls/tls_record.cpp
+++ b/src/lib/tls/tls_record.cpp
@@ -90,7 +90,7 @@ Connection_Cipher_State::Connection_Cipher_State(Protocol_Version version,
else if(our_side == false)
m_aead->start(iv.bits_of());
#else
- throw Exception("Negotiated disabled TLS CBC+HMAC ciphersuite");
+ throw Internal_Error("Negotiated disabled TLS CBC+HMAC ciphersuite");
#endif
}
else
diff --git a/src/lib/tls/tls_seq_numbers.h b/src/lib/tls/tls_seq_numbers.h
index 1be280453..85077f5f5 100644
--- a/src/lib/tls/tls_seq_numbers.h
+++ b/src/lib/tls/tls_seq_numbers.h
@@ -79,7 +79,7 @@ class Datagram_Sequence_Numbers final : public Connection_Sequence_Numbers
uint64_t next_read_sequence() override
{
- throw Exception("DTLS uses explicit sequence numbers");
+ throw Invalid_State("DTLS uses explicit sequence numbers");
}
bool already_seen(uint64_t sequence) const override
diff --git a/src/lib/tls/tls_text_policy.cpp b/src/lib/tls/tls_text_policy.cpp
index 5c7a4b278..829899fbc 100644
--- a/src/lib/tls/tls_text_policy.cpp
+++ b/src/lib/tls/tls_text_policy.cpp
@@ -283,7 +283,7 @@ bool Text_Policy::get_bool(const std::string& key, bool def) const
}
else
{
- throw Exception("Invalid boolean '" + v + "'");
+ throw Decoding_Error("Invalid boolean '" + v + "'");
}
}
diff --git a/src/lib/utils/assert.cpp b/src/lib/utils/assert.cpp
index 31a35374a..b251a469e 100644
--- a/src/lib/utils/assert.cpp
+++ b/src/lib/utils/assert.cpp
@@ -48,7 +48,7 @@ void assertion_failure(const char* expr_str,
format << "@" << file << ":" << line;
- throw Exception(format.str());
+ throw Internal_Error(format.str());
}
}
diff --git a/src/lib/utils/dyn_load/dyn_load.cpp b/src/lib/utils/dyn_load/dyn_load.cpp
index 1bbcffbdb..b32fe4b3a 100644
--- a/src/lib/utils/dyn_load/dyn_load.cpp
+++ b/src/lib/utils/dyn_load/dyn_load.cpp
@@ -23,8 +23,11 @@ namespace {
void raise_runtime_loader_exception(const std::string& lib_name,
const char* msg)
{
- throw Exception("Failed to load " + lib_name + ": " +
- (msg ? msg : "Unknown error"));
+ const std::string ex_msg =
+ "Failed to load " + lib_name + ": " +
+ (msg ? msg : "Unknown error");
+
+ throw System_Error(ex_msg, 0);
}
}
@@ -70,8 +73,8 @@ void* Dynamically_Loaded_Library::resolve_symbol(const std::string& symbol)
#endif
if(!addr)
- throw Exception("Failed to resolve symbol " + symbol +
- " in " + m_lib_name);
+ throw Invalid_Argument("Failed to resolve symbol " + symbol +
+ " in " + m_lib_name);
return addr;
}
diff --git a/src/lib/utils/exceptn.cpp b/src/lib/utils/exceptn.cpp
index cc6eb9f85..8fc86d3e7 100644
--- a/src/lib/utils/exceptn.cpp
+++ b/src/lib/utils/exceptn.cpp
@@ -105,6 +105,10 @@ Stream_IO_Error::Stream_IO_Error(const std::string& err) :
Exception("I/O error: " + err)
{}
+System_Error::System_Error(const std::string& msg, int err_code) :
+ Exception(msg + " error code " + std::to_string(err_code))
+ {}
+
Self_Test_Failure::Self_Test_Failure(const std::string& err) :
Internal_Error("Self test failed: " + err)
{}
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
diff --git a/src/lib/utils/http_util/http_util.cpp b/src/lib/utils/http_util/http_util.cpp
index f5f9c0213..3fd08b5b8 100644
--- a/src/lib/utils/http_util/http_util.cpp
+++ b/src/lib/utils/http_util/http_util.cpp
@@ -36,7 +36,7 @@ std::string http_transact(const std::string& hostname,
{
socket = OS::open_socket(hostname, "http", timeout);
if(!socket)
- throw Exception("No socket support enabled in build");
+ throw Not_Implemented("No socket support enabled in build");
}
catch(std::exception& e)
{
diff --git a/src/lib/utils/http_util/http_util.h b/src/lib/utils/http_util/http_util.h
index 9edd3d983..92a67e42b 100644
--- a/src/lib/utils/http_util/http_util.h
+++ b/src/lib/utils/http_util/http_util.h
@@ -20,6 +20,20 @@ namespace Botan {
namespace HTTP {
+/**
+* HTTP_Error Exception
+*/
+class BOTAN_PUBLIC_API(2,0) HTTP_Error final : public Exception
+ {
+ public:
+ explicit HTTP_Error(const std::string& msg) :
+ Exception("HTTP error " + msg)
+ {}
+
+ ErrorType error_type() const noexcept override { return ErrorType::HttpError; }
+
+ };
+
class Response final
{
public:
@@ -44,7 +58,7 @@ class Response final
void throw_unless_ok()
{
if(status_code() != 200)
- throw Exception("HTTP error: " + status_message());
+ throw HTTP_Error(status_message());
}
private:
@@ -54,17 +68,6 @@ class Response final
std::map<std::string, std::string> m_headers;
};
-/**
-* HTTP_Error Exception
-*/
-class BOTAN_PUBLIC_API(2,0) HTTP_Error final : public Exception
- {
- public:
- explicit HTTP_Error(const std::string& msg) :
- Exception("HTTP error " + msg)
- {}
- };
-
BOTAN_PUBLIC_API(2,0) std::ostream& operator<<(std::ostream& o, const Response& resp);
typedef std::function<std::string (const std::string&, const std::string&)> http_exch_fn;
diff --git a/src/lib/utils/os_utils.cpp b/src/lib/utils/os_utils.cpp
index 0d98df867..ab9c73b0c 100644
--- a/src/lib/utils/os_utils.cpp
+++ b/src/lib/utils/os_utils.cpp
@@ -430,7 +430,7 @@ int OS::run_cpu_instruction_probe(std::function<int ()> probe_fn)
int rc = ::sigaction(SIGILL, &sigaction, &old_sigaction);
if(rc != 0)
- throw Exception("run_cpu_instruction_probe sigaction failed");
+ throw System_Error("run_cpu_instruction_probe sigaction failed", errno);
rc = sigsetjmp(g_sigill_jmp_buf, /*save sigs*/1);
@@ -448,7 +448,7 @@ int OS::run_cpu_instruction_probe(std::function<int ()> probe_fn)
// Restore old SIGILL handler, if any
rc = ::sigaction(SIGILL, &old_sigaction, nullptr);
if(rc != 0)
- throw Exception("run_cpu_instruction_probe sigaction restore failed");
+ throw System_Error("run_cpu_instruction_probe sigaction restore failed", errno);
#elif defined(BOTAN_TARGET_OS_IS_WINDOWS) && defined(BOTAN_TARGET_COMPILER_IS_MSVC)
diff --git a/src/lib/utils/read_cfg.cpp b/src/lib/utils/read_cfg.cpp
index bf68c0479..02f2e0ac8 100644
--- a/src/lib/utils/read_cfg.cpp
+++ b/src/lib/utils/read_cfg.cpp
@@ -49,7 +49,7 @@ std::map<std::string, std::string> read_cfg(std::istream& is)
auto eq = s.find("=");
if(eq == std::string::npos || eq == 0 || eq == s.size() - 1)
- throw Exception("Bad read_cfg input '" + s + "' on line " + std::to_string(line));
+ throw Decoding_Error("Bad read_cfg input '" + s + "' on line " + std::to_string(line));
const std::string key = clean_ws(s.substr(0, eq));
const std::string val = clean_ws(s.substr(eq + 1, std::string::npos));
diff --git a/src/lib/utils/safeint.h b/src/lib/utils/safeint.h
index 377f13418..5c9ea4955 100644
--- a/src/lib/utils/safeint.h
+++ b/src/lib/utils/safeint.h
@@ -19,6 +19,8 @@ class BOTAN_PUBLIC_API(2,0) Integer_Overflow_Detected final : public Exception
Integer_Overflow_Detected(const std::string& file, int line) :
Exception("Integer overflow detected at " + file + ":" + std::to_string(line))
{}
+
+ ErrorType error_type() const noexcept override { return ErrorType::InternalError; }
};
inline size_t checked_add(size_t x, size_t y, const char* file, int line)
diff --git a/src/lib/utils/socket/socket.cpp b/src/lib/utils/socket/socket.cpp
index 39ffc7951..c9c37f2bb 100644
--- a/src/lib/utils/socket/socket.cpp
+++ b/src/lib/utils/socket/socket.cpp
@@ -73,7 +73,7 @@ class Asio_Socket final : public OS::Socket
if(ec)
throw boost::system::system_error(ec);
if(ec || m_tcp.is_open() == false)
- throw Exception("Connection to host " + hostname + " failed");
+ throw System_Error("Connection to host " + hostname + " failed");
}
void write(const uint8_t buf[], size_t len) override
@@ -166,13 +166,13 @@ class BSD_Socket final : public OS::Socket
if (::WSAStartup(wsa_version, &wsa_data) != 0)
{
- throw Exception("WSAStartup() failed: " + std::to_string(WSAGetLastError()));
+ throw System_Error("WSAStartup() failed", WSAGetLastError());
}
if (LOBYTE(wsa_data.wVersion) != 2 || HIBYTE(wsa_data.wVersion) != 2)
{
::WSACleanup();
- throw Exception("Could not find a usable version of Winsock.dll");
+ throw System_Error("Could not find a usable version of Winsock.dll");
}
}
@@ -190,7 +190,7 @@ class BSD_Socket final : public OS::Socket
static void set_nonblocking(socket_type s)
{
if(::fcntl(s, F_SETFL, O_NONBLOCK) < 0)
- throw Exception("Setting socket to non-blocking state failed");
+ throw System_Error("Setting socket to non-blocking state failed", errno);
}
static void socket_init() {}
@@ -212,9 +212,11 @@ class BSD_Socket final : public OS::Socket
hints.ai_socktype = SOCK_STREAM;
addrinfo* res;
- if(::getaddrinfo(hostname.c_str(), service.c_str(), &hints, &res) != 0)
+ int rc = ::getaddrinfo(hostname.c_str(), service.c_str(), &hints, &res);
+
+ if(rc != 0)
{
- throw Exception("Name resolution failed for " + hostname);
+ throw System_Error("Name resolution failed for " + hostname, rc);
}
for(addrinfo* rp = res; (m_socket == invalid_socket()) && (rp != nullptr); rp = rp->ai_next)
@@ -252,7 +254,7 @@ class BSD_Socket final : public OS::Socket
socklen_t len = sizeof(socket_error);
if(::getsockopt(m_socket, SOL_SOCKET, SO_ERROR, reinterpret_cast<char*>(&socket_error), &len) < 0)
- throw Exception("Error calling getsockopt");
+ throw System_Error("Error calling getsockopt", errno);
if(socket_error != 0)
{
@@ -274,8 +276,8 @@ class BSD_Socket final : public OS::Socket
if(m_socket == invalid_socket())
{
- throw Exception("Connecting to " + hostname +
- " for service " + service + " failed");
+ throw System_Error("Connecting to " + hostname +
+ " for service " + service + " failed", errno);
}
}
@@ -299,13 +301,12 @@ class BSD_Socket final : public OS::Socket
int active = ::select(m_socket + 1, nullptr, &write_set, nullptr, &timeout);
if(active == 0)
- throw Exception("Timeout during socket write");
+ throw System_Error("Timeout during socket write");
const size_t left = len - sent_so_far;
socket_op_ret_type sent = ::send(m_socket, cast_uint8_ptr_to_char(&buf[sent_so_far]), left, 0);
if(sent < 0)
- throw Exception("Socket write failed with error '" +
- std::string(::strerror(errno)) + "'");
+ throw System_Error("Socket write failed", errno);
else
sent_so_far += static_cast<size_t>(sent);
}
@@ -321,13 +322,13 @@ class BSD_Socket final : public OS::Socket
int active = ::select(m_socket + 1, &read_set, nullptr, nullptr, &timeout);
if(active == 0)
- throw Exception("Timeout during socket read");
+ throw System_Error("Timeout during socket read");
socket_op_ret_type got = ::recv(m_socket, cast_uint8_ptr_to_char(buf), len, 0);
if(got < 0)
- throw Exception("Socket read failed with error '" +
- std::string(::strerror(errno)) + "'");
+ throw System_Error("Socket read failed", errno);
+
return static_cast<size_t>(got);
}
diff --git a/src/lib/x509/key_constraint.cpp b/src/lib/x509/key_constraint.cpp
index dfadedac5..95a59d65f 100644
--- a/src/lib/x509/key_constraint.cpp
+++ b/src/lib/x509/key_constraint.cpp
@@ -93,7 +93,7 @@ void verify_cert_constraints_valid_for_key_type(const Public_Key& pub_key,
if((constraints & permitted) != constraints)
{
- throw Exception("Invalid " + name + " constraints " + key_constraints_to_string(constraints));
+ throw Invalid_Argument("Invalid " + name + " constraints " + key_constraints_to_string(constraints));
}
}
diff --git a/src/lib/x509/key_constraint.h b/src/lib/x509/key_constraint.h
index 3d456f6c4..75f9fb82f 100644
--- a/src/lib/x509/key_constraint.h
+++ b/src/lib/x509/key_constraint.h
@@ -37,7 +37,7 @@ class Public_Key;
* Check that key constraints are permitted for a specific public key.
* @param pub_key the public key on which the constraints shall be enforced on
* @param constraints the constraints that shall be enforced on the key
-* @throw Exception if the given constraints are not permitted for this key
+* @throw Invalid_Argument if the given constraints are not permitted for this key
*/
BOTAN_PUBLIC_API(2,0) void verify_cert_constraints_valid_for_key_type(const Public_Key& pub_key,
Key_Constraints constraints);
diff --git a/src/lib/x509/ocsp.cpp b/src/lib/x509/ocsp.cpp
index 115c4117a..62d814702 100644
--- a/src/lib/x509/ocsp.cpp
+++ b/src/lib/x509/ocsp.cpp
@@ -106,8 +106,11 @@ Response::Response(const uint8_t response_bits[], size_t response_bits_len) :
response_outer.decode(resp_status, ENUMERATED, UNIVERSAL);
+ /*
+ * FIXME: properly decode error responses
+ */
if(resp_status != 0)
- throw Exception("OCSP response status " + std::to_string(resp_status));
+ throw Decoding_Error("OCSP response status " + std::to_string(resp_status));
if(response_outer.more_items())
{
diff --git a/src/lib/x509/x509_crl.h b/src/lib/x509/x509_crl.h
index 89925aa04..d52c98e9a 100644
--- a/src/lib/x509/x509_crl.h
+++ b/src/lib/x509/x509_crl.h
@@ -28,12 +28,15 @@ class BOTAN_PUBLIC_API(2,0) X509_CRL final : public X509_Object
public:
/**
* This class represents CRL related errors.
+ *
+ * In a future major release this exception type will be removed and
+ * replaced with Decoding_Error
*/
- class BOTAN_PUBLIC_API(2,0) X509_CRL_Error final : public Exception
+ class BOTAN_PUBLIC_API(2,0) X509_CRL_Error final : public Decoding_Error
{
public:
explicit X509_CRL_Error(const std::string& error) :
- Exception("X509_CRL: " + error) {}
+ Decoding_Error("X509_CRL: " + error) {}
};
/**
diff --git a/src/lib/x509/x509_ext.h b/src/lib/x509/x509_ext.h
index 48a9f338c..11e14e8d6 100644
--- a/src/lib/x509/x509_ext.h
+++ b/src/lib/x509/x509_ext.h
@@ -115,7 +115,7 @@ class BOTAN_PUBLIC_API(2,0) Extensions final : public ASN1_Object
}
else
{
- throw Exception("Exception::get_extension_object_as dynamic_cast failed");
+ throw Decoding_Error("Exception::get_extension_object_as dynamic_cast failed");
}
}
diff --git a/src/lib/x509/x509_obj.cpp b/src/lib/x509/x509_obj.cpp
index 49d7fcc60..6c591bde7 100644
--- a/src/lib/x509/x509_obj.cpp
+++ b/src/lib/x509/x509_obj.cpp
@@ -170,7 +170,7 @@ std::string X509_Object::hash_used_for_signature() const
bool X509_Object::check_signature(const Public_Key* pub_key) const
{
if(!pub_key)
- throw Exception("No key provided for " + PEM_label() + " signature check");
+ throw Invalid_Argument("No key provided for " + PEM_label() + " signature check");
std::unique_ptr<const Public_Key> key(pub_key);
return check_signature(*key);
}
diff --git a/src/lib/x509/x509path.cpp b/src/lib/x509/x509path.cpp
index 8e459e9d2..9fed87f60 100644
--- a/src/lib/x509/x509path.cpp
+++ b/src/lib/x509/x509path.cpp
@@ -452,7 +452,7 @@ PKIX::check_crl_online(const std::vector<std::shared_ptr<const X509_Certificate>
{
// Avoid creating a thread for this case
future_crls.emplace_back(std::async(std::launch::deferred, [&]() -> std::shared_ptr<const X509_CRL> {
- throw Exception("No CRL distribution point for this certificate");
+ throw Not_Implemented("No CRL distribution point for this certificate");
}));
}
else
@@ -741,7 +741,7 @@ PKIX::build_all_certificate_paths(std::vector<std::vector<std::shared_ptr<const
if(cert_paths_out.empty())
{
if(stats.empty())
- throw Exception("X509 path building failed for unknown reasons");
+ throw Internal_Error("X509 path building failed for unknown reasons");
else
// arbitrarily return the first error
return stats[0];
@@ -1005,9 +1005,9 @@ Path_Validation_Result::Path_Validation_Result(CertificatePathStatusCodes status
const X509_Certificate& Path_Validation_Result::trust_root() const
{
if(m_cert_path.empty())
- throw Exception("Path_Validation_Result::trust_root no path set");
+ throw Invalid_State("Path_Validation_Result::trust_root no path set");
if(result() != Certificate_Status_Code::VERIFIED)
- throw Exception("Path_Validation_Result::trust_root meaningless with invalid status");
+ throw Invalid_State("Path_Validation_Result::trust_root meaningless with invalid status");
return *m_cert_path[m_cert_path.size()-1];
}
diff --git a/src/tests/main.cpp b/src/tests/main.cpp
index 6777f85f4..180daf1d4 100644
--- a/src/tests/main.cpp
+++ b/src/tests/main.cpp
@@ -102,7 +102,7 @@ int main(int argc, char* argv[])
#if defined(BOTAN_HAS_OPENSSL)
if(opts.provider().empty() || opts.provider() == "openssl")
{
- ::ERR_free_strings();
+ ERR_free_strings();
::ERR_remove_thread_state(nullptr);
}
#endif
diff --git a/src/tests/test_ffi.cpp b/src/tests/test_ffi.cpp
index aca2dbfb9..50c85eff6 100644
--- a/src/tests/test_ffi.cpp
+++ b/src/tests/test_ffi.cpp
@@ -214,12 +214,12 @@ class FFI_Unit_Tests final : public Test
TEST_FFI_OK(botan_rng_get, (rng, outbuf.data(), outbuf.size()));
TEST_FFI_OK(botan_rng_reseed, (rng, 256));
- TEST_FFI_RC(-20, botan_rng_reseed_from_rng, (rng, null_rng, 256));
+ TEST_FFI_RC(BOTAN_FFI_ERROR_INVALID_OBJECT_STATE, botan_rng_reseed_from_rng, (rng, null_rng, 256));
if(rdrand_rng)
{
TEST_FFI_OK(botan_rng_reseed_from_rng, (rng, rdrand_rng, 256));
}
- TEST_FFI_RC(-20, botan_rng_get, (null_rng, outbuf.data(), outbuf.size()));
+ TEST_FFI_RC(BOTAN_FFI_ERROR_INVALID_OBJECT_STATE, botan_rng_get, (null_rng, outbuf.data(), outbuf.size()));
TEST_FFI_OK(botan_rng_destroy, (rng));
}
diff --git a/src/tests/test_pkcs11_low_level.cpp b/src/tests/test_pkcs11_low_level.cpp
index ffe9dfc20..6dbd6ac0c 100644
--- a/src/tests/test_pkcs11_low_level.cpp
+++ b/src/tests/test_pkcs11_low_level.cpp
@@ -74,7 +74,7 @@ class RAII_LowLevel
if(slots.empty())
{
- throw Exception("No slot with attached token found");
+ throw Test_Error("No slot with attached token found");
}
return slots;
@@ -100,7 +100,7 @@ class RAII_LowLevel
{
if(!m_is_session_open)
{
- throw Exception("no open session");
+ throw Test_Error("no open session");
}
return m_session_handle;
}
@@ -109,7 +109,7 @@ class RAII_LowLevel
{
if(!m_is_session_open)
{
- throw Exception("no open session");
+ throw Test_Error("no open session");
}
m_low_level.get()->C_CloseSession(m_session_handle);
@@ -120,12 +120,12 @@ class RAII_LowLevel
{
if(!m_is_session_open)
{
- throw Exception("no open session");
+ throw Test_Error("no open session");
}
if(m_is_logged_in)
{
- throw Exception("Already logged in");
+ throw Test_Error("Already logged in");
}
m_low_level.get()->C_Login(m_session_handle, user_type, pin);
@@ -136,7 +136,7 @@ class RAII_LowLevel
{
if(!m_is_logged_in)
{
- throw Exception("Not logged in");
+ throw Test_Error("Not logged in");
}
m_low_level.get()->C_Logout(m_session_handle);
diff --git a/src/tests/test_rng.cpp b/src/tests/test_rng.cpp
index 0b316335e..a7510b650 100644
--- a/src/tests/test_rng.cpp
+++ b/src/tests/test_rng.cpp
@@ -150,7 +150,7 @@ class Stateful_RNG_Tests : public Test
size_t poll(Botan::RandomNumberGenerator&) override
{
- throw Botan::Exception("polling not available");
+ throw Botan::Not_Implemented("polling not available");
}
};
diff --git a/src/tests/test_rng.h b/src/tests/test_rng.h
index 822536971..01fe89c92 100644
--- a/src/tests/test_rng.h
+++ b/src/tests/test_rng.h
@@ -122,7 +122,7 @@ class Fixed_Output_Position_RNG final : public Fixed_Output_RNG
void add_entropy(const uint8_t*, size_t) override
{
- throw Botan::Exception("add_entropy() not supported by this RNG, test bug?");
+ throw Test_Error("add_entropy() not supported by this RNG, test bug?");
}
std::string name() const override
@@ -148,7 +148,7 @@ class SeedCapturing_RNG final : public Botan::RandomNumberGenerator
public:
void randomize(uint8_t[], size_t) override
{
- throw Botan::Exception("SeedCapturing_RNG has no output");
+ throw Test_Error("SeedCapturing_RNG has no output");
}
bool accepts_input() const override { return true; }
diff --git a/src/tests/test_tests.cpp b/src/tests/test_tests.cpp
index 49a05d6ab..a7324eef8 100644
--- a/src/tests/test_tests.cpp
+++ b/src/tests/test_tests.cpp
@@ -143,7 +143,7 @@ class Test_Tests final : public Test
{
Test::Result test_result(testcase_name);
test_result.test_throws("test_throws", "expected msg",
- []() { throw Botan::Exception("not the message"); });
+ []() { throw std::runtime_error("not the message"); });
verify_failure("test_throws", result, test_result);
}
diff --git a/src/tests/test_tss.cpp b/src/tests/test_tss.cpp
index 714f08df6..139e2087d 100644
--- a/src/tests/test_tss.cpp
+++ b/src/tests/test_tss.cpp
@@ -40,8 +40,8 @@ class TSS_Recovery_Tests final : public Text_Based_Test
shares.push_back(Botan::RTSS_Share(v.data(), v.size()));
}
- auto reconstructed_secret = Botan::RTSS_Share::reconstruct(shares);
- result.test_eq("Reconstructed secret correctly from all shares", reconstructed_secret, input);
+ auto reconstructed_secret_all = Botan::RTSS_Share::reconstruct(shares);
+ result.test_eq("Reconstructed secret correctly from all shares", reconstructed_secret_all, input);
if(header == "Invalid")
result.test_failure("Invalid shares should not result in recovery");
@@ -127,8 +127,8 @@ class TSS_Generation_Tests final : public Text_Based_Test
result.test_eq("Expected share", shares[i].data(), expected_shares[i]);
}
- auto reconstructed_secret = Botan::RTSS_Share::reconstruct(shares);
- result.test_eq("Reconstructed secret correctly from all shares", reconstructed_secret, input);
+ auto reconstructed_secret_all = Botan::RTSS_Share::reconstruct(shares);
+ result.test_eq("Reconstructed secret correctly from all shares", reconstructed_secret_all, input);
if(N != M)
{
diff --git a/src/tests/test_x509_path.cpp b/src/tests/test_x509_path.cpp
index 57f2d8602..e86c7b70f 100644
--- a/src/tests/test_x509_path.cpp
+++ b/src/tests/test_x509_path.cpp
@@ -634,19 +634,17 @@ std::vector<Test::Result> BSI_Path_Validation_Tests::run()
/* Some certificates are rejected when executing the X509_Certificate constructor
* by throwing a Decoding_Error exception.
*/
- catch(const Botan::Decoding_Error& d)
+ catch(const Botan::Exception& e)
{
- result.test_eq(test_name + " path validation result", d.what(),
- expected_result);
- }
- catch(const Botan::X509_CRL::X509_CRL_Error& e)
- {
- result.test_eq(test_name + " path validation result", e.what(),
- expected_result);
- }
- catch(const std::exception& e)
- {
- result.test_failure(test_name, e.what());
+ if(e.error_type() == Botan::ErrorType::DecodingFailure)
+ {
+ result.test_eq(test_name + " path validation result", e.what(),
+ expected_result);
+ }
+ else
+ {
+ result.test_failure(test_name, e.what());
+ }
}
result.end_timer();
diff --git a/src/tests/tests.h b/src/tests/tests.h
index 7a0e4e54e..d21acf6f9 100644
--- a/src/tests/tests.h
+++ b/src/tests/tests.h
@@ -45,6 +45,7 @@ class Test_Error final : public Botan::Exception
{
public:
explicit Test_Error(const std::string& what) : Exception("Test error", what) {}
+ Botan::ErrorType error_type() const noexcept override { return Botan::ErrorType::Unknown; }
};
class Test_Options