aboutsummaryrefslogtreecommitdiff
path: root/unit_tests.py
blob: 2e4dc5dc4bda4771323122dcf3a240736052f5c7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#!/usr/bin/env python

import unittest
import os

from py11 import *
from py11.mutex import MutexDB

p11 = None

so_pin    = "fnord"
user_pin  = "fnord"
only_slot = 0

class TestInit(unittest.TestCase):

  def test_no_lock(self):
    p11.C_Initialize()

  def test_os_lock(self):
    p11.C_Initialize(CKF_OS_LOCKING_OK)

  def test_mutex(self):
    mdb = MutexDB()
    p11.C_Initialize(0, mdb.create, mdb.destroy, mdb.lock, mdb.unlock)

  def test_both(self):
    mdb = MutexDB()
    p11.C_Initialize(CKF_OS_LOCKING_OK, mdb.create, mdb.destroy, mdb.lock, mdb.unlock)

  def tearDown(self):
    p11.C_Finalize()

class TestDevice(unittest.TestCase):

  @classmethod
  def setUpClass(cls):
    p11.C_Initialize()

  @classmethod
  def tearDownClass(cls):
    p11.C_Finalize()

  def tearDown(self):
    p11.C_CloseAllSessions(only_slot)

  def test_slots(self):
    self.assertEqual(p11.C_GetSlotList(), [only_slot])

  def test_serial_sessions(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):
    # 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
    handle = CK_SESSION_HANDLE()
    notify = CK_NOTIFY()
    with self.assertRaises(CKR_SESSION_PARALLEL_NOT_SUPPORTED):
      p11.so.C_OpenSession(only_slot, CKF_RW_SESSION, None, notify, byref(handle))
    with self.assertRaises(CKR_SESSION_PARALLEL_NOT_SUPPORTED):
      p11.so.C_OpenSession(only_slot, 0,              None, notify, byref(handle))

  def test_login_user(self):
    rw_session = p11.C_OpenSession(only_slot, CKF_RW_SESSION | CKF_SERIAL_SESSION)
    ro_session = p11.C_OpenSession(only_slot, CKF_SERIAL_SESSION)
    p11.C_Login(ro_session, CKU_USER, user_pin)
    p11.C_Logout(ro_session)

  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)
    p11.C_CloseSession(ro_session)
    p11.C_Login(rw_session, CKU_SO, user_pin)
    self.assertRaises(CKR_SESSION_READ_WRITE_SO_EXISTS, p11.C_OpenSession, only_slot, CKF_SERIAL_SESSION)
    p11.C_Logout(rw_session)

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()

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))

if __name__ == "__main__":
  unittest.main(verbosity = 2)