• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

LudovicRousseau / PyKCS11 / 16367380199

18 Jul 2025 09:31AM UTC coverage: 93.474% (+5.9%) from 87.592%
16367380199

push

github

LudovicRousseau
IsNum(): CKA_HW_FEATURE_TYPE is also a numeric value

Thanks to Ivan Wallis for the bug report
"Venafi PKCS#11 Library fails with Unkown PKCS#11 type () during findObjects #140"
Closes: https://github.com/LudovicRousseau/PyKCS11/issues/140

5529 of 5915 relevant lines covered (93.47%)

0.93 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.96
/test/test_objects.py
1
# pylint: disable=missing-module-docstring
2
# pylint: disable=missing-class-docstring
3
# pylint: disable=missing-function-docstring
4

5
import unittest
1✔
6

7
from PyKCS11 import PyKCS11
1✔
8

9
# those shortcuts make the testing code more readable
10
CK_FALSE = PyKCS11.CK_FALSE
1✔
11
CK_TRUE = PyKCS11.CK_TRUE
1✔
12

13

14
class TestUtil(unittest.TestCase):
1✔
15
    def setUp(self):
1✔
16
        self.pkcs11 = PyKCS11.PyKCS11Lib()
1✔
17
        self.pkcs11.load()
1✔
18

19
        # get SoftHSM major version
20
        self.SoftHSMversion = self.pkcs11.getInfo().libraryVersion[0]
1✔
21

22
        self.slot = self.pkcs11.getSlotList(tokenPresent=True)[0]
1✔
23

24
        self.session = self.pkcs11.openSession(
1✔
25
            self.slot, PyKCS11.CKF_SERIAL_SESSION | PyKCS11.CKF_RW_SESSION
26
        )
27
        self.session.login("1234")
1✔
28

29
    def tearDown(self):
1✔
30
        self.session.logout()
1✔
31
        self.pkcs11.closeAllSessions(self.slot)
1✔
32
        del self.pkcs11
1✔
33

34
    def test_objects(self):
1✔
35
        if self.SoftHSMversion < 2:
1✔
36
            self.skipTest("generateKey() only supported by SoftHSM >= 2")
×
37

38
        AESKeyTemplate = [
1✔
39
            (PyKCS11.CKA_CLASS, PyKCS11.CKO_SECRET_KEY),
40
            (PyKCS11.CKA_KEY_TYPE, PyKCS11.CKK_AES),
41
            (PyKCS11.CKA_TOKEN, PyKCS11.CK_TRUE),
42
            (PyKCS11.CKA_PRIVATE, PyKCS11.CK_FALSE),
43
            (PyKCS11.CKA_ENCRYPT, PyKCS11.CK_TRUE),
44
            (PyKCS11.CKA_DECRYPT, PyKCS11.CK_TRUE),
45
            (PyKCS11.CKA_SIGN, PyKCS11.CK_FALSE),
46
            (PyKCS11.CKA_VERIFY, PyKCS11.CK_FALSE),
47
            (PyKCS11.CKA_VALUE_LEN, 32),
48
            (PyKCS11.CKA_LABEL, "TestAESKey"),
49
            (PyKCS11.CKA_ID, (0x01,)),
50
        ]
51

52
        # generate AES key
53
        AESKey = self.session.generateKey(AESKeyTemplate)
1✔
54
        self.assertIsNotNone(AESKey)
1✔
55

56
        # find the first secret key
57
        symKey = self.session.findObjects(
1✔
58
            [(PyKCS11.CKA_CLASS, PyKCS11.CKO_SECRET_KEY)]
59
        )[0]
60

61
        # test object handle
62
        text = str(symKey)
1✔
63
        self.assertIsNotNone(text)
1✔
64

65
        # test createObject()
66
        template = [(PyKCS11.CKA_CLASS, PyKCS11.CKO_DATA), (PyKCS11.CKA_LABEL, "data")]
1✔
67
        handle = self.session.createObject(template)
1✔
68
        self.assertIsNotNone(handle)
1✔
69

70
        self.session.destroyObject(handle)
1✔
71

72
        # test getAttributeValue
73

74
        # attributes as define by AESKeyTemplate
75
        all_attributes = [
1✔
76
            PyKCS11.CKA_CLASS,
77
            PyKCS11.CKA_KEY_TYPE,
78
            PyKCS11.CKA_TOKEN,
79
            PyKCS11.CKA_LABEL,
80
            PyKCS11.CKA_ID,
81
        ]
82

83
        values = self.session.getAttributeValue(AESKey, all_attributes)
1✔
84
        self.assertEqual(
1✔
85
            values,
86
            [
87
                PyKCS11.CKO_SECRET_KEY,
88
                PyKCS11.CKK_AES,
89
                PyKCS11.CK_TRUE,
90
                "TestAESKey",
91
                (0x01,),
92
            ],
93
        )
94

95
        # clean up
96
        self.session.destroyObject(AESKey)
1✔
97

98
        template = [(PyKCS11.CKA_HW_FEATURE_TYPE, PyKCS11.CKH_USER_INTERFACE)]
1✔
99
        o = self.session.findObjects(template)
1✔
100
        self.assertListEqual(o, [])
1✔
101

102
    def test_BoolAttributes(self):
1✔
103
        # dictionary of attributes expected to be bool and their expected values
104
        boolAttributes = {
1✔
105
            PyKCS11.CKA_TOKEN: PyKCS11.CK_FALSE,
106
            PyKCS11.CKA_PRIVATE: PyKCS11.CK_FALSE,
107
            # The attributes below are defaulted to CK_TRUE
108
            # ( according to the PKCS#11 standard )
109
            PyKCS11.CKA_MODIFIABLE: PyKCS11.CK_TRUE,
110
            PyKCS11.CKA_COPYABLE: PyKCS11.CK_TRUE,
111
            PyKCS11.CKA_DESTROYABLE: PyKCS11.CK_TRUE,
112
        }
113

114
        CkoDataTemplate = [
1✔
115
            (PyKCS11.CKA_CLASS, PyKCS11.CKO_DATA),
116
            (PyKCS11.CKA_TOKEN, PyKCS11.CK_FALSE),
117
            (PyKCS11.CKA_PRIVATE, PyKCS11.CK_FALSE),
118
            (PyKCS11.CKA_LABEL, "TestData"),
119
        ]
120

121
        # create a CKO_DATA object
122
        ckoData = self.session.createObject(CkoDataTemplate)
1✔
123
        self.assertIsNotNone(ckoData)
1✔
124

125
        attrValues = self.session.getAttributeValue(
1✔
126
            ckoData, list(boolAttributes.keys())
127
        )
128

129
        # check that attributes are of bool type
130
        # and have expected values
131
        for i, attr in enumerate(boolAttributes):
1✔
132
            self.assertIsInstance(attrValues[i], bool)
1✔
133
            self.assertEqual(attrValues[i], boolAttributes[attr])
1✔
134

135
        # clean up
136
        self.session.destroyObject(ckoData)
1✔
137

138

139
class TestGetSetAttributeValues(unittest.TestCase):
1✔
140

141
    def setUp(self) -> None:
1✔
142

143
        self.pkcs11 = PyKCS11.PyKCS11Lib()
1✔
144
        self.pkcs11.load()
1✔
145

146
        # get SoftHSM major version
147
        self.SoftHSMversion = self.pkcs11.getInfo().libraryVersion[0]
1✔
148
        if self.SoftHSMversion < 2:
1✔
149
            self.skipTest("generateKey() only supported by SoftHSM >= 2")
×
150

151
        self.slot = self.pkcs11.getSlotList(tokenPresent=True)[0]
1✔
152

153
        self.session = self.pkcs11.openSession(
1✔
154
            self.slot, PyKCS11.CKF_SERIAL_SESSION | PyKCS11.CKF_RW_SESSION
155
        )
156
        self.session.login("1234")
1✔
157

158
        AESKeyTemplate = [
1✔
159
            (PyKCS11.CKA_CLASS, PyKCS11.CKO_SECRET_KEY),
160
            (PyKCS11.CKA_KEY_TYPE, PyKCS11.CKK_AES),
161
            (PyKCS11.CKA_TOKEN, CK_TRUE),
162
            (PyKCS11.CKA_PRIVATE, CK_FALSE),
163
            (PyKCS11.CKA_ENCRYPT, CK_TRUE),
164
            (PyKCS11.CKA_DECRYPT, CK_TRUE),
165
            (PyKCS11.CKA_SIGN, CK_FALSE),
166
            (PyKCS11.CKA_VERIFY, CK_FALSE),
167
            (PyKCS11.CKA_VALUE_LEN, 32),
168
            (PyKCS11.CKA_LABEL, "TestAESKey"),
169
            (PyKCS11.CKA_ID, (0x01,)),
170
        ]
171

172
        # generate AES key
173
        self.AESKey = self.session.generateKey(AESKeyTemplate)
1✔
174
        self.assertIsNotNone(self.AESKey)
1✔
175

176
    def tearDown(self):
1✔
177
        self.session.destroyObject(self.AESKey)
1✔
178
        self.session.logout()
1✔
179
        self.pkcs11.closeAllSessions(self.slot)
1✔
180
        del self.pkcs11
1✔
181

182
    def test_getAttributeValue(self):
1✔
183

184
        # attributes as defined by AESKeyTemplate in setUp
185
        all_attributes = [
1✔
186
            PyKCS11.CKA_CLASS,
187
            PyKCS11.CKA_KEY_TYPE,
188
            PyKCS11.CKA_TOKEN,
189
            PyKCS11.CKA_LABEL,
190
            PyKCS11.CKA_ID,
191
        ]
192

193
        values = self.session.getAttributeValue(self.AESKey, all_attributes)
1✔
194
        self.assertEqual(
1✔
195
            values,
196
            [
197
                PyKCS11.CKO_SECRET_KEY,
198
                PyKCS11.CKK_AES,
199
                CK_TRUE,
200
                "TestAESKey",
201
                (0x01,),
202
            ],
203
        )
204

205
    def test_setAttributeValue_with_single_binary_attribute(self):
1✔
206
        # test setAttributeValue with a binary attribute
207
        _ATTR = PyKCS11.CKA_SIGN  # which attribute to test with. use a binary attribute
1✔
208

209
        old_state = self.session.getAttributeValue(self.AESKey, [_ATTR])[0]
1✔
210
        new_state = CK_TRUE if old_state == CK_FALSE else CK_FALSE  # switch the state
1✔
211

212
        # pylint: disable=assignment-from-no-return
213
        rv = self.session.setAttributeValue(self.AESKey, [(_ATTR, new_state)])
1✔
214
        assert rv is None
1✔
215

216
        # test to see if object is really modified
217
        test_state = self.session.getAttributeValue(self.AESKey, [_ATTR])[0]
1✔
218
        assert test_state == new_state
1✔
219
        assert test_state != old_state
1✔
220

221
    def test_setAttributeValue_with_a_list_of_attributes(self):
1✔
222

223
        # which binary attributes to flip?
224
        attributes_to_switch = [
1✔
225
            PyKCS11.CKA_SIGN,
226
            PyKCS11.CKA_ENCRYPT,
227
            PyKCS11.CKA_DECRYPT,
228
            PyKCS11.CKA_VERIFY,
229
            PyKCS11.CKA_WRAP,
230
            PyKCS11.CKA_UNWRAP,
231
        ]
232

233
        old_attributes = self.session.getAttributeValue(
1✔
234
            self.AESKey, attributes_to_switch
235
        )
236

237
        flipped_attributes = []
1✔
238
        for i, attr in enumerate(attributes_to_switch):
1✔
239
            new_value = CK_TRUE if old_attributes[i] == CK_FALSE else CK_FALSE
1✔
240
            flipped_attributes.append((attr, new_value))
1✔
241

242
        # pylint: disable=assignment-from-no-return
243
        rv = self.session.setAttributeValue(self.AESKey, flipped_attributes)
1✔
244
        assert rv is None
1✔
245

246
        new_attributes = self.session.getAttributeValue(
1✔
247
            self.AESKey, attributes_to_switch
248
        )
249
        for new, old in zip(new_attributes, old_attributes):
1✔
250
            assert new != old
1✔
251
            assert (new == CK_TRUE and old == CK_FALSE) or (
1✔
252
                new == CK_FALSE and old == CK_TRUE
253
            )
254

255
    def test_setAttributeValue_with_label_attribute(self):
1✔
256
        # test setAttributeValue with the text field `CKA_Label` by appending some text
257

258
        old_label = self.session.getAttributeValue(self.AESKey, [PyKCS11.CKA_LABEL])[0]
1✔
259
        new_label = old_label + "-mod"
1✔
260
        self.session.setAttributeValue(self.AESKey, [(PyKCS11.CKA_LABEL, new_label)])
1✔
261
        test_label = self.session.getAttributeValue(self.AESKey, [PyKCS11.CKA_LABEL])[0]
1✔
262

263
        assert new_label != old_label
1✔
264
        assert test_label == new_label
1✔
265
        assert test_label != old_label
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc