From e6d45052efedfe49e99adb6318aaf56e0a9e8d7b Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Thu, 26 Oct 2017 20:31:30 -0400 Subject: Add checks that keyed algorithms are actually keyed before use Previously calling update or encrypt without calling set_key first would result in invalid outputs or else crashing. --- src/lib/prov/openssl/openssl_block.cpp | 15 +++++++++++++-- src/lib/prov/openssl/openssl_rc4.cpp | 5 ++++- 2 files changed, 17 insertions(+), 3 deletions(-) (limited to 'src/lib/prov') diff --git a/src/lib/prov/openssl/openssl_block.cpp b/src/lib/prov/openssl/openssl_block.cpp index 33cd9b8cc..3cf203961 100644 --- a/src/lib/prov/openssl/openssl_block.cpp +++ b/src/lib/prov/openssl/openssl_block.cpp @@ -36,6 +36,7 @@ class OpenSSL_BlockCipher final : public BlockCipher void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override { + 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"); @@ -43,6 +44,7 @@ class OpenSSL_BlockCipher final : public BlockCipher void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override { + 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"); @@ -55,13 +57,15 @@ class OpenSSL_BlockCipher final : public BlockCipher std::string m_cipher_name; EVP_CIPHER_CTX *m_encrypt; EVP_CIPHER_CTX *m_decrypt; + bool m_key_set; }; OpenSSL_BlockCipher::OpenSSL_BlockCipher(const std::string& algo_name, const EVP_CIPHER* algo) : m_block_sz(EVP_CIPHER_block_size(algo)), m_cipher_key_spec(EVP_CIPHER_key_length(algo)), - m_cipher_name(algo_name) + m_cipher_name(algo_name), + m_key_set(false) { if(EVP_CIPHER_mode(algo) != EVP_CIPH_ECB_MODE) throw Invalid_Argument("OpenSSL_BlockCipher: Non-ECB EVP was passed in"); @@ -92,7 +96,8 @@ OpenSSL_BlockCipher::OpenSSL_BlockCipher(const std::string& algo_name, size_t key_mod) : m_block_sz(EVP_CIPHER_block_size(algo)), m_cipher_key_spec(key_min, key_max, key_mod), - m_cipher_name(algo_name) + m_cipher_name(algo_name), + m_key_set(false) { if(EVP_CIPHER_mode(algo) != EVP_CIPH_ECB_MODE) throw Invalid_Argument("OpenSSL_BlockCipher: Non-ECB EVP was passed in"); @@ -134,15 +139,19 @@ void OpenSSL_BlockCipher::key_schedule(const uint8_t key[], size_t length) full_key += std::make_pair(key, 8); } else + { if(EVP_CIPHER_CTX_set_key_length(m_encrypt, length) == 0 || EVP_CIPHER_CTX_set_key_length(m_decrypt, length) == 0) throw Invalid_Argument("OpenSSL_BlockCipher: Bad key length for " + m_cipher_name); + } if(!EVP_EncryptInit_ex(m_encrypt, nullptr, nullptr, full_key.data(), nullptr)) throw OpenSSL_Error("EVP_EncryptInit_ex"); if(!EVP_DecryptInit_ex(m_decrypt, nullptr, nullptr, full_key.data(), nullptr)) throw OpenSSL_Error("EVP_DecryptInit_ex"); + + m_key_set = true; } /* @@ -164,6 +173,8 @@ void OpenSSL_BlockCipher::clear() { const EVP_CIPHER* algo = EVP_CIPHER_CTX_cipher(m_encrypt); + m_key_set = false; + if(!EVP_CIPHER_CTX_cleanup(m_encrypt)) throw OpenSSL_Error("EVP_CIPHER_CTX_cleanup encrypt"); if(!EVP_CIPHER_CTX_cleanup(m_decrypt)) diff --git a/src/lib/prov/openssl/openssl_rc4.cpp b/src/lib/prov/openssl/openssl_rc4.cpp index 5fb2a68f5..b24760f45 100644 --- a/src/lib/prov/openssl/openssl_rc4.cpp +++ b/src/lib/prov/openssl/openssl_rc4.cpp @@ -21,7 +21,7 @@ namespace { class OpenSSL_RC4 final : public StreamCipher { public: - void clear() override { clear_mem(&m_rc4, 1); } + void clear() override { clear_mem(&m_rc4, 1); m_key_set = false; } std::string provider() const override { return "openssl"; } @@ -61,6 +61,7 @@ class OpenSSL_RC4 final : public StreamCipher private: void cipher(const uint8_t in[], uint8_t out[], size_t length) override { + verify_key_set(m_key_set); ::RC4(&m_rc4, length, in, out); } @@ -70,10 +71,12 @@ class OpenSSL_RC4 final : public StreamCipher uint8_t d = 0; for(size_t i = 0; i != m_skip; ++i) ::RC4(&m_rc4, 1, &d, &d); + m_key_set = true; } size_t m_skip; RC4_KEY m_rc4; + bool m_key_set; }; } -- cgit v1.2.3