diff options
-rw-r--r-- | unit_tests.py | 144 |
1 files changed, 110 insertions, 34 deletions
diff --git a/unit_tests.py b/unit_tests.py index 2e4dc5d..b38e4ac 100644 --- a/unit_tests.py +++ b/unit_tests.py @@ -1,30 +1,32 @@ #!/usr/bin/env python import unittest -import os from py11 import * from py11.mutex import MutexDB -p11 = None - +p11 = None so_pin = "fnord" user_pin = "fnord" only_slot = 0 +verbose = True class TestInit(unittest.TestCase): + """ + Test all the flavors of C_Initialize(). + """ - def test_no_lock(self): + def test_mutex_none(self): p11.C_Initialize() - def test_os_lock(self): + def test_mutex_os(self): p11.C_Initialize(CKF_OS_LOCKING_OK) - def test_mutex(self): + def test_mutex_user(self): mdb = MutexDB() p11.C_Initialize(0, mdb.create, mdb.destroy, mdb.lock, mdb.unlock) - def test_both(self): + def test_mutex_both(self): mdb = MutexDB() p11.C_Initialize(CKF_OS_LOCKING_OK, mdb.create, mdb.destroy, mdb.lock, mdb.unlock) @@ -32,6 +34,9 @@ class TestInit(unittest.TestCase): p11.C_Finalize() class TestDevice(unittest.TestCase): + """ + Test basic device stuff like C_GetSlotList(), C_OpenSession(), and C_Login(). + """ @classmethod def setUpClass(cls): @@ -44,14 +49,19 @@ class TestDevice(unittest.TestCase): def tearDown(self): p11.C_CloseAllSessions(only_slot) - def test_slots(self): + def test_getSlots(self): self.assertEqual(p11.C_GetSlotList(), [only_slot]) - def test_serial_sessions(self): + def test_getTokenInfo(self): + token_info = p11.C_GetTokenInfo(only_slot) + self.assertIsInstance(token_info, CK_TOKEN_INFO) + self.assertEqual(token_info.label.rstrip(), "Cryptech Token") + + def test_sessions_serial(self): rw_session = p11.C_OpenSession(only_slot, CKF_RW_SESSION | CKF_SERIAL_SESSION) ro_session = p11.C_OpenSession(only_slot, CKF_SERIAL_SESSION) - def test_parallel_sessions(self): + def test_sessions_parallel(self): # Cooked API doesn't allow the user to make this mistake, so we # have to use the raw API to test it. from ctypes import byref @@ -71,38 +81,104 @@ class TestDevice(unittest.TestCase): def test_login_so(self): rw_session = p11.C_OpenSession(only_slot, CKF_RW_SESSION | CKF_SERIAL_SESSION) ro_session = p11.C_OpenSession(only_slot, CKF_SERIAL_SESSION) - self.assertRaises(CKR_SESSION_READ_ONLY_EXISTS, p11.C_Login, ro_session, CKU_SO, user_pin) + self.assertRaises(CKR_SESSION_READ_ONLY_EXISTS, p11.C_Login, ro_session, CKU_SO, so_pin) p11.C_CloseSession(ro_session) - p11.C_Login(rw_session, CKU_SO, user_pin) + p11.C_Login(rw_session, CKU_SO, so_pin) self.assertRaises(CKR_SESSION_READ_WRITE_SO_EXISTS, p11.C_OpenSession, only_slot, CKF_SERIAL_SESSION) p11.C_Logout(rw_session) + def test_random(self): + # Testing that what this produces really is random seems beyond + # the scope of a unit test. + session = p11.C_OpenSession(only_slot) + n = 17 + random = p11.C_GenerateRandom(session, n) + self.assertIsInstance(random, str) + self.assertEqual(len(random), n) + +class TestKeys(unittest.TestCase): + """ + Tests involving keys. + """ + + oid_p256 = "".join(chr(i) for i in (0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07)) + oid_p384 = "".join(chr(i) for i in (0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22)) + oid_p521 = "".join(chr(i) for i in (0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23)) + + @classmethod + def setUpClass(cls): + p11.C_Initialize() + + @classmethod + def tearDownClass(cls): + p11.C_Finalize() + + def setUp(self): + self.session = p11.C_OpenSession(only_slot) + p11.C_Login(self.session, CKU_USER, user_pin) + + def tearDown(self): + p11.C_CloseAllSessions(only_slot) + del self.session + + def assertIsKeypair(self, public_key, private_key = None): + if isinstance(public_key, tuple) and private_key is None: + public_key, private_key = public_key + self.assertIsInstance(public_key, (int, long)) + self.assertIsInstance(private_key, (int, long)) + # Could do something clever here like use C_GetAttributeValue() to + # examine the objects. Maybe later. + + def test_keygen_ec_p256(self): + self.assertIsKeypair( + p11.C_GenerateKeyPair(self.session, CKM_EC_KEY_PAIR_GEN, CKA_TOKEN = False, + CKA_ID = "EC-P256", CKA_EC_PARAMS = self.oid_p256, + CKA_SIGN = True, CKA_VERIFY = True)) + self.assertIsKeypair( + p11.C_GenerateKeyPair(self.session, CKM_EC_KEY_PAIR_GEN, CKA_TOKEN = True, + CKA_ID = "EC-P256", CKA_EC_PARAMS = self.oid_p256, + CKA_SIGN = True, CKA_VERIFY = True)) + self.assertIsKeypair( + p11.C_GenerateKeyPair(self.session, CKM_EC_KEY_PAIR_GEN, + public_CKA_TOKEN = False, private_CKA_TOKEN = True, + CKA_ID = "EC-P256", CKA_EC_PARAMS = self.oid_p256, + CKA_SIGN = True, CKA_VERIFY = True)) + self.assertIsKeypair( + p11.C_GenerateKeyPair(self.session, CKM_EC_KEY_PAIR_GEN, + public_CKA_TOKEN = True, private_CKA_TOKEN = False, + CKA_ID = "EC-P256", CKA_EC_PARAMS = self.oid_p256, + CKA_SIGN = True, CKA_VERIFY = True)) + + def test_gen_sign_verify_ecdsa_p256_sha256(self): + public_key, private_key = p11.C_GenerateKeyPair(self.session, CKM_EC_KEY_PAIR_GEN, CKA_TOKEN = False, + CKA_ID = "EC-P256", CKA_EC_PARAMS = self.oid_p256, + CKA_SIGN = True, CKA_VERIFY = True) + self.assertIsKeypair(public_key, private_key) + hamster = "Your mother was a hamster" + p11.C_SignInit(self.session, CKM_ECDSA_SHA256, private_key) + sig = p11.C_Sign(self.session, hamster) + self.assertIsInstance(sig, str) + p11.C_VerifyInit(self.session, CKM_ECDSA_SHA256, public_key) + p11.C_Verify(self.session, hamster, sig) + + def setUpModule(): - from os import environ - from os.path import abspath global p11 p11 = PKCS11("./libpkcs11.so") - environ["PKCS11_DATABASE"] = abspath("unit_tests.db") - delete_db() - set_pin() + import os, subprocess + if verbose: + print "Initializing database" + db = os.path.abspath("unit_tests.db") + if os.path.exists(db): + os.unlink(db) + os.environ["PKCS11_DATABASE"] = db + subprocess.Popen(("./p11util", "-sup"), stdin = subprocess.PIPE).communicate("%s\n%s\n" % (so_pin, user_pin)) + if verbose: + print "Setup complete" def tearDownModule(): - delete_db() - -def delete_db(): - from os import environ, unlink - print "Deleting database", environ["PKCS11_DATABASE"] - try: - unlink(environ["PKCS11_DATABASE"]) - except OSError, e: - if e.errno != 2: - raise - -def set_pin(): - from subprocess import Popen, PIPE - print "Creating database and setting PINs" - Popen(("./p11util", "-sup"), stdin = PIPE).communicate("%s\n%s\n" % (so_pin, user_pin)) + import os + os.unlink(os.environ["PKCS11_DATABASE"]) if __name__ == "__main__": - unittest.main(verbosity = 2) - + unittest.main(verbosity = 2 if verbose else 1) |