diff options
Diffstat (limited to 'tests/hazmat')
-rw-r--r-- | tests/hazmat/backends/test_openssl.py | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index f01c3f64..e527ed19 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -11,6 +11,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +import cffi + import pytest from cryptography import utils @@ -23,6 +25,96 @@ from cryptography.hazmat.primitives.ciphers.algorithms import AES from cryptography.hazmat.primitives.ciphers.modes import CBC +ffi = cffi.FFI() + +ffi.cdef(""" +static const char *const Cryptography_faux_engine_name; +static const char *const Cryptography_faux_engine_id; +int Cryptography_add_faux_engine(void); +""") +dummy_engine = ffi.verify( + source=""" + #include <openssl/engine.h> + #include <string.h> + static const char *const Cryptography_faux_engine_name="faux_engine"; + static const char *const Cryptography_faux_engine_id="faux"; + static int faux_bytes(unsigned char *buffer, int size) { + memset(buffer, 1, size); + return 1; + } + static int faux_status(void) { return 1; } + static int faux_init(ENGINE *e) { return 1; } + static int faux_finish(ENGINE *e) { return 1; } + static RAND_METHOD faux_rand = { + NULL, + faux_bytes, + NULL, + NULL, + faux_bytes, + faux_status, + }; + + int Cryptography_add_faux_engine(void) { + ENGINE *e = ENGINE_new(); + if (e == NULL) { + return 0; + } + if(!ENGINE_set_id(e, Cryptography_faux_engine_id) || + !ENGINE_set_name(e, Cryptography_faux_engine_name) || + !ENGINE_set_RAND(e, &faux_rand) || + !ENGINE_set_init_function(e, faux_init) || + !ENGINE_set_finish_function(e, faux_finish)) { + return 0; + } + if (!ENGINE_add(e)) { + ENGINE_free(e); + return 0; + } + if (!ENGINE_free(e)) { + return 0; + } + + return 1; + } + """, + libraries=["crypto", "ssl"], +) + + +def register_dummy_engine(): + current_rand = backend._lib.ENGINE_get_default_RAND() + assert current_rand != backend._ffi.NULL + name = backend._lib.ENGINE_get_name(current_rand) + assert name != backend._ffi.NULL + assert name != dummy_engine.Cryptography_faux_engine_id + res = backend._lib.ENGINE_finish(current_rand) + assert res == 1 + e = backend._lib.ENGINE_by_id(dummy_engine.Cryptography_faux_engine_id) + assert e != backend._ffi.NULL + res = backend._lib.ENGINE_init(e) + assert res == 1 + res = backend._lib.ENGINE_set_default_RAND(e) + assert res == 1 + res = backend._lib.ENGINE_finish(e) + assert res == 1 + res = backend._lib.ENGINE_free(e) + assert res == 1 + # this resets the RNG to use the new engine + backend._lib.RAND_cleanup() + + +def unregister_dummy_engine(): + e = backend._lib.ENGINE_get_default_RAND() + if e != backend._ffi.NULL: + name = backend._lib.ENGINE_get_name(e) + assert name != backend._ffi.NULL + if name == dummy_engine.Cryptography_faux_engine_name: + backend._lib.ENGINE_unregister_RAND(e) + backend._lib.RAND_cleanup() + res = backend._lib.ENGINE_finish(e) + assert res == 1 + + @utils.register_interface(interfaces.Mode) class DummyMode(object): name = "dummy-mode" @@ -113,3 +205,100 @@ class TestOpenSSL(object): b"error:0607F08A:digital envelope routines:EVP_EncryptFinal_ex:" b"data not multiple of block length" ) + + # This test is not in the next class because to check if it's really + # default we don't want to run the setup_method before it + def test_osrandom_engine_is_default(self): + e = backend._lib.ENGINE_get_default_RAND() + name = backend._lib.ENGINE_get_name(e) + assert name == backend._lib.Cryptography_osrandom_engine_name + res = backend._lib.ENGINE_free(e) + assert res == 1 + + +class TestOpenSSLRandomEngine(object): + @classmethod + def setup_class(cls): + # add the faux engine to the list of available engines + res = dummy_engine.Cryptography_add_faux_engine() + assert res == 1 + + def teardown_method(self, method): + # we need to reset state to being default. backend is a shared global + # for all these tests. + unregister_dummy_engine() + backend.register_osrandom_engine() + current_default = backend._lib.ENGINE_get_default_RAND() + name = backend._lib.ENGINE_get_name(current_default) + assert name == backend._lib.Cryptography_osrandom_engine_name + + def test_register_osrandom_already_default(self): + e = backend._lib.ENGINE_get_default_RAND() + name = backend._lib.ENGINE_get_name(e) + assert name == backend._lib.Cryptography_osrandom_engine_name + res = backend._lib.ENGINE_free(e) + assert res == 1 + backend.register_osrandom_engine() + e = backend._lib.ENGINE_get_default_RAND() + name = backend._lib.ENGINE_get_name(e) + assert name == backend._lib.Cryptography_osrandom_engine_name + res = backend._lib.ENGINE_free(e) + assert res == 1 + + def test_unregister_osrandom_engine_nothing_registered(self): + backend.unregister_osrandom_engine() + e = backend._lib.ENGINE_get_default_RAND() + assert e == backend._ffi.NULL + backend.unregister_osrandom_engine() + e = backend._lib.ENGINE_get_default_RAND() + assert e == backend._ffi.NULL + + def test_unregister_osrandom_engine(self): + e = backend._lib.ENGINE_get_default_RAND() + assert e != backend._ffi.NULL + name = backend._lib.ENGINE_get_name(e) + assert name == backend._lib.Cryptography_osrandom_engine_name + res = backend._lib.ENGINE_free(e) + assert res == 1 + backend.unregister_osrandom_engine() + e = backend._lib.ENGINE_get_default_RAND() + assert e == backend._ffi.NULL + + def test_register_osrandom_no_default(self): + backend.unregister_osrandom_engine() + e = backend._lib.ENGINE_get_default_RAND() + assert e == backend._ffi.NULL + backend.register_osrandom_engine() + e = backend._lib.ENGINE_get_default_RAND() + name = backend._lib.ENGINE_get_name(e) + assert name == backend._lib.Cryptography_osrandom_engine_name + res = backend._lib.ENGINE_free(e) + assert res == 1 + + def test_unregister_osrandom_other_engine_default(self): + register_dummy_engine() + default = backend._lib.ENGINE_get_default_RAND() + default_name = backend._lib.ENGINE_get_name(default) + assert default_name == dummy_engine.Cryptography_faux_engine_name + res = backend._lib.ENGINE_finish(default) + assert res == 1 + backend.unregister_osrandom_engine() + current_default = backend._lib.ENGINE_get_default_RAND() + name = backend._lib.ENGINE_get_name(current_default) + assert name == dummy_engine.Cryptography_faux_engine_name + res = backend._lib.ENGINE_finish(current_default) + assert res == 1 + + def test_register_osrandom_other_engine_default(self): + register_dummy_engine() + default = backend._lib.ENGINE_get_default_RAND() + default_name = backend._lib.ENGINE_get_name(default) + assert default_name == dummy_engine.Cryptography_faux_engine_name + res = backend._lib.ENGINE_finish(default) + assert res == 1 + backend.register_osrandom_engine() + current_default = backend._lib.ENGINE_get_default_RAND() + name = backend._lib.ENGINE_get_name(current_default) + assert name == backend._lib.Cryptography_osrandom_engine_name + res = backend._lib.ENGINE_finish(current_default) + assert res == 1 |