• 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.17
/test/test_wrap.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

10
class TestUtil(unittest.TestCase):
1✔
11
    def setUp(self):
1✔
12
        self.pkcs11 = PyKCS11.PyKCS11Lib()
1✔
13
        self.pkcs11.load()
1✔
14

15
        # get SoftHSM major version
16
        self.SoftHSMversion = self.pkcs11.getInfo().libraryVersion[0]
1✔
17

18
        self.slot = self.pkcs11.getSlotList(tokenPresent=True)[0]
1✔
19
        self.session = self.pkcs11.openSession(
1✔
20
            self.slot, PyKCS11.CKF_SERIAL_SESSION | PyKCS11.CKF_RW_SESSION
21
        )
22
        self.session.login("1234")
1✔
23

24
    def tearDown(self):
1✔
25
        self.session.logout()
1✔
26
        self.pkcs11.closeAllSessions(self.slot)
1✔
27
        del self.pkcs11
1✔
28

29
    def test_wrapKey(self):
1✔
30
        keyID = (0x01,)
1✔
31
        AESKeyTemplate = [
1✔
32
            (PyKCS11.CKA_CLASS, PyKCS11.CKO_SECRET_KEY),
33
            (PyKCS11.CKA_KEY_TYPE, PyKCS11.CKK_AES),
34
            (PyKCS11.CKA_TOKEN, PyKCS11.CK_TRUE),
35
            (PyKCS11.CKA_PRIVATE, PyKCS11.CK_FALSE),
36
            (PyKCS11.CKA_ENCRYPT, PyKCS11.CK_TRUE),
37
            (PyKCS11.CKA_DECRYPT, PyKCS11.CK_TRUE),
38
            (PyKCS11.CKA_SIGN, PyKCS11.CK_FALSE),
39
            (PyKCS11.CKA_EXTRACTABLE, PyKCS11.CK_TRUE),
40
            (PyKCS11.CKA_VERIFY, PyKCS11.CK_FALSE),
41
            (PyKCS11.CKA_VALUE_LEN, 32),
42
            (PyKCS11.CKA_LABEL, "TestAESKey"),
43
            (PyKCS11.CKA_ID, keyID),
44
        ]
45

46
        if self.SoftHSMversion < 2:
1✔
47
            self.skipTest("generateKey() only supported by SoftHSM >= 2")
×
48

49
        self.wrapKey = self.session.generateKey(AESKeyTemplate)
1✔
50
        self.assertIsNotNone(self.wrapKey)
1✔
51

52
        keyID = (0x02,)
1✔
53
        # make the key extractable
54
        AESKeyTemplate.append((PyKCS11.CKA_EXTRACTABLE, PyKCS11.CK_TRUE))
1✔
55

56
        self.AESKey = self.session.generateKey(AESKeyTemplate)
1✔
57
        self.assertIsNotNone(self.AESKey)
1✔
58

59
        # buffer of 32 bytes 0x42
60
        DataIn = [42] * 32
1✔
61

62
        mechanism = PyKCS11.Mechanism(PyKCS11.CKM_AES_ECB)
1✔
63
        DataOut = self.session.encrypt(self.AESKey, DataIn, mechanism)
1✔
64
        # print("DataOut", DataOut)
65

66
        DataCheck = self.session.decrypt(self.AESKey, DataOut, mechanism)
1✔
67
        # print("DataCheck:", DataCheck)
68

69
        # check we can encrypt/decrypt with the AES key
70
        self.assertSequenceEqual(DataIn, DataCheck)
1✔
71

72
        # wrap using CKM_AES_KEY_WRAP
73
        mechanismWrap = PyKCS11.Mechanism(PyKCS11.CKM_AES_KEY_WRAP)
1✔
74
        wrapped = self.session.wrapKey(self.wrapKey, self.AESKey, mechanismWrap)
1✔
75
        self.assertIsNotNone(wrapped)
1✔
76

77
        # destroy the original key
78
        self.session.destroyObject(self.AESKey)
1✔
79

80
        # unwrap
81
        template = [
1✔
82
            (PyKCS11.CKA_CLASS, PyKCS11.CKO_SECRET_KEY),
83
            (PyKCS11.CKA_KEY_TYPE, PyKCS11.CKK_AES),
84
            (PyKCS11.CKA_TOKEN, PyKCS11.CK_TRUE),
85
            (PyKCS11.CKA_PRIVATE, PyKCS11.CK_FALSE),
86
            (PyKCS11.CKA_ENCRYPT, PyKCS11.CK_TRUE),
87
            (PyKCS11.CKA_DECRYPT, PyKCS11.CK_TRUE),
88
            (PyKCS11.CKA_SIGN, PyKCS11.CK_FALSE),
89
            (PyKCS11.CKA_VERIFY, PyKCS11.CK_FALSE),
90
        ]
91
        unwrapped = self.session.unwrapKey(
1✔
92
            self.wrapKey, wrapped, template, mechanismWrap
93
        )
94
        self.assertIsNotNone(unwrapped)
1✔
95

96
        DataCheck = self.session.decrypt(unwrapped, DataOut, mechanism)
1✔
97
        # print("DataCheck:", DataCheck)
98

99
        # check we can decrypt with the unwrapped AES key
100
        self.assertSequenceEqual(DataIn, DataCheck)
1✔
101

102
        # cleanup
103
        self.session.destroyObject(unwrapped)
1✔
104

105
        self.session.destroyObject(self.wrapKey)
1✔
106

107
    def test_wrapKey_OAEP(self):
1✔
108
        if self.SoftHSMversion < 2:
1✔
109
            self.skipTest("generateKey() only supported by SoftHSM >= 2")
×
110

111
        keyID = (0x22,)
1✔
112
        pubTemplate = [
1✔
113
            (PyKCS11.CKA_CLASS, PyKCS11.CKO_PUBLIC_KEY),
114
            (PyKCS11.CKA_TOKEN, PyKCS11.CK_TRUE),
115
            (PyKCS11.CKA_PRIVATE, PyKCS11.CK_FALSE),
116
            (PyKCS11.CKA_MODULUS_BITS, 0x0400),
117
            (PyKCS11.CKA_PUBLIC_EXPONENT, (0x01, 0x00, 0x01)),
118
            (PyKCS11.CKA_ENCRYPT, PyKCS11.CK_TRUE),
119
            (PyKCS11.CKA_VERIFY, PyKCS11.CK_TRUE),
120
            (PyKCS11.CKA_VERIFY_RECOVER, PyKCS11.CK_TRUE),
121
            (PyKCS11.CKA_WRAP, PyKCS11.CK_TRUE),
122
            (PyKCS11.CKA_LABEL, "My Public Key"),
123
            (PyKCS11.CKA_ID, keyID),
124
        ]
125

126
        privTemplate = [
1✔
127
            (PyKCS11.CKA_CLASS, PyKCS11.CKO_PRIVATE_KEY),
128
            (PyKCS11.CKA_TOKEN, PyKCS11.CK_TRUE),
129
            (PyKCS11.CKA_PRIVATE, PyKCS11.CK_TRUE),
130
            (PyKCS11.CKA_DECRYPT, PyKCS11.CK_TRUE),
131
            (PyKCS11.CKA_SIGN, PyKCS11.CK_TRUE),
132
            (PyKCS11.CKA_SIGN_RECOVER, PyKCS11.CK_TRUE),
133
            (PyKCS11.CKA_UNWRAP, PyKCS11.CK_TRUE),
134
            (PyKCS11.CKA_ID, keyID),
135
        ]
136

137
        self.pubKey, self.privKey = self.session.generateKeyPair(
1✔
138
            pubTemplate, privTemplate
139
        )
140
        self.assertIsNotNone(self.pubKey)
1✔
141
        self.assertIsNotNone(self.privKey)
1✔
142

143
        keyID = (0x02,)
1✔
144
        AESKeyTemplate = [
1✔
145
            (PyKCS11.CKA_CLASS, PyKCS11.CKO_SECRET_KEY),
146
            (PyKCS11.CKA_KEY_TYPE, PyKCS11.CKK_AES),
147
            (PyKCS11.CKA_TOKEN, PyKCS11.CK_TRUE),
148
            (PyKCS11.CKA_PRIVATE, PyKCS11.CK_FALSE),
149
            (PyKCS11.CKA_ENCRYPT, PyKCS11.CK_TRUE),
150
            (PyKCS11.CKA_DECRYPT, PyKCS11.CK_TRUE),
151
            (PyKCS11.CKA_SIGN, PyKCS11.CK_FALSE),
152
            (PyKCS11.CKA_EXTRACTABLE, PyKCS11.CK_TRUE),
153
            (PyKCS11.CKA_VERIFY, PyKCS11.CK_FALSE),
154
            (PyKCS11.CKA_VALUE_LEN, 32),
155
            (PyKCS11.CKA_LABEL, "TestAESKey"),
156
            (PyKCS11.CKA_ID, keyID),
157
        ]
158

159
        # make the key extractable
160
        AESKeyTemplate.append((PyKCS11.CKA_EXTRACTABLE, PyKCS11.CK_TRUE))
1✔
161

162
        self.AESKey = self.session.generateKey(AESKeyTemplate)
1✔
163
        self.assertIsNotNone(self.AESKey)
1✔
164

165
        # buffer of 32 bytes 0x42
166
        DataIn = [42] * 32
1✔
167

168
        mechanism = PyKCS11.Mechanism(PyKCS11.CKM_AES_ECB)
1✔
169
        DataOut = self.session.encrypt(self.AESKey, DataIn, mechanism)
1✔
170
        # print("DataOut", DataOut)
171

172
        DataCheck = self.session.decrypt(self.AESKey, DataOut, mechanism)
1✔
173
        # print("DataCheck:", DataCheck)
174

175
        # check we can encrypt/decrypt with the AES key
176
        self.assertSequenceEqual(DataIn, DataCheck)
1✔
177

178
        # wrap using CKM_RSA_PKCS_OAEP + CKG_MGF1_SHA1
179
        mechanismWrap = PyKCS11.RSAOAEPMechanism(
1✔
180
            PyKCS11.CKM_SHA_1, PyKCS11.CKG_MGF1_SHA1
181
        )
182
        wrapped = self.session.wrapKey(self.pubKey, self.AESKey, mechanismWrap)
1✔
183
        self.assertIsNotNone(wrapped)
1✔
184

185
        # destroy the original key
186
        self.session.destroyObject(self.AESKey)
1✔
187

188
        # unwrap
189
        template = [
1✔
190
            (PyKCS11.CKA_CLASS, PyKCS11.CKO_SECRET_KEY),
191
            (PyKCS11.CKA_KEY_TYPE, PyKCS11.CKK_AES),
192
            (PyKCS11.CKA_TOKEN, PyKCS11.CK_TRUE),
193
            (PyKCS11.CKA_PRIVATE, PyKCS11.CK_FALSE),
194
            (PyKCS11.CKA_ENCRYPT, PyKCS11.CK_TRUE),
195
            (PyKCS11.CKA_DECRYPT, PyKCS11.CK_TRUE),
196
            (PyKCS11.CKA_SIGN, PyKCS11.CK_FALSE),
197
            (PyKCS11.CKA_VERIFY, PyKCS11.CK_FALSE),
198
        ]
199
        unwrapped = self.session.unwrapKey(
1✔
200
            self.privKey, wrapped, template, mechanismWrap
201
        )
202
        self.assertIsNotNone(unwrapped)
1✔
203

204
        DataCheck = self.session.decrypt(unwrapped, DataOut, mechanism)
1✔
205
        # print("DataCheck:", DataCheck)
206

207
        # check we can decrypt with the unwrapped AES key
208
        self.assertSequenceEqual(DataIn, DataCheck)
1✔
209

210
        # cleanup
211
        self.session.destroyObject(unwrapped)
1✔
212

213
        self.session.destroyObject(self.pubKey)
1✔
214
        self.session.destroyObject(self.privKey)
1✔
215

216
    def test_wrapKey_UNWRAP_TEMPLATE(self):
1✔
217
        keyID = (0x01,)
1✔
218
        pubTemplate = [
1✔
219
            (PyKCS11.CKA_CLASS, PyKCS11.CKO_PUBLIC_KEY),
220
            (PyKCS11.CKA_LABEL, "RSA Public Key"),
221
            (PyKCS11.CKA_KEY_TYPE, PyKCS11.CKK_RSA),
222
            (PyKCS11.CKA_TOKEN, PyKCS11.CK_TRUE),
223
            (PyKCS11.CKA_PRIVATE, PyKCS11.CK_TRUE),
224
            (PyKCS11.CKA_VERIFY, PyKCS11.CK_TRUE),
225
            (PyKCS11.CKA_MODULUS_BITS, 2048),
226
            (PyKCS11.CKA_PUBLIC_EXPONENT, (0x01, 0x00, 0x01)),
227
            (PyKCS11.CKA_ID, keyID),
228
            (PyKCS11.CKA_WRAP, PyKCS11.CK_TRUE),
229
        ]
230

231
        unwrap_template = [
1✔
232
            (PyKCS11.CKA_EXTRACTABLE, PyKCS11.CK_FALSE),
233
        ]
234

235
        privTemplate = [
1✔
236
            (PyKCS11.CKA_CLASS, PyKCS11.CKO_PRIVATE_KEY),
237
            (PyKCS11.CKA_LABEL, "RSA Private Key"),
238
            (PyKCS11.CKA_KEY_TYPE, PyKCS11.CKK_RSA),
239
            (PyKCS11.CKA_TOKEN, PyKCS11.CK_TRUE),
240
            (PyKCS11.CKA_PRIVATE, PyKCS11.CK_TRUE),
241
            (PyKCS11.CKA_SIGN, PyKCS11.CK_TRUE),
242
            (PyKCS11.CKA_ID, keyID),
243
            (PyKCS11.CKA_UNWRAP, PyKCS11.CK_TRUE),
244
            (PyKCS11.CKA_UNWRAP_TEMPLATE, unwrap_template),
245
        ]
246

247
        if self.SoftHSMversion < 2:
1✔
248
            self.skipTest("generateKey() only supported by SoftHSM >= 2")
×
249

250
        self.pubKey, self.privKey = self.session.generateKeyPair(
1✔
251
            pubTemplate, privTemplate
252
        )
253
        self.assertIsNotNone(self.pubKey)
1✔
254
        self.assertIsNotNone(self.privKey)
1✔
255

256
        keyID = (0x02,)
1✔
257
        AESKeyTemplate = [
1✔
258
            (PyKCS11.CKA_CLASS, PyKCS11.CKO_SECRET_KEY),
259
            (PyKCS11.CKA_KEY_TYPE, PyKCS11.CKK_AES),
260
            (PyKCS11.CKA_TOKEN, PyKCS11.CK_TRUE),
261
            (PyKCS11.CKA_PRIVATE, PyKCS11.CK_FALSE),
262
            (PyKCS11.CKA_ENCRYPT, PyKCS11.CK_TRUE),
263
            (PyKCS11.CKA_DECRYPT, PyKCS11.CK_TRUE),
264
            (PyKCS11.CKA_SIGN, PyKCS11.CK_FALSE),
265
            (PyKCS11.CKA_EXTRACTABLE, PyKCS11.CK_TRUE),
266
            (PyKCS11.CKA_VERIFY, PyKCS11.CK_FALSE),
267
            (PyKCS11.CKA_VALUE_LEN, 32),
268
            (PyKCS11.CKA_LABEL, "TestAESKey"),
269
            (PyKCS11.CKA_ID, keyID),
270
        ]
271

272
        # make the key extractable
273
        AESKeyTemplate.append((PyKCS11.CKA_EXTRACTABLE, PyKCS11.CK_TRUE))
1✔
274

275
        self.AESKey = self.session.generateKey(AESKeyTemplate)
1✔
276
        self.assertIsNotNone(self.AESKey)
1✔
277

278
        # buffer of 32 bytes 0x42
279
        DataIn = [42] * 32
1✔
280

281
        mechanism = PyKCS11.Mechanism(PyKCS11.CKM_AES_ECB)
1✔
282
        DataOut = self.session.encrypt(self.AESKey, DataIn, mechanism)
1✔
283
        # print("DataOut", DataOut)
284

285
        DataCheck = self.session.decrypt(self.AESKey, DataOut, mechanism)
1✔
286
        # print("DataCheck:", DataCheck)
287

288
        # check we can encrypt/decrypt with the AES key
289
        self.assertSequenceEqual(DataIn, DataCheck)
1✔
290

291
        # wrap
292
        mechanismWrap = PyKCS11.RSAOAEPMechanism(
1✔
293
            PyKCS11.CKM_SHA_1, PyKCS11.CKG_MGF1_SHA1
294
        )
295
        wrapped = self.session.wrapKey(self.pubKey, self.AESKey, mechanismWrap)
1✔
296
        self.assertIsNotNone(wrapped)
1✔
297

298
        # destroy the original key
299
        self.session.destroyObject(self.AESKey)
1✔
300

301
        # unwrap
302
        template = [
1✔
303
            (PyKCS11.CKA_TOKEN, PyKCS11.CK_TRUE),
304
            (PyKCS11.CKA_CLASS, PyKCS11.CKO_SECRET_KEY),
305
            (PyKCS11.CKA_KEY_TYPE, PyKCS11.CKK_AES),
306
            (PyKCS11.CKA_EXTRACTABLE, PyKCS11.CK_FALSE),
307
        ]
308
        unwrapped = self.session.unwrapKey(
1✔
309
            self.privKey, wrapped, template, mechanismWrap
310
        )
311
        self.assertIsNotNone(unwrapped)
1✔
312

313
        DataCheck = self.session.decrypt(unwrapped, DataOut, mechanism)
1✔
314
        # print("DataCheck:", DataCheck)
315

316
        # check we can decrypt with the unwrapped AES key
317
        self.assertSequenceEqual(DataIn, DataCheck)
1✔
318

319
        attributes = self.session.getAttributeValue(
1✔
320
            unwrapped, [PyKCS11.CKA_EXTRACTABLE]
321
        )
322
        self.assertSequenceEqual(attributes, [False])
1✔
323

324
        # cleanup
325
        self.session.destroyObject(unwrapped)
1✔
326

327
        self.session.destroyObject(self.pubKey)
1✔
328
        self.session.destroyObject(self.privKey)
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