aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--unit_tests.py144
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)