aboutsummaryrefslogtreecommitdiffstats
path: root/tests/hazmat/backends
diff options
context:
space:
mode:
Diffstat (limited to 'tests/hazmat/backends')
-rw-r--r--tests/hazmat/backends/test_openssl.py189
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