python-pkcs11 0.8.0__cp39-cp39-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pkcs11/__init__.py +36 -0
- pkcs11/_pkcs11.cp39-win_amd64.pyd +0 -0
- pkcs11/_pkcs11.pxd +622 -0
- pkcs11/_pkcs11.pyx +1891 -0
- pkcs11/constants.py +514 -0
- pkcs11/defaults.py +197 -0
- pkcs11/exceptions.py +414 -0
- pkcs11/mechanisms.py +796 -0
- pkcs11/types.py +1169 -0
- pkcs11/util/__init__.py +12 -0
- pkcs11/util/dh.py +72 -0
- pkcs11/util/dsa.py +101 -0
- pkcs11/util/ec.py +133 -0
- pkcs11/util/rsa.py +81 -0
- pkcs11/util/x509.py +124 -0
- python_pkcs11-0.8.0.dist-info/METADATA +392 -0
- python_pkcs11-0.8.0.dist-info/RECORD +20 -0
- python_pkcs11-0.8.0.dist-info/WHEEL +5 -0
- python_pkcs11-0.8.0.dist-info/licenses/LICENSE +21 -0
- python_pkcs11-0.8.0.dist-info/top_level.txt +1 -0
pkcs11/_pkcs11.pyx
ADDED
|
@@ -0,0 +1,1891 @@
|
|
|
1
|
+
#!python
|
|
2
|
+
#cython: language_level=3
|
|
3
|
+
"""
|
|
4
|
+
High-level Python PKCS#11 Wrapper.
|
|
5
|
+
|
|
6
|
+
Most class here inherit from pkcs11.types, which provides easier introspection
|
|
7
|
+
for Sphinx/Jedi/etc, as this module is not importable without having the
|
|
8
|
+
library loaded.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import (absolute_import, unicode_literals,
|
|
12
|
+
print_function, division)
|
|
13
|
+
|
|
14
|
+
from cpython.mem cimport PyMem_Malloc, PyMem_Free
|
|
15
|
+
|
|
16
|
+
from . import types
|
|
17
|
+
from .defaults import *
|
|
18
|
+
from .exceptions import *
|
|
19
|
+
from .constants import *
|
|
20
|
+
from .mechanisms import *
|
|
21
|
+
from .types import (
|
|
22
|
+
_CK_UTF8CHAR_to_str,
|
|
23
|
+
_CK_VERSION_to_tuple,
|
|
24
|
+
_CK_MECHANISM_TYPE_to_enum,
|
|
25
|
+
PROTECTED_AUTH,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# _funclist is used to keep the pointer to the list of functions, when lib() is invoked.
|
|
30
|
+
# This is a global, as this object cannot be shared between Python and Cython classes
|
|
31
|
+
# Due to this limitation, the current implementation limits the loading of the library
|
|
32
|
+
# to one instance only, or to several instances of the same kind.
|
|
33
|
+
cdef CK_FUNCTION_LIST *_funclist = NULL
|
|
34
|
+
|
|
35
|
+
cdef assertRV(rv) with gil:
|
|
36
|
+
"""Check for an acceptable RV value or thrown an exception."""
|
|
37
|
+
if rv == CKR_OK:
|
|
38
|
+
return
|
|
39
|
+
elif rv == CKR_ATTRIBUTE_TYPE_INVALID:
|
|
40
|
+
exc = AttributeTypeInvalid()
|
|
41
|
+
elif rv == CKR_ATTRIBUTE_VALUE_INVALID:
|
|
42
|
+
exc = AttributeValueInvalid()
|
|
43
|
+
elif rv == CKR_ATTRIBUTE_READ_ONLY:
|
|
44
|
+
exc = AttributeReadOnly()
|
|
45
|
+
elif rv == CKR_ATTRIBUTE_SENSITIVE:
|
|
46
|
+
exc = AttributeSensitive()
|
|
47
|
+
elif rv == CKR_ARGUMENTS_BAD:
|
|
48
|
+
exc = ArgumentsBad()
|
|
49
|
+
elif rv == CKR_BUFFER_TOO_SMALL:
|
|
50
|
+
exc = MemoryError("Buffer was too small. Should never see this.")
|
|
51
|
+
elif rv == CKR_CRYPTOKI_ALREADY_INITIALIZED:
|
|
52
|
+
exc = RuntimeError("Initialisation error (already initialized). Should never see this.")
|
|
53
|
+
elif rv == CKR_CRYPTOKI_NOT_INITIALIZED:
|
|
54
|
+
exc = RuntimeError("Initialisation error (not initialized). Should never see this.")
|
|
55
|
+
elif rv == CKR_DATA_INVALID:
|
|
56
|
+
exc = DataInvalid()
|
|
57
|
+
elif rv == CKR_DATA_LEN_RANGE:
|
|
58
|
+
exc = DataLenRange()
|
|
59
|
+
elif rv == CKR_DOMAIN_PARAMS_INVALID:
|
|
60
|
+
exc = DomainParamsInvalid()
|
|
61
|
+
elif rv == CKR_DEVICE_ERROR:
|
|
62
|
+
exc = DeviceError()
|
|
63
|
+
elif rv == CKR_DEVICE_MEMORY:
|
|
64
|
+
exc = DeviceMemory()
|
|
65
|
+
elif rv == CKR_DEVICE_REMOVED:
|
|
66
|
+
exc = DeviceRemoved()
|
|
67
|
+
elif rv == CKR_ENCRYPTED_DATA_INVALID:
|
|
68
|
+
exc = EncryptedDataInvalid()
|
|
69
|
+
elif rv == CKR_ENCRYPTED_DATA_LEN_RANGE:
|
|
70
|
+
exc = EncryptedDataLenRange()
|
|
71
|
+
elif rv == CKR_EXCEEDED_MAX_ITERATIONS:
|
|
72
|
+
exc = ExceededMaxIterations()
|
|
73
|
+
elif rv == CKR_FUNCTION_CANCELED:
|
|
74
|
+
exc = FunctionCancelled()
|
|
75
|
+
elif rv == CKR_FUNCTION_FAILED:
|
|
76
|
+
exc = FunctionFailed()
|
|
77
|
+
elif rv == CKR_FUNCTION_REJECTED:
|
|
78
|
+
exc = FunctionRejected()
|
|
79
|
+
elif rv == CKR_FUNCTION_NOT_SUPPORTED:
|
|
80
|
+
exc = FunctionNotSupported()
|
|
81
|
+
elif rv == CKR_KEY_HANDLE_INVALID:
|
|
82
|
+
exc = KeyHandleInvalid()
|
|
83
|
+
elif rv == CKR_KEY_INDIGESTIBLE:
|
|
84
|
+
exc = KeyIndigestible()
|
|
85
|
+
elif rv == CKR_KEY_NEEDED:
|
|
86
|
+
exc = KeyNeeded()
|
|
87
|
+
elif rv == CKR_KEY_NOT_NEEDED:
|
|
88
|
+
exc = KeyNotNeeded()
|
|
89
|
+
elif rv == CKR_KEY_SIZE_RANGE:
|
|
90
|
+
exc = KeySizeRange()
|
|
91
|
+
elif rv == CKR_KEY_NOT_WRAPPABLE:
|
|
92
|
+
exc = KeyNotWrappable()
|
|
93
|
+
elif rv == CKR_KEY_TYPE_INCONSISTENT:
|
|
94
|
+
exc = KeyTypeInconsistent()
|
|
95
|
+
elif rv == CKR_KEY_UNEXTRACTABLE:
|
|
96
|
+
exc = KeyUnextractable()
|
|
97
|
+
elif rv == CKR_GENERAL_ERROR:
|
|
98
|
+
exc = GeneralError()
|
|
99
|
+
elif rv == CKR_HOST_MEMORY:
|
|
100
|
+
exc = HostMemory()
|
|
101
|
+
elif rv == CKR_MECHANISM_INVALID:
|
|
102
|
+
exc = MechanismInvalid()
|
|
103
|
+
elif rv == CKR_MECHANISM_PARAM_INVALID:
|
|
104
|
+
exc = MechanismParamInvalid()
|
|
105
|
+
elif rv == CKR_NO_EVENT:
|
|
106
|
+
exc = NoEvent()
|
|
107
|
+
elif rv == CKR_OBJECT_HANDLE_INVALID:
|
|
108
|
+
exc = ObjectHandleInvalid()
|
|
109
|
+
elif rv == CKR_OPERATION_ACTIVE:
|
|
110
|
+
exc = OperationActive()
|
|
111
|
+
elif rv == CKR_OPERATION_NOT_INITIALIZED:
|
|
112
|
+
exc = OperationNotInitialized()
|
|
113
|
+
elif rv == CKR_PIN_EXPIRED:
|
|
114
|
+
exc = PinExpired()
|
|
115
|
+
elif rv == CKR_PIN_INCORRECT:
|
|
116
|
+
exc = PinIncorrect()
|
|
117
|
+
elif rv == CKR_PIN_INVALID:
|
|
118
|
+
exc = PinInvalid()
|
|
119
|
+
elif rv == CKR_PIN_LOCKED:
|
|
120
|
+
exc = PinLocked()
|
|
121
|
+
elif rv == CKR_PIN_TOO_WEAK:
|
|
122
|
+
exc = PinTooWeak()
|
|
123
|
+
elif rv == CKR_PUBLIC_KEY_INVALID:
|
|
124
|
+
exc = PublicKeyInvalid()
|
|
125
|
+
elif rv == CKR_RANDOM_NO_RNG:
|
|
126
|
+
exc = RandomNoRNG()
|
|
127
|
+
elif rv == CKR_RANDOM_SEED_NOT_SUPPORTED:
|
|
128
|
+
exc = RandomSeedNotSupported()
|
|
129
|
+
elif rv == CKR_SESSION_CLOSED:
|
|
130
|
+
exc = SessionClosed()
|
|
131
|
+
elif rv == CKR_SESSION_COUNT:
|
|
132
|
+
exc = SessionCount()
|
|
133
|
+
elif rv == CKR_SESSION_EXISTS:
|
|
134
|
+
exc = SessionExists()
|
|
135
|
+
elif rv == CKR_SESSION_HANDLE_INVALID:
|
|
136
|
+
exc = SessionHandleInvalid()
|
|
137
|
+
elif rv == CKR_SESSION_PARALLEL_NOT_SUPPORTED:
|
|
138
|
+
exc = RuntimeError("Parallel not supported. Should never see this.")
|
|
139
|
+
elif rv == CKR_SESSION_READ_ONLY:
|
|
140
|
+
exc = SessionReadOnly()
|
|
141
|
+
elif rv == CKR_SESSION_READ_ONLY_EXISTS:
|
|
142
|
+
exc = SessionReadOnlyExists()
|
|
143
|
+
elif rv == CKR_SESSION_READ_WRITE_SO_EXISTS:
|
|
144
|
+
exc = SessionReadWriteSOExists()
|
|
145
|
+
elif rv == CKR_SIGNATURE_LEN_RANGE:
|
|
146
|
+
exc = SignatureLenRange()
|
|
147
|
+
elif rv == CKR_SIGNATURE_INVALID:
|
|
148
|
+
exc = SignatureInvalid()
|
|
149
|
+
elif rv == CKR_TEMPLATE_INCOMPLETE:
|
|
150
|
+
exc = TemplateIncomplete()
|
|
151
|
+
elif rv == CKR_TEMPLATE_INCONSISTENT:
|
|
152
|
+
exc = TemplateInconsistent()
|
|
153
|
+
elif rv == CKR_SLOT_ID_INVALID:
|
|
154
|
+
exc = SlotIDInvalid()
|
|
155
|
+
elif rv == CKR_TOKEN_NOT_PRESENT:
|
|
156
|
+
exc = TokenNotPresent()
|
|
157
|
+
elif rv == CKR_TOKEN_NOT_RECOGNIZED:
|
|
158
|
+
exc = TokenNotRecognised()
|
|
159
|
+
elif rv == CKR_TOKEN_WRITE_PROTECTED:
|
|
160
|
+
exc = TokenWriteProtected()
|
|
161
|
+
elif rv == CKR_UNWRAPPING_KEY_HANDLE_INVALID:
|
|
162
|
+
exc = UnwrappingKeyHandleInvalid()
|
|
163
|
+
elif rv == CKR_UNWRAPPING_KEY_SIZE_RANGE:
|
|
164
|
+
exc = UnwrappingKeySizeRange()
|
|
165
|
+
elif rv == CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT:
|
|
166
|
+
exc = UnwrappingKeyTypeInconsistent()
|
|
167
|
+
elif rv == CKR_USER_NOT_LOGGED_IN:
|
|
168
|
+
exc = UserNotLoggedIn()
|
|
169
|
+
elif rv == CKR_USER_ALREADY_LOGGED_IN:
|
|
170
|
+
exc = UserAlreadyLoggedIn()
|
|
171
|
+
elif rv == CKR_USER_ANOTHER_ALREADY_LOGGED_IN:
|
|
172
|
+
exc = AnotherUserAlreadyLoggedIn()
|
|
173
|
+
elif rv == CKR_USER_PIN_NOT_INITIALIZED:
|
|
174
|
+
exc = UserPinNotInitialized()
|
|
175
|
+
elif rv == CKR_USER_TOO_MANY_TYPES:
|
|
176
|
+
exc = UserTooManyTypes()
|
|
177
|
+
elif rv == CKR_USER_TYPE_INVALID:
|
|
178
|
+
exc = RuntimeError("User type invalid. Should never see this.")
|
|
179
|
+
elif rv == CKR_WRAPPED_KEY_INVALID:
|
|
180
|
+
exc = WrappedKeyInvalid()
|
|
181
|
+
elif rv == CKR_WRAPPED_KEY_LEN_RANGE:
|
|
182
|
+
exc = WrappedKeyLenRange()
|
|
183
|
+
elif rv == CKR_WRAPPING_KEY_HANDLE_INVALID:
|
|
184
|
+
exc = WrappingKeyHandleInvalid()
|
|
185
|
+
elif rv == CKR_WRAPPING_KEY_SIZE_RANGE:
|
|
186
|
+
exc = WrappingKeySizeRange()
|
|
187
|
+
elif rv == CKR_WRAPPING_KEY_TYPE_INCONSISTENT:
|
|
188
|
+
exc = WrappingKeyTypeInconsistent()
|
|
189
|
+
else:
|
|
190
|
+
exc = PKCS11Error("Unmapped error code %s" % hex(rv))
|
|
191
|
+
raise exc
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
cdef class AttributeList:
|
|
196
|
+
"""
|
|
197
|
+
A list of CK_ATTRIBUTE objects.
|
|
198
|
+
"""
|
|
199
|
+
|
|
200
|
+
cdef CK_ATTRIBUTE *data
|
|
201
|
+
"""CK_ATTRIBUTE * representation of the data."""
|
|
202
|
+
cdef CK_ULONG count
|
|
203
|
+
"""Length of `data`."""
|
|
204
|
+
|
|
205
|
+
cdef _values
|
|
206
|
+
|
|
207
|
+
def __cinit__(self, attrs):
|
|
208
|
+
attrs = dict(attrs)
|
|
209
|
+
self.count = count = <CK_ULONG> len(attrs)
|
|
210
|
+
|
|
211
|
+
self.data = <CK_ATTRIBUTE *> PyMem_Malloc(count * sizeof(CK_ATTRIBUTE))
|
|
212
|
+
if not self.data:
|
|
213
|
+
raise MemoryError()
|
|
214
|
+
|
|
215
|
+
# Turn the values into bytes and store them so we have pointers
|
|
216
|
+
# to them.
|
|
217
|
+
self._values = [
|
|
218
|
+
(key, _pack_attribute(key, value))
|
|
219
|
+
for key, value in attrs.items()
|
|
220
|
+
]
|
|
221
|
+
|
|
222
|
+
for index, (key, value) in enumerate(self._values):
|
|
223
|
+
self.data[index].type = key
|
|
224
|
+
self.data[index].pValue = <CK_CHAR *> value
|
|
225
|
+
self.data[index].ulValueLen = <CK_ULONG>len(value)
|
|
226
|
+
|
|
227
|
+
def __dealloc__(self):
|
|
228
|
+
PyMem_Free(self.data)
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
cdef class MechanismWithParam:
|
|
232
|
+
"""
|
|
233
|
+
Python wrapper for a Mechanism with its parameter
|
|
234
|
+
"""
|
|
235
|
+
|
|
236
|
+
cdef CK_MECHANISM *data
|
|
237
|
+
"""The mechanism."""
|
|
238
|
+
cdef void *param
|
|
239
|
+
"""Reference to a pointer we might need to free."""
|
|
240
|
+
|
|
241
|
+
def __cinit__(self, *args):
|
|
242
|
+
self.data = <CK_MECHANISM *> PyMem_Malloc(sizeof(CK_MECHANISM))
|
|
243
|
+
self.param = NULL
|
|
244
|
+
|
|
245
|
+
def __init__(self, key_type, mapping, mechanism=None, param=None):
|
|
246
|
+
if mechanism is None:
|
|
247
|
+
try:
|
|
248
|
+
mechanism = mapping[key_type]
|
|
249
|
+
except KeyError:
|
|
250
|
+
raise ArgumentsBad("No default mechanism for this key type. "
|
|
251
|
+
"Please specify `mechanism`.")
|
|
252
|
+
|
|
253
|
+
if not isinstance(mechanism, Mechanism):
|
|
254
|
+
raise ArgumentsBad("`mechanism` must be a Mechanism.")
|
|
255
|
+
# Possible types of parameters we might need to allocate
|
|
256
|
+
# These are used to make assigning to the object we malloc() easier
|
|
257
|
+
# FIXME: is there a better way to do this?
|
|
258
|
+
cdef CK_RSA_PKCS_OAEP_PARAMS *oaep_params
|
|
259
|
+
cdef CK_RSA_PKCS_PSS_PARAMS *pss_params
|
|
260
|
+
cdef CK_EDDSA_PARAMS *eddsa_params
|
|
261
|
+
cdef CK_ECDH1_DERIVE_PARAMS *ecdh1_params
|
|
262
|
+
cdef CK_KEY_DERIVATION_STRING_DATA *aes_ecb_params
|
|
263
|
+
cdef CK_AES_CBC_ENCRYPT_DATA_PARAMS *aes_cbc_params
|
|
264
|
+
|
|
265
|
+
# Unpack mechanism parameters
|
|
266
|
+
|
|
267
|
+
if mechanism == Mechanism.AES_ECB_ENCRYPT_DATA:
|
|
268
|
+
paramlen = sizeof(CK_KEY_DERIVATION_STRING_DATA)
|
|
269
|
+
self.param = aes_ecb_params = \
|
|
270
|
+
<CK_KEY_DERIVATION_STRING_DATA *> PyMem_Malloc(paramlen)
|
|
271
|
+
aes_ecb_params.pData = <CK_BYTE *> param
|
|
272
|
+
aes_ecb_params.ulLen = <CK_ULONG> len(param)
|
|
273
|
+
|
|
274
|
+
elif isinstance(param, bytes):
|
|
275
|
+
# Note: this is an escape hatch of sorts that can be used to provide parameters for
|
|
276
|
+
# unsupported algorithms in raw binary form.
|
|
277
|
+
# We include it at this point in the chain for forwards compatibility reasons:
|
|
278
|
+
# if at a later point, "first class" support for the unsupported mechanism is added
|
|
279
|
+
# to the library, existing code that used this "raw mode" workaround will keep working
|
|
280
|
+
# because this branch takes priority.
|
|
281
|
+
#
|
|
282
|
+
# The parameter convention for AES_ECB_ENCRYPT_DATA predates this ordering decision,
|
|
283
|
+
# so it takes precedence over this branch for backwards compatibility.
|
|
284
|
+
self.data.pParameter = <CK_BYTE *> param
|
|
285
|
+
paramlen = len(param)
|
|
286
|
+
|
|
287
|
+
elif mechanism == Mechanism.RSA_PKCS_OAEP:
|
|
288
|
+
paramlen = sizeof(CK_RSA_PKCS_OAEP_PARAMS)
|
|
289
|
+
self.param = oaep_params = \
|
|
290
|
+
<CK_RSA_PKCS_OAEP_PARAMS *> PyMem_Malloc(paramlen)
|
|
291
|
+
|
|
292
|
+
oaep_params.source = CKZ_DATA_SPECIFIED
|
|
293
|
+
|
|
294
|
+
if param is None:
|
|
295
|
+
param = DEFAULT_MECHANISM_PARAMS[mechanism]
|
|
296
|
+
|
|
297
|
+
(oaep_params.hashAlg, oaep_params.mgf, source_data) = param
|
|
298
|
+
|
|
299
|
+
if source_data is None:
|
|
300
|
+
oaep_params.pSourceData = NULL
|
|
301
|
+
oaep_params.ulSourceDataLen = <CK_ULONG> 0
|
|
302
|
+
else:
|
|
303
|
+
oaep_params.pSourceData = <CK_BYTE *> source_data
|
|
304
|
+
oaep_params.ulSourceDataLen = <CK_ULONG> len(source_data)
|
|
305
|
+
|
|
306
|
+
elif mechanism in (Mechanism.RSA_PKCS_PSS,
|
|
307
|
+
Mechanism.SHA1_RSA_PKCS_PSS,
|
|
308
|
+
Mechanism.SHA224_RSA_PKCS_PSS,
|
|
309
|
+
Mechanism.SHA256_RSA_PKCS_PSS,
|
|
310
|
+
Mechanism.SHA384_RSA_PKCS_PSS,
|
|
311
|
+
Mechanism.SHA512_RSA_PKCS_PSS):
|
|
312
|
+
paramlen = sizeof(CK_RSA_PKCS_PSS_PARAMS)
|
|
313
|
+
self.param = pss_params = \
|
|
314
|
+
<CK_RSA_PKCS_PSS_PARAMS *> PyMem_Malloc(paramlen)
|
|
315
|
+
|
|
316
|
+
if param is None:
|
|
317
|
+
# All PSS mechanisms have the same defaults
|
|
318
|
+
param = DEFAULT_MECHANISM_PARAMS[Mechanism.RSA_PKCS_PSS]
|
|
319
|
+
|
|
320
|
+
(pss_params.hashAlg, pss_params.mgf, pss_params.sLen) = param
|
|
321
|
+
|
|
322
|
+
elif mechanism == Mechanism.EDDSA and param is not None:
|
|
323
|
+
paramlen = sizeof(CK_EDDSA_PARAMS)
|
|
324
|
+
self.param = eddsa_params = \
|
|
325
|
+
<CK_EDDSA_PARAMS *> PyMem_Malloc(paramlen)
|
|
326
|
+
(eddsa_params.phFlag, context_data) = param
|
|
327
|
+
if context_data is None:
|
|
328
|
+
eddsa_params.pContextData = NULL
|
|
329
|
+
eddsa_params.ulContextDataLen = 0
|
|
330
|
+
else:
|
|
331
|
+
eddsa_params.pContextData = context_data
|
|
332
|
+
eddsa_params.ulContextDataLen = <CK_ULONG> len(context_data)
|
|
333
|
+
|
|
334
|
+
elif mechanism in (
|
|
335
|
+
Mechanism.ECDH1_DERIVE,
|
|
336
|
+
Mechanism.ECDH1_COFACTOR_DERIVE):
|
|
337
|
+
paramlen = sizeof(CK_ECDH1_DERIVE_PARAMS)
|
|
338
|
+
self.param = ecdh1_params = \
|
|
339
|
+
<CK_ECDH1_DERIVE_PARAMS *> PyMem_Malloc(paramlen)
|
|
340
|
+
|
|
341
|
+
(ecdh1_params.kdf, shared_data, public_data) = param
|
|
342
|
+
|
|
343
|
+
if shared_data is None:
|
|
344
|
+
ecdh1_params.pSharedData = NULL
|
|
345
|
+
ecdh1_params.ulSharedDataLen = 0
|
|
346
|
+
else:
|
|
347
|
+
ecdh1_params.pSharedData = shared_data
|
|
348
|
+
ecdh1_params.ulSharedDataLen = <CK_ULONG> len(shared_data)
|
|
349
|
+
|
|
350
|
+
ecdh1_params.pPublicData = public_data
|
|
351
|
+
ecdh1_params.ulPublicDataLen = <CK_ULONG> len(public_data)
|
|
352
|
+
|
|
353
|
+
elif mechanism == Mechanism.AES_CBC_ENCRYPT_DATA:
|
|
354
|
+
paramlen = sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS)
|
|
355
|
+
self.param = aes_cbc_params = \
|
|
356
|
+
<CK_AES_CBC_ENCRYPT_DATA_PARAMS *> PyMem_Malloc(paramlen)
|
|
357
|
+
(iv, data) = param
|
|
358
|
+
aes_cbc_params.iv = iv[:16]
|
|
359
|
+
aes_cbc_params.pData = <CK_BYTE *> data
|
|
360
|
+
aes_cbc_params.length = <CK_ULONG> len(data)
|
|
361
|
+
|
|
362
|
+
elif param is None:
|
|
363
|
+
self.data.pParameter = NULL
|
|
364
|
+
paramlen = 0
|
|
365
|
+
|
|
366
|
+
else:
|
|
367
|
+
raise ArgumentsBad("Unexpected argument to mechanism_param")
|
|
368
|
+
|
|
369
|
+
self.data.mechanism = mechanism
|
|
370
|
+
self.data.ulParameterLen = <CK_ULONG> paramlen
|
|
371
|
+
|
|
372
|
+
if self.param != NULL:
|
|
373
|
+
self.data.pParameter = self.param
|
|
374
|
+
|
|
375
|
+
def __dealloc__(self):
|
|
376
|
+
PyMem_Free(self.data)
|
|
377
|
+
PyMem_Free(self.param)
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
class Slot(types.Slot):
|
|
381
|
+
"""Extend Slot with implementation."""
|
|
382
|
+
|
|
383
|
+
def get_token(self):
|
|
384
|
+
cdef CK_SLOT_ID slot_id = self.slot_id
|
|
385
|
+
cdef CK_TOKEN_INFO info
|
|
386
|
+
cdef CK_RV retval
|
|
387
|
+
|
|
388
|
+
with nogil:
|
|
389
|
+
retval = _funclist.C_GetTokenInfo(slot_id, &info)
|
|
390
|
+
assertRV(retval)
|
|
391
|
+
|
|
392
|
+
label = info.label[:sizeof(info.label)]
|
|
393
|
+
serialNumber = info.serialNumber[:sizeof(info.serialNumber)]
|
|
394
|
+
model = info.model[:sizeof(info.model)]
|
|
395
|
+
manufacturerID = info.manufacturerID[:sizeof(info.manufacturerID)]
|
|
396
|
+
|
|
397
|
+
return Token(self, label, serialNumber, model, manufacturerID,
|
|
398
|
+
info.hardwareVersion, info.firmwareVersion, info.flags)
|
|
399
|
+
|
|
400
|
+
def get_mechanisms(self):
|
|
401
|
+
cdef CK_SLOT_ID slot_id = self.slot_id
|
|
402
|
+
cdef CK_ULONG count
|
|
403
|
+
cdef CK_RV retval
|
|
404
|
+
|
|
405
|
+
with nogil:
|
|
406
|
+
retval = _funclist.C_GetMechanismList(slot_id, NULL, &count)
|
|
407
|
+
assertRV(retval)
|
|
408
|
+
|
|
409
|
+
if count == 0:
|
|
410
|
+
return set()
|
|
411
|
+
|
|
412
|
+
cdef CK_MECHANISM_TYPE [:] mechanisms = CK_ULONG_buffer(count)
|
|
413
|
+
|
|
414
|
+
with nogil:
|
|
415
|
+
retval = _funclist.C_GetMechanismList(slot_id, &mechanisms[0], &count)
|
|
416
|
+
assertRV(retval)
|
|
417
|
+
|
|
418
|
+
return set(map(_CK_MECHANISM_TYPE_to_enum, mechanisms))
|
|
419
|
+
|
|
420
|
+
def get_mechanism_info(self, mechanism):
|
|
421
|
+
cdef CK_SLOT_ID slot_id = self.slot_id
|
|
422
|
+
cdef CK_MECHANISM_TYPE mech_type = mechanism
|
|
423
|
+
cdef CK_MECHANISM_INFO info
|
|
424
|
+
cdef CK_RV retval
|
|
425
|
+
|
|
426
|
+
with nogil:
|
|
427
|
+
retval = _funclist.C_GetMechanismInfo(slot_id, mech_type, &info)
|
|
428
|
+
assertRV(retval)
|
|
429
|
+
|
|
430
|
+
return types.MechanismInfo(self, mechanism, **info)
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
class Token(types.Token):
|
|
434
|
+
"""Extend Token with implementation."""
|
|
435
|
+
|
|
436
|
+
def open(self, rw=False, user_pin=None, so_pin=None, user_type=None):
|
|
437
|
+
cdef CK_SLOT_ID slot_id = self.slot.slot_id
|
|
438
|
+
cdef CK_SESSION_HANDLE handle
|
|
439
|
+
cdef CK_FLAGS flags = CKF_SERIAL_SESSION
|
|
440
|
+
cdef CK_USER_TYPE final_user_type
|
|
441
|
+
cdef CK_UTF8CHAR *pin_data
|
|
442
|
+
cdef CK_ULONG pin_length
|
|
443
|
+
cdef CK_RV retval
|
|
444
|
+
|
|
445
|
+
if rw:
|
|
446
|
+
flags |= CKF_RW_SESSION
|
|
447
|
+
|
|
448
|
+
if user_pin is not None and so_pin is not None:
|
|
449
|
+
raise ArgumentsBad("Set either `user_pin` or `so_pin`")
|
|
450
|
+
elif user_pin is PROTECTED_AUTH:
|
|
451
|
+
pin = None
|
|
452
|
+
user_type = user_type if user_type is not None else CKU_USER
|
|
453
|
+
elif so_pin is PROTECTED_AUTH:
|
|
454
|
+
pin = None
|
|
455
|
+
user_type = CKU_SO
|
|
456
|
+
elif user_pin is not None:
|
|
457
|
+
pin = user_pin.encode('utf-8')
|
|
458
|
+
user_type = user_type if user_type is not None else CKU_USER
|
|
459
|
+
elif so_pin is not None:
|
|
460
|
+
pin = so_pin.encode('utf-8')
|
|
461
|
+
user_type = CKU_SO
|
|
462
|
+
else:
|
|
463
|
+
pin = None
|
|
464
|
+
user_type = UserType.NOBODY
|
|
465
|
+
|
|
466
|
+
final_user_type = user_type
|
|
467
|
+
with nogil:
|
|
468
|
+
retval = _funclist.C_OpenSession(slot_id, flags, NULL, NULL, &handle)
|
|
469
|
+
assertRV(retval)
|
|
470
|
+
|
|
471
|
+
if so_pin is PROTECTED_AUTH or user_pin is PROTECTED_AUTH:
|
|
472
|
+
if self.flags & TokenFlag.PROTECTED_AUTHENTICATION_PATH:
|
|
473
|
+
with nogil:
|
|
474
|
+
retval = _funclist.C_Login(handle, final_user_type, NULL, 0)
|
|
475
|
+
assertRV(retval)
|
|
476
|
+
else:
|
|
477
|
+
raise ArgumentsBad("Protected authentication is not supported by loaded module")
|
|
478
|
+
elif pin is not None:
|
|
479
|
+
pin_data = pin
|
|
480
|
+
pin_length = <CK_ULONG> len(pin)
|
|
481
|
+
|
|
482
|
+
with nogil:
|
|
483
|
+
retval = _funclist.C_Login(handle, final_user_type, pin_data, pin_length)
|
|
484
|
+
assertRV(retval)
|
|
485
|
+
|
|
486
|
+
return Session(self, handle, rw=rw, user_type=user_type)
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
class SearchIter:
|
|
490
|
+
"""Iterate a search for objects on a session."""
|
|
491
|
+
|
|
492
|
+
def __init__(self, session, attrs):
|
|
493
|
+
self.session = session
|
|
494
|
+
|
|
495
|
+
template = AttributeList(attrs)
|
|
496
|
+
self.session._operation_lock.acquire()
|
|
497
|
+
self._active = True
|
|
498
|
+
|
|
499
|
+
cdef CK_SESSION_HANDLE handle = self.session._handle
|
|
500
|
+
cdef CK_ATTRIBUTE *attr_data = template.data
|
|
501
|
+
cdef CK_ULONG attr_count = template.count
|
|
502
|
+
cdef CK_RV retval
|
|
503
|
+
|
|
504
|
+
with nogil:
|
|
505
|
+
retval = _funclist.C_FindObjectsInit(handle, attr_data, attr_count)
|
|
506
|
+
assertRV(retval)
|
|
507
|
+
|
|
508
|
+
def __iter__(self):
|
|
509
|
+
return self
|
|
510
|
+
|
|
511
|
+
def __next__(self):
|
|
512
|
+
"""Get the next object."""
|
|
513
|
+
cdef CK_SESSION_HANDLE handle = self.session._handle
|
|
514
|
+
cdef CK_OBJECT_HANDLE obj
|
|
515
|
+
cdef CK_ULONG count
|
|
516
|
+
cdef CK_RV retval
|
|
517
|
+
|
|
518
|
+
with nogil:
|
|
519
|
+
retval = _funclist.C_FindObjects(handle, &obj, 1, &count)
|
|
520
|
+
assertRV(retval)
|
|
521
|
+
|
|
522
|
+
if count == 0:
|
|
523
|
+
self._finalize()
|
|
524
|
+
raise StopIteration()
|
|
525
|
+
else:
|
|
526
|
+
return Object._make(self.session, obj)
|
|
527
|
+
|
|
528
|
+
def __del__(self):
|
|
529
|
+
"""Close the search."""
|
|
530
|
+
self._finalize()
|
|
531
|
+
|
|
532
|
+
def _finalize(self):
|
|
533
|
+
"""Finish the operation."""
|
|
534
|
+
cdef CK_SESSION_HANDLE handle = self.session._handle
|
|
535
|
+
cdef CK_RV retval
|
|
536
|
+
|
|
537
|
+
if self._active:
|
|
538
|
+
self._active = False
|
|
539
|
+
|
|
540
|
+
with nogil:
|
|
541
|
+
retval = _funclist.C_FindObjectsFinal(handle)
|
|
542
|
+
assertRV(retval)
|
|
543
|
+
|
|
544
|
+
self.session._operation_lock.release()
|
|
545
|
+
|
|
546
|
+
|
|
547
|
+
def merge_templates(default_template, *user_templates):
|
|
548
|
+
template = default_template.copy()
|
|
549
|
+
|
|
550
|
+
for user_template in user_templates:
|
|
551
|
+
if user_template is not None:
|
|
552
|
+
template.update(user_template)
|
|
553
|
+
|
|
554
|
+
return {
|
|
555
|
+
key: value
|
|
556
|
+
for key, value in template.items()
|
|
557
|
+
if value is not DEFAULT
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
|
|
561
|
+
class Session(types.Session):
|
|
562
|
+
"""Extend Session with implementation."""
|
|
563
|
+
|
|
564
|
+
def close(self):
|
|
565
|
+
cdef CK_SESSION_HANDLE handle = self._handle
|
|
566
|
+
cdef CK_RV retval
|
|
567
|
+
|
|
568
|
+
if self.user_type != UserType.NOBODY:
|
|
569
|
+
with nogil:
|
|
570
|
+
retval = _funclist.C_Logout(handle)
|
|
571
|
+
assertRV(retval)
|
|
572
|
+
|
|
573
|
+
with nogil:
|
|
574
|
+
retval = _funclist.C_CloseSession(handle)
|
|
575
|
+
assertRV(retval)
|
|
576
|
+
|
|
577
|
+
def get_objects(self, attrs=None):
|
|
578
|
+
return SearchIter(self, attrs or {})
|
|
579
|
+
|
|
580
|
+
def create_object(self, attrs):
|
|
581
|
+
template = AttributeList(attrs)
|
|
582
|
+
|
|
583
|
+
cdef CK_OBJECT_HANDLE handle = self._handle
|
|
584
|
+
cdef CK_ATTRIBUTE *attr_data = template.data
|
|
585
|
+
cdef CK_ULONG attr_count = template.count
|
|
586
|
+
cdef CK_OBJECT_HANDLE new
|
|
587
|
+
cdef CK_RV retval
|
|
588
|
+
|
|
589
|
+
with nogil:
|
|
590
|
+
retval = _funclist.C_CreateObject(handle, attr_data, attr_count, &new)
|
|
591
|
+
assertRV(retval)
|
|
592
|
+
|
|
593
|
+
return Object._make(self, new)
|
|
594
|
+
|
|
595
|
+
def create_domain_parameters(self, key_type, attrs,
|
|
596
|
+
local=False, store=False):
|
|
597
|
+
if local and store:
|
|
598
|
+
raise ArgumentsBad("Cannot set both `local` and `store`")
|
|
599
|
+
|
|
600
|
+
attrs = dict(attrs)
|
|
601
|
+
attrs[Attribute.CLASS] = ObjectClass.DOMAIN_PARAMETERS
|
|
602
|
+
attrs[Attribute.KEY_TYPE] = key_type
|
|
603
|
+
attrs[Attribute.TOKEN] = store
|
|
604
|
+
|
|
605
|
+
if local:
|
|
606
|
+
return DomainParameters(self, None, attrs)
|
|
607
|
+
else:
|
|
608
|
+
return self.create_object(attrs)
|
|
609
|
+
|
|
610
|
+
def generate_domain_parameters(self, key_type, param_length, store=False,
|
|
611
|
+
mechanism=None, mechanism_param=None,
|
|
612
|
+
template=None):
|
|
613
|
+
if not isinstance(key_type, KeyType):
|
|
614
|
+
raise ArgumentsBad("`key_type` must be KeyType.")
|
|
615
|
+
|
|
616
|
+
if not isinstance(param_length, int):
|
|
617
|
+
raise ArgumentsBad("`param_length` is the length in bits.")
|
|
618
|
+
|
|
619
|
+
mech = MechanismWithParam(
|
|
620
|
+
key_type, DEFAULT_PARAM_GENERATE_MECHANISMS,
|
|
621
|
+
mechanism, mechanism_param)
|
|
622
|
+
|
|
623
|
+
template_ = {
|
|
624
|
+
Attribute.CLASS: ObjectClass.DOMAIN_PARAMETERS,
|
|
625
|
+
Attribute.TOKEN: store,
|
|
626
|
+
Attribute.PRIME_BITS: param_length,
|
|
627
|
+
}
|
|
628
|
+
attrs = AttributeList(merge_templates(template_, template))
|
|
629
|
+
|
|
630
|
+
cdef CK_SESSION_HANDLE handle = self._handle
|
|
631
|
+
cdef CK_MECHANISM *mech_data = mech.data
|
|
632
|
+
cdef CK_ATTRIBUTE *attr_data = attrs.data
|
|
633
|
+
cdef CK_ULONG attr_count = attrs.count
|
|
634
|
+
cdef CK_OBJECT_HANDLE obj
|
|
635
|
+
cdef CK_RV retval
|
|
636
|
+
|
|
637
|
+
with nogil:
|
|
638
|
+
retval = _funclist.C_GenerateKey(handle, mech_data, attr_data, attr_count, &obj)
|
|
639
|
+
assertRV(retval)
|
|
640
|
+
|
|
641
|
+
return Object._make(self, obj)
|
|
642
|
+
|
|
643
|
+
def generate_key(self, key_type, key_length=None,
|
|
644
|
+
id=None, label=None,
|
|
645
|
+
store=False, capabilities=None,
|
|
646
|
+
mechanism=None, mechanism_param=None,
|
|
647
|
+
template=None):
|
|
648
|
+
|
|
649
|
+
if not isinstance(key_type, KeyType):
|
|
650
|
+
raise ArgumentsBad("`key_type` must be KeyType.")
|
|
651
|
+
|
|
652
|
+
if key_length is not None and not isinstance(key_length, int):
|
|
653
|
+
raise ArgumentsBad("`key_length` is the length in bits.")
|
|
654
|
+
|
|
655
|
+
if capabilities is None:
|
|
656
|
+
try:
|
|
657
|
+
capabilities = DEFAULT_KEY_CAPABILITIES[key_type]
|
|
658
|
+
except KeyError:
|
|
659
|
+
raise ArgumentsBad("No default capabilities for this key "
|
|
660
|
+
"type. Please specify `capabilities`.")
|
|
661
|
+
|
|
662
|
+
mech = MechanismWithParam(
|
|
663
|
+
key_type, DEFAULT_GENERATE_MECHANISMS,
|
|
664
|
+
mechanism, mechanism_param)
|
|
665
|
+
|
|
666
|
+
# Build attributes
|
|
667
|
+
template_ = {
|
|
668
|
+
Attribute.CLASS: ObjectClass.SECRET_KEY,
|
|
669
|
+
Attribute.ID: id or b'',
|
|
670
|
+
Attribute.LABEL: label or '',
|
|
671
|
+
Attribute.TOKEN: store,
|
|
672
|
+
Attribute.PRIVATE: True,
|
|
673
|
+
Attribute.SENSITIVE: True,
|
|
674
|
+
# Capabilities
|
|
675
|
+
Attribute.ENCRYPT: MechanismFlag.ENCRYPT & capabilities,
|
|
676
|
+
Attribute.DECRYPT: MechanismFlag.DECRYPT & capabilities,
|
|
677
|
+
Attribute.WRAP: MechanismFlag.WRAP & capabilities,
|
|
678
|
+
Attribute.UNWRAP: MechanismFlag.UNWRAP & capabilities,
|
|
679
|
+
Attribute.SIGN: MechanismFlag.SIGN & capabilities,
|
|
680
|
+
Attribute.VERIFY: MechanismFlag.VERIFY & capabilities,
|
|
681
|
+
Attribute.DERIVE: MechanismFlag.DERIVE & capabilities,
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
if key_type not in (KeyType.DES2, KeyType.DES3, KeyType.GOST28147, KeyType.SEED):
|
|
685
|
+
if key_length is None:
|
|
686
|
+
raise ArgumentsBad("Must provide `key_length'")
|
|
687
|
+
|
|
688
|
+
template_[Attribute.VALUE_LEN] = key_length // 8 # In bytes
|
|
689
|
+
|
|
690
|
+
attrs = AttributeList(merge_templates(template_, template))
|
|
691
|
+
|
|
692
|
+
cdef CK_SESSION_HANDLE handle = self._handle
|
|
693
|
+
cdef CK_MECHANISM *mech_data = mech.data
|
|
694
|
+
cdef CK_ATTRIBUTE *attr_data = attrs.data
|
|
695
|
+
cdef CK_ULONG attr_count = attrs.count
|
|
696
|
+
cdef CK_OBJECT_HANDLE key
|
|
697
|
+
|
|
698
|
+
with nogil:
|
|
699
|
+
retval = _funclist.C_GenerateKey(handle, mech_data, attr_data, attr_count, &key)
|
|
700
|
+
assertRV(retval)
|
|
701
|
+
|
|
702
|
+
return Object._make(self, key)
|
|
703
|
+
|
|
704
|
+
def _generate_keypair(self, key_type, key_length=None,
|
|
705
|
+
id=None, label=None,
|
|
706
|
+
store=False, capabilities=None,
|
|
707
|
+
mechanism=None, mechanism_param=None,
|
|
708
|
+
public_template=None, private_template=None):
|
|
709
|
+
|
|
710
|
+
if not isinstance(key_type, KeyType):
|
|
711
|
+
raise ArgumentsBad("`key_type` must be KeyType.")
|
|
712
|
+
|
|
713
|
+
if key_length is not None and not isinstance(key_length, int):
|
|
714
|
+
raise ArgumentsBad("`key_length` is the length in bits.")
|
|
715
|
+
|
|
716
|
+
if capabilities is None:
|
|
717
|
+
try:
|
|
718
|
+
capabilities = DEFAULT_KEY_CAPABILITIES[key_type]
|
|
719
|
+
except KeyError:
|
|
720
|
+
raise ArgumentsBad("No default capabilities for this key "
|
|
721
|
+
"type. Please specify `capabilities`.")
|
|
722
|
+
|
|
723
|
+
mech = MechanismWithParam(
|
|
724
|
+
key_type, DEFAULT_GENERATE_MECHANISMS,
|
|
725
|
+
mechanism, mechanism_param)
|
|
726
|
+
|
|
727
|
+
# Build attributes
|
|
728
|
+
public_template_ = {
|
|
729
|
+
Attribute.CLASS: ObjectClass.PUBLIC_KEY,
|
|
730
|
+
Attribute.ID: id or b'',
|
|
731
|
+
Attribute.LABEL: label or '',
|
|
732
|
+
Attribute.TOKEN: store,
|
|
733
|
+
# Capabilities
|
|
734
|
+
Attribute.ENCRYPT: MechanismFlag.ENCRYPT & capabilities,
|
|
735
|
+
Attribute.WRAP: MechanismFlag.WRAP & capabilities,
|
|
736
|
+
Attribute.VERIFY: MechanismFlag.VERIFY & capabilities,
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
if key_type is KeyType.RSA:
|
|
740
|
+
if key_length is None:
|
|
741
|
+
raise ArgumentsBad("Must provide `key_length'")
|
|
742
|
+
|
|
743
|
+
# Some PKCS#11 implementations don't default this, it makes sense
|
|
744
|
+
# to do it here
|
|
745
|
+
public_template_.update({
|
|
746
|
+
Attribute.PUBLIC_EXPONENT: b'\1\0\1',
|
|
747
|
+
Attribute.MODULUS_BITS: key_length,
|
|
748
|
+
})
|
|
749
|
+
|
|
750
|
+
public_attrs = AttributeList(merge_templates(public_template_, public_template))
|
|
751
|
+
|
|
752
|
+
private_template_ = {
|
|
753
|
+
Attribute.CLASS: ObjectClass.PRIVATE_KEY,
|
|
754
|
+
Attribute.ID: id or b'',
|
|
755
|
+
Attribute.LABEL: label or '',
|
|
756
|
+
Attribute.TOKEN: store,
|
|
757
|
+
Attribute.PRIVATE: True,
|
|
758
|
+
Attribute.SENSITIVE: True,
|
|
759
|
+
# Capabilities
|
|
760
|
+
Attribute.DECRYPT: MechanismFlag.DECRYPT & capabilities,
|
|
761
|
+
Attribute.UNWRAP: MechanismFlag.UNWRAP & capabilities,
|
|
762
|
+
Attribute.SIGN: MechanismFlag.SIGN & capabilities,
|
|
763
|
+
Attribute.DERIVE: MechanismFlag.DERIVE & capabilities,
|
|
764
|
+
}
|
|
765
|
+
private_attrs = AttributeList(merge_templates(private_template_, private_template))
|
|
766
|
+
|
|
767
|
+
cdef CK_SESSION_HANDLE handle = self._handle
|
|
768
|
+
cdef CK_MECHANISM *mech_data = mech.data
|
|
769
|
+
cdef CK_ATTRIBUTE *public_attr_data = public_attrs.data
|
|
770
|
+
cdef CK_ULONG public_attr_count = public_attrs.count
|
|
771
|
+
cdef CK_ATTRIBUTE *private_attr_data = private_attrs.data
|
|
772
|
+
cdef CK_ULONG private_attr_count = private_attrs.count
|
|
773
|
+
cdef CK_OBJECT_HANDLE public_key
|
|
774
|
+
cdef CK_OBJECT_HANDLE private_key
|
|
775
|
+
cdef CK_RV retval
|
|
776
|
+
|
|
777
|
+
with nogil:
|
|
778
|
+
retval = _funclist.C_GenerateKeyPair(handle, mech_data, public_attr_data, public_attr_count, private_attr_data, private_attr_count, &public_key, &private_key)
|
|
779
|
+
assertRV(retval)
|
|
780
|
+
|
|
781
|
+
return (Object._make(self, public_key),
|
|
782
|
+
Object._make(self, private_key))
|
|
783
|
+
|
|
784
|
+
def seed_random(self, seed):
|
|
785
|
+
cdef CK_SESSION_HANDLE handle = self._handle
|
|
786
|
+
cdef CK_BYTE *seed_data = seed
|
|
787
|
+
cdef CK_ULONG seed_len = <CK_ULONG> len(seed)
|
|
788
|
+
cdef CK_RV retval
|
|
789
|
+
|
|
790
|
+
with nogil:
|
|
791
|
+
retval = _funclist.C_SeedRandom(handle, seed_data, seed_len)
|
|
792
|
+
assertRV(retval)
|
|
793
|
+
|
|
794
|
+
def generate_random(self, nbits):
|
|
795
|
+
cdef CK_SESSION_HANDLE handle = self._handle
|
|
796
|
+
cdef CK_ULONG length = nbits // 8
|
|
797
|
+
cdef CK_CHAR [:] random = CK_BYTE_buffer(length)
|
|
798
|
+
cdef CK_RV retval
|
|
799
|
+
|
|
800
|
+
with nogil:
|
|
801
|
+
retval = _funclist.C_GenerateRandom(handle, &random[0], length)
|
|
802
|
+
assertRV(retval)
|
|
803
|
+
|
|
804
|
+
return bytes(random)
|
|
805
|
+
|
|
806
|
+
def _digest(self, data, mechanism=None, mechanism_param=None):
|
|
807
|
+
mech = MechanismWithParam(None, {}, mechanism, mechanism_param)
|
|
808
|
+
|
|
809
|
+
cdef CK_SESSION_HANDLE handle = self._handle
|
|
810
|
+
cdef CK_MECHANISM *mech_data = mech.data
|
|
811
|
+
cdef CK_BYTE *data_ptr = data
|
|
812
|
+
cdef CK_ULONG data_len = <CK_ULONG> len(data)
|
|
813
|
+
cdef CK_BYTE [:] digest
|
|
814
|
+
cdef CK_ULONG length
|
|
815
|
+
cdef CK_RV retval
|
|
816
|
+
|
|
817
|
+
with self._operation_lock:
|
|
818
|
+
with nogil:
|
|
819
|
+
retval = _funclist.C_DigestInit(handle, mech_data)
|
|
820
|
+
assertRV(retval)
|
|
821
|
+
|
|
822
|
+
with nogil:
|
|
823
|
+
# Run once to get the length
|
|
824
|
+
retval = _funclist.C_Digest(handle, data_ptr, data_len, NULL, &length)
|
|
825
|
+
assertRV(retval)
|
|
826
|
+
|
|
827
|
+
digest = CK_BYTE_buffer(length)
|
|
828
|
+
|
|
829
|
+
with nogil:
|
|
830
|
+
retval = _funclist.C_Digest(handle, data_ptr, data_len, &digest[0], &length)
|
|
831
|
+
assertRV(retval)
|
|
832
|
+
|
|
833
|
+
return bytes(digest[:length])
|
|
834
|
+
|
|
835
|
+
def _digest_generator(self, data, mechanism=None, mechanism_param=None):
|
|
836
|
+
mech = MechanismWithParam(None, {}, mechanism, mechanism_param)
|
|
837
|
+
|
|
838
|
+
cdef CK_SESSION_HANDLE handle = self._handle
|
|
839
|
+
cdef CK_MECHANISM *mech_data = mech.data
|
|
840
|
+
cdef CK_OBJECT_HANDLE key
|
|
841
|
+
cdef CK_BYTE *data_ptr
|
|
842
|
+
cdef CK_ULONG data_len
|
|
843
|
+
cdef CK_BYTE [:] digest
|
|
844
|
+
cdef CK_ULONG length
|
|
845
|
+
cdef CK_RV retval
|
|
846
|
+
|
|
847
|
+
with self._operation_lock:
|
|
848
|
+
with nogil:
|
|
849
|
+
retval = _funclist.C_DigestInit(handle, mech_data)
|
|
850
|
+
assertRV(retval)
|
|
851
|
+
|
|
852
|
+
for block in data:
|
|
853
|
+
if isinstance(block, types.Key):
|
|
854
|
+
key = block._handle
|
|
855
|
+
|
|
856
|
+
with nogil:
|
|
857
|
+
retval = _funclist.C_DigestKey(handle, key)
|
|
858
|
+
assertRV(retval)
|
|
859
|
+
else:
|
|
860
|
+
data_ptr = block
|
|
861
|
+
data_len = <CK_ULONG> len(block)
|
|
862
|
+
|
|
863
|
+
with nogil:
|
|
864
|
+
retval = _funclist.C_DigestUpdate(handle, data_ptr, data_len)
|
|
865
|
+
assertRV(retval)
|
|
866
|
+
|
|
867
|
+
# Run once to get the length
|
|
868
|
+
with nogil:
|
|
869
|
+
retval = _funclist.C_DigestFinal(handle, NULL, &length)
|
|
870
|
+
assertRV(retval)
|
|
871
|
+
|
|
872
|
+
digest = CK_BYTE_buffer(length)
|
|
873
|
+
|
|
874
|
+
with nogil:
|
|
875
|
+
retval = _funclist.C_DigestFinal(handle, &digest[0], &length)
|
|
876
|
+
assertRV(retval)
|
|
877
|
+
|
|
878
|
+
return bytes(digest[:length])
|
|
879
|
+
|
|
880
|
+
|
|
881
|
+
class Object(types.Object):
|
|
882
|
+
"""Expand Object with an implementation."""
|
|
883
|
+
|
|
884
|
+
@classmethod
|
|
885
|
+
def _make(cls, *args, **kwargs):
|
|
886
|
+
"""
|
|
887
|
+
Make an object with the right bases for its class and capabilities.
|
|
888
|
+
"""
|
|
889
|
+
|
|
890
|
+
# Make a version of ourselves we can introspect
|
|
891
|
+
self = cls(*args, **kwargs)
|
|
892
|
+
|
|
893
|
+
try:
|
|
894
|
+
# Determine a list of base classes to manufacture our class with
|
|
895
|
+
# FIXME: we should really request all of these attributes in
|
|
896
|
+
# one go
|
|
897
|
+
object_class = self[Attribute.CLASS]
|
|
898
|
+
bases = (_CLASS_MAP[object_class],)
|
|
899
|
+
|
|
900
|
+
# Build a list of mixins for this new class
|
|
901
|
+
for attribute, mixin in (
|
|
902
|
+
(Attribute.ENCRYPT, EncryptMixin),
|
|
903
|
+
(Attribute.DECRYPT, DecryptMixin),
|
|
904
|
+
(Attribute.SIGN, SignMixin),
|
|
905
|
+
(Attribute.VERIFY, VerifyMixin),
|
|
906
|
+
(Attribute.WRAP, WrapMixin),
|
|
907
|
+
(Attribute.UNWRAP, UnwrapMixin),
|
|
908
|
+
(Attribute.DERIVE, DeriveMixin),
|
|
909
|
+
):
|
|
910
|
+
try:
|
|
911
|
+
if self[attribute]:
|
|
912
|
+
bases += (mixin,)
|
|
913
|
+
# nFast returns FunctionFailed when you request an attribute
|
|
914
|
+
# it doesn't like.
|
|
915
|
+
except (AttributeTypeInvalid, FunctionFailed):
|
|
916
|
+
pass
|
|
917
|
+
|
|
918
|
+
bases += (cls,)
|
|
919
|
+
|
|
920
|
+
# Manufacture a class with the right capabilities.
|
|
921
|
+
klass = type(bases[0].__name__, bases, {})
|
|
922
|
+
|
|
923
|
+
return klass(*args, **kwargs)
|
|
924
|
+
|
|
925
|
+
except KeyError:
|
|
926
|
+
return self
|
|
927
|
+
|
|
928
|
+
def __getitem__(self, key):
|
|
929
|
+
cdef CK_SESSION_HANDLE handle = self.session._handle
|
|
930
|
+
cdef CK_OBJECT_HANDLE obj = self._handle
|
|
931
|
+
cdef CK_ATTRIBUTE template
|
|
932
|
+
cdef CK_RV retval
|
|
933
|
+
|
|
934
|
+
template.type = key
|
|
935
|
+
template.pValue = NULL
|
|
936
|
+
template.ulValueLen = <CK_ULONG> 0
|
|
937
|
+
|
|
938
|
+
# Find out the attribute size
|
|
939
|
+
with nogil:
|
|
940
|
+
retval = _funclist.C_GetAttributeValue(handle, obj, &template, 1)
|
|
941
|
+
if retval == CK_UNAVAILABLE_INFORMATION:
|
|
942
|
+
return None
|
|
943
|
+
assertRV(retval)
|
|
944
|
+
|
|
945
|
+
if template.ulValueLen == 0:
|
|
946
|
+
return _unpack_attributes(key, b'')
|
|
947
|
+
|
|
948
|
+
# Put a buffer of the right length in place
|
|
949
|
+
cdef CK_CHAR [:] value = CK_BYTE_buffer(template.ulValueLen)
|
|
950
|
+
template.pValue = <CK_CHAR *> &value[0]
|
|
951
|
+
|
|
952
|
+
# Request the value
|
|
953
|
+
with nogil:
|
|
954
|
+
retval = _funclist.C_GetAttributeValue(handle, obj, &template, 1)
|
|
955
|
+
if retval == CK_UNAVAILABLE_INFORMATION:
|
|
956
|
+
return None
|
|
957
|
+
assertRV(retval)
|
|
958
|
+
|
|
959
|
+
return _unpack_attributes(key, value)
|
|
960
|
+
|
|
961
|
+
def __setitem__(self, key, value):
|
|
962
|
+
cdef CK_SESSION_HANDLE handle = self.session._handle
|
|
963
|
+
cdef CK_OBJECT_HANDLE obj = self._handle
|
|
964
|
+
cdef CK_ATTRIBUTE template
|
|
965
|
+
cdef CK_RV retval
|
|
966
|
+
|
|
967
|
+
value = _pack_attribute(key, value)
|
|
968
|
+
|
|
969
|
+
template.type = key
|
|
970
|
+
template.pValue = <CK_CHAR *> value
|
|
971
|
+
template.ulValueLen = <CK_ULONG>len(value)
|
|
972
|
+
|
|
973
|
+
with nogil:
|
|
974
|
+
retval = _funclist.C_SetAttributeValue(handle, obj, &template, 1)
|
|
975
|
+
assertRV(retval)
|
|
976
|
+
|
|
977
|
+
def copy(self, attrs):
|
|
978
|
+
template = AttributeList(attrs)
|
|
979
|
+
|
|
980
|
+
cdef CK_SESSION_HANDLE handle = self.session._handle
|
|
981
|
+
cdef CK_OBJECT_HANDLE obj = self._handle
|
|
982
|
+
cdef CK_ATTRIBUTE *attr_data = template.data
|
|
983
|
+
cdef CK_ULONG attr_count = template.count
|
|
984
|
+
cdef CK_OBJECT_HANDLE new
|
|
985
|
+
cdef CK_RV retval
|
|
986
|
+
|
|
987
|
+
with nogil:
|
|
988
|
+
retval = _funclist.C_CopyObject(handle, obj, attr_data, attr_count, &new)
|
|
989
|
+
assertRV(retval)
|
|
990
|
+
|
|
991
|
+
return Object._make(self.session, new)
|
|
992
|
+
|
|
993
|
+
def destroy(self):
|
|
994
|
+
cdef CK_SESSION_HANDLE handle = self.session._handle
|
|
995
|
+
cdef CK_OBJECT_HANDLE obj = self._handle
|
|
996
|
+
cdef CK_RV retval
|
|
997
|
+
|
|
998
|
+
with nogil:
|
|
999
|
+
retval = _funclist.C_DestroyObject(handle, obj)
|
|
1000
|
+
assertRV(retval)
|
|
1001
|
+
|
|
1002
|
+
|
|
1003
|
+
class SecretKey(types.SecretKey):
|
|
1004
|
+
pass
|
|
1005
|
+
|
|
1006
|
+
|
|
1007
|
+
class PublicKey(types.PublicKey):
|
|
1008
|
+
pass
|
|
1009
|
+
|
|
1010
|
+
|
|
1011
|
+
class PrivateKey(types.PrivateKey):
|
|
1012
|
+
pass
|
|
1013
|
+
|
|
1014
|
+
|
|
1015
|
+
class DomainParameters(types.DomainParameters):
|
|
1016
|
+
def generate_keypair(self,
|
|
1017
|
+
id=None, label=None,
|
|
1018
|
+
store=False, capabilities=None,
|
|
1019
|
+
mechanism=None, mechanism_param=None,
|
|
1020
|
+
public_template=None, private_template=None):
|
|
1021
|
+
|
|
1022
|
+
if capabilities is None:
|
|
1023
|
+
try:
|
|
1024
|
+
capabilities = DEFAULT_KEY_CAPABILITIES[self.key_type]
|
|
1025
|
+
except KeyError:
|
|
1026
|
+
raise ArgumentsBad("No default capabilities for this key "
|
|
1027
|
+
"type. Please specify `capabilities`.")
|
|
1028
|
+
|
|
1029
|
+
mech = MechanismWithParam(
|
|
1030
|
+
self.key_type, DEFAULT_GENERATE_MECHANISMS,
|
|
1031
|
+
mechanism, mechanism_param)
|
|
1032
|
+
|
|
1033
|
+
# Build attributes
|
|
1034
|
+
public_template_ = {
|
|
1035
|
+
Attribute.CLASS: ObjectClass.PUBLIC_KEY,
|
|
1036
|
+
Attribute.ID: id or b'',
|
|
1037
|
+
Attribute.LABEL: label or '',
|
|
1038
|
+
Attribute.TOKEN: store,
|
|
1039
|
+
# Capabilities
|
|
1040
|
+
Attribute.ENCRYPT: MechanismFlag.ENCRYPT & capabilities,
|
|
1041
|
+
Attribute.WRAP: MechanismFlag.WRAP & capabilities,
|
|
1042
|
+
Attribute.VERIFY: MechanismFlag.VERIFY & capabilities,
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
# Copy in our domain parameters.
|
|
1046
|
+
# Not all parameters are appropriate for all domains.
|
|
1047
|
+
for attribute in (
|
|
1048
|
+
Attribute.BASE,
|
|
1049
|
+
Attribute.PRIME,
|
|
1050
|
+
Attribute.SUBPRIME,
|
|
1051
|
+
Attribute.EC_PARAMS,
|
|
1052
|
+
):
|
|
1053
|
+
try:
|
|
1054
|
+
public_template_[attribute] = self[attribute]
|
|
1055
|
+
# nFast returns FunctionFailed for parameters it doesn't like
|
|
1056
|
+
except (AttributeTypeInvalid, FunctionFailed):
|
|
1057
|
+
pass
|
|
1058
|
+
|
|
1059
|
+
public_attrs = AttributeList(merge_templates(public_template_, public_template))
|
|
1060
|
+
|
|
1061
|
+
private_template_ = {
|
|
1062
|
+
Attribute.CLASS: ObjectClass.PRIVATE_KEY,
|
|
1063
|
+
Attribute.ID: id or b'',
|
|
1064
|
+
Attribute.LABEL: label or '',
|
|
1065
|
+
Attribute.TOKEN: store,
|
|
1066
|
+
Attribute.PRIVATE: True,
|
|
1067
|
+
Attribute.SENSITIVE: True,
|
|
1068
|
+
# Capabilities
|
|
1069
|
+
Attribute.DECRYPT: MechanismFlag.DECRYPT & capabilities,
|
|
1070
|
+
Attribute.UNWRAP: MechanismFlag.UNWRAP & capabilities,
|
|
1071
|
+
Attribute.SIGN: MechanismFlag.SIGN & capabilities,
|
|
1072
|
+
Attribute.DERIVE: MechanismFlag.DERIVE & capabilities,
|
|
1073
|
+
}
|
|
1074
|
+
private_attrs = AttributeList(merge_templates(private_template_, private_template))
|
|
1075
|
+
|
|
1076
|
+
cdef CK_SESSION_HANDLE handle = self.session._handle
|
|
1077
|
+
cdef CK_MECHANISM *mech_data = mech.data
|
|
1078
|
+
cdef CK_ATTRIBUTE *public_attr_data = public_attrs.data
|
|
1079
|
+
cdef CK_ULONG public_attr_count = public_attrs.count
|
|
1080
|
+
cdef CK_ATTRIBUTE *private_attr_data = private_attrs.data
|
|
1081
|
+
cdef CK_ULONG private_attr_count = private_attrs.count
|
|
1082
|
+
cdef CK_OBJECT_HANDLE public_key
|
|
1083
|
+
cdef CK_OBJECT_HANDLE private_key
|
|
1084
|
+
cdef CK_RV retval
|
|
1085
|
+
|
|
1086
|
+
with nogil:
|
|
1087
|
+
retval = _funclist.C_GenerateKeyPair(handle, mech_data, public_attr_data, public_attr_count, private_attr_data, private_attr_count, &public_key, &private_key)
|
|
1088
|
+
assertRV(retval)
|
|
1089
|
+
|
|
1090
|
+
return (Object._make(self.session, public_key),
|
|
1091
|
+
Object._make(self.session, private_key))
|
|
1092
|
+
|
|
1093
|
+
|
|
1094
|
+
class Certificate(types.Certificate):
|
|
1095
|
+
pass
|
|
1096
|
+
|
|
1097
|
+
|
|
1098
|
+
class EncryptMixin(types.EncryptMixin):
|
|
1099
|
+
"""Expand EncryptMixin with an implementation."""
|
|
1100
|
+
|
|
1101
|
+
def _encrypt(self, data,
|
|
1102
|
+
mechanism=None, mechanism_param=None):
|
|
1103
|
+
"""
|
|
1104
|
+
Non chunking encrypt. Needed for some mechanisms.
|
|
1105
|
+
"""
|
|
1106
|
+
mech = MechanismWithParam(
|
|
1107
|
+
self.key_type, DEFAULT_ENCRYPT_MECHANISMS,
|
|
1108
|
+
mechanism, mechanism_param)
|
|
1109
|
+
|
|
1110
|
+
cdef CK_SESSION_HANDLE handle = self.session._handle
|
|
1111
|
+
cdef CK_MECHANISM *mech_data = mech.data
|
|
1112
|
+
cdef CK_OBJECT_HANDLE key = self._handle
|
|
1113
|
+
cdef CK_BYTE *data_ptr = data
|
|
1114
|
+
cdef CK_ULONG data_len = <CK_ULONG> len(data)
|
|
1115
|
+
cdef CK_BYTE [:] ciphertext
|
|
1116
|
+
cdef CK_ULONG length
|
|
1117
|
+
cdef CK_RV retval
|
|
1118
|
+
|
|
1119
|
+
with self.session._operation_lock:
|
|
1120
|
+
with nogil:
|
|
1121
|
+
retval = _funclist.C_EncryptInit(handle, mech_data, key)
|
|
1122
|
+
assertRV(retval)
|
|
1123
|
+
|
|
1124
|
+
# Call to find out the buffer length
|
|
1125
|
+
with nogil:
|
|
1126
|
+
retval = _funclist.C_Encrypt(handle, data_ptr, data_len, NULL, &length)
|
|
1127
|
+
assertRV(retval)
|
|
1128
|
+
|
|
1129
|
+
ciphertext = CK_BYTE_buffer(length)
|
|
1130
|
+
|
|
1131
|
+
with nogil:
|
|
1132
|
+
retval = _funclist.C_Encrypt(handle, data_ptr, data_len, &ciphertext[0], &length)
|
|
1133
|
+
assertRV(retval)
|
|
1134
|
+
|
|
1135
|
+
return bytes(ciphertext[:length])
|
|
1136
|
+
|
|
1137
|
+
|
|
1138
|
+
def _encrypt_generator(self, data,
|
|
1139
|
+
mechanism=None, mechanism_param=None,
|
|
1140
|
+
buffer_size=8192):
|
|
1141
|
+
"""
|
|
1142
|
+
Do chunked encryption.
|
|
1143
|
+
|
|
1144
|
+
Failing to consume the generator will raise GeneratorExit when it
|
|
1145
|
+
garbage collects. This will release the lock, but you'll still be
|
|
1146
|
+
in the middle of an operation, and all future operations will raise
|
|
1147
|
+
OperationActive, see tests/test_iterators.py:test_close_iterators().
|
|
1148
|
+
|
|
1149
|
+
FIXME: cancel the operation when we exit the generator early.
|
|
1150
|
+
"""
|
|
1151
|
+
mech = MechanismWithParam(
|
|
1152
|
+
self.key_type, DEFAULT_ENCRYPT_MECHANISMS,
|
|
1153
|
+
mechanism, mechanism_param)
|
|
1154
|
+
|
|
1155
|
+
cdef CK_SESSION_HANDLE handle = self.session._handle
|
|
1156
|
+
cdef CK_MECHANISM *mech_data = mech.data
|
|
1157
|
+
cdef CK_OBJECT_HANDLE key = self._handle
|
|
1158
|
+
cdef CK_BYTE *data_ptr
|
|
1159
|
+
cdef CK_ULONG data_len
|
|
1160
|
+
cdef CK_ULONG length
|
|
1161
|
+
cdef CK_BYTE [:] part_out = CK_BYTE_buffer(buffer_size)
|
|
1162
|
+
cdef CK_RV retval
|
|
1163
|
+
|
|
1164
|
+
with self.session._operation_lock:
|
|
1165
|
+
with nogil:
|
|
1166
|
+
retval = _funclist.C_EncryptInit(handle, mech_data, key)
|
|
1167
|
+
assertRV(retval)
|
|
1168
|
+
|
|
1169
|
+
for part_in in data:
|
|
1170
|
+
if not part_in:
|
|
1171
|
+
continue
|
|
1172
|
+
|
|
1173
|
+
data_ptr = part_in
|
|
1174
|
+
data_len = <CK_ULONG> len(part_in)
|
|
1175
|
+
length = buffer_size
|
|
1176
|
+
|
|
1177
|
+
with nogil:
|
|
1178
|
+
retval = _funclist.C_EncryptUpdate(handle, data_ptr, data_len, &part_out[0], &length)
|
|
1179
|
+
assertRV(retval)
|
|
1180
|
+
|
|
1181
|
+
yield bytes(part_out[:length])
|
|
1182
|
+
|
|
1183
|
+
# Finalize
|
|
1184
|
+
# We assume the buffer is much bigger than the block size
|
|
1185
|
+
length = buffer_size
|
|
1186
|
+
|
|
1187
|
+
with nogil:
|
|
1188
|
+
retval = _funclist.C_EncryptFinal(handle, &part_out[0], &length)
|
|
1189
|
+
assertRV(retval)
|
|
1190
|
+
|
|
1191
|
+
yield bytes(part_out[:length])
|
|
1192
|
+
|
|
1193
|
+
|
|
1194
|
+
class DecryptMixin(types.DecryptMixin):
|
|
1195
|
+
"""Expand DecryptMixin with an implementation."""
|
|
1196
|
+
|
|
1197
|
+
def _decrypt(self, data,
|
|
1198
|
+
mechanism=None, mechanism_param=None, pin=None):
|
|
1199
|
+
"""Non chunking decrypt."""
|
|
1200
|
+
mech = MechanismWithParam(
|
|
1201
|
+
self.key_type, DEFAULT_ENCRYPT_MECHANISMS,
|
|
1202
|
+
mechanism, mechanism_param)
|
|
1203
|
+
|
|
1204
|
+
cdef CK_SESSION_HANDLE handle = self.session._handle
|
|
1205
|
+
cdef CK_MECHANISM *mech_data = mech.data
|
|
1206
|
+
cdef CK_OBJECT_HANDLE key = self._handle
|
|
1207
|
+
cdef CK_BYTE *data_ptr = data
|
|
1208
|
+
cdef CK_ULONG data_len = <CK_ULONG> len(data)
|
|
1209
|
+
cdef CK_BYTE [:] plaintext
|
|
1210
|
+
cdef CK_ULONG length
|
|
1211
|
+
cdef CK_USER_TYPE user_type
|
|
1212
|
+
cdef CK_UTF8CHAR *pin_data
|
|
1213
|
+
cdef CK_ULONG pin_length
|
|
1214
|
+
cdef CK_RV retval
|
|
1215
|
+
|
|
1216
|
+
if pin is not None:
|
|
1217
|
+
pin = pin.encode('utf-8')
|
|
1218
|
+
pin_data = pin
|
|
1219
|
+
pin_length = <CK_ULONG> len(pin)
|
|
1220
|
+
user_type = CKU_CONTEXT_SPECIFIC
|
|
1221
|
+
|
|
1222
|
+
with self.session._operation_lock:
|
|
1223
|
+
with nogil:
|
|
1224
|
+
retval = _funclist.C_DecryptInit(handle, mech_data, key)
|
|
1225
|
+
assertRV(retval)
|
|
1226
|
+
|
|
1227
|
+
# Log in if pin provided
|
|
1228
|
+
if pin is not None:
|
|
1229
|
+
with nogil:
|
|
1230
|
+
retval = _funclist.C_Login(handle, user_type, pin_data, pin_length)
|
|
1231
|
+
assertRV(retval)
|
|
1232
|
+
|
|
1233
|
+
# Call to find out the buffer length
|
|
1234
|
+
with nogil:
|
|
1235
|
+
retval = _funclist.C_Decrypt(handle, data_ptr, data_len, NULL, &length)
|
|
1236
|
+
assertRV(retval)
|
|
1237
|
+
|
|
1238
|
+
plaintext = CK_BYTE_buffer(length)
|
|
1239
|
+
|
|
1240
|
+
with nogil:
|
|
1241
|
+
retval = _funclist.C_Decrypt(handle, data_ptr, data_len, &plaintext[0], &length)
|
|
1242
|
+
assertRV(retval)
|
|
1243
|
+
|
|
1244
|
+
return bytes(plaintext[:length])
|
|
1245
|
+
|
|
1246
|
+
|
|
1247
|
+
def _decrypt_generator(self, data,
|
|
1248
|
+
mechanism=None, mechanism_param=None, pin=None,
|
|
1249
|
+
buffer_size=8192):
|
|
1250
|
+
"""
|
|
1251
|
+
Chunking decrypt.
|
|
1252
|
+
|
|
1253
|
+
Failing to consume the generator will raise GeneratorExit when it
|
|
1254
|
+
garbage collects. This will release the lock, but you'll still be
|
|
1255
|
+
in the middle of an operation, and all future operations will raise
|
|
1256
|
+
OperationActive, see tests/test_iterators.py:test_close_iterators().
|
|
1257
|
+
|
|
1258
|
+
FIXME: cancel the operation when we exit the generator early.
|
|
1259
|
+
"""
|
|
1260
|
+
mech = MechanismWithParam(
|
|
1261
|
+
self.key_type, DEFAULT_ENCRYPT_MECHANISMS,
|
|
1262
|
+
mechanism, mechanism_param)
|
|
1263
|
+
|
|
1264
|
+
cdef CK_SESSION_HANDLE handle = self.session._handle
|
|
1265
|
+
cdef CK_MECHANISM *mech_data = mech.data
|
|
1266
|
+
cdef CK_OBJECT_HANDLE key = self._handle
|
|
1267
|
+
cdef CK_BYTE *data_ptr
|
|
1268
|
+
cdef CK_ULONG data_len
|
|
1269
|
+
cdef CK_ULONG length
|
|
1270
|
+
cdef CK_BYTE [:] part_out = CK_BYTE_buffer(buffer_size)
|
|
1271
|
+
cdef CK_USER_TYPE user_type
|
|
1272
|
+
cdef CK_UTF8CHAR *pin_data
|
|
1273
|
+
cdef CK_ULONG pin_length
|
|
1274
|
+
cdef CK_RV retval
|
|
1275
|
+
|
|
1276
|
+
if pin is not None:
|
|
1277
|
+
pin = pin.encode('utf-8')
|
|
1278
|
+
pin_data = pin
|
|
1279
|
+
pin_length = <CK_ULONG> len(pin)
|
|
1280
|
+
user_type = CKU_CONTEXT_SPECIFIC
|
|
1281
|
+
|
|
1282
|
+
with self.session._operation_lock:
|
|
1283
|
+
with nogil:
|
|
1284
|
+
retval = _funclist.C_DecryptInit(handle, mech_data, key)
|
|
1285
|
+
assertRV(retval)
|
|
1286
|
+
|
|
1287
|
+
# Log in if pin provided
|
|
1288
|
+
if pin is not None:
|
|
1289
|
+
with nogil:
|
|
1290
|
+
retval = _funclist.C_Login(handle, user_type, pin_data, pin_length)
|
|
1291
|
+
assertRV(retval)
|
|
1292
|
+
|
|
1293
|
+
for part_in in data:
|
|
1294
|
+
if not part_in:
|
|
1295
|
+
continue
|
|
1296
|
+
|
|
1297
|
+
data_ptr = part_in
|
|
1298
|
+
data_len = <CK_ULONG> len(part_in)
|
|
1299
|
+
length = buffer_size
|
|
1300
|
+
|
|
1301
|
+
with nogil:
|
|
1302
|
+
retval = _funclist.C_DecryptUpdate(handle, data_ptr, data_len, &part_out[0], &length)
|
|
1303
|
+
assertRV(retval)
|
|
1304
|
+
|
|
1305
|
+
yield bytes(part_out[:length])
|
|
1306
|
+
|
|
1307
|
+
# Finalize
|
|
1308
|
+
# We assume the buffer is much bigger than the block size
|
|
1309
|
+
length = buffer_size
|
|
1310
|
+
|
|
1311
|
+
with nogil:
|
|
1312
|
+
retval = _funclist.C_DecryptFinal(handle, &part_out[0], &length)
|
|
1313
|
+
assertRV(retval)
|
|
1314
|
+
|
|
1315
|
+
yield bytes(part_out[:length])
|
|
1316
|
+
|
|
1317
|
+
|
|
1318
|
+
class SignMixin(types.SignMixin):
|
|
1319
|
+
"""Expand SignMixin with an implementation."""
|
|
1320
|
+
|
|
1321
|
+
def _sign(self, data,
|
|
1322
|
+
mechanism=None, mechanism_param=None, pin=None):
|
|
1323
|
+
|
|
1324
|
+
mech = MechanismWithParam(
|
|
1325
|
+
self.key_type, DEFAULT_SIGN_MECHANISMS,
|
|
1326
|
+
mechanism, mechanism_param)
|
|
1327
|
+
|
|
1328
|
+
cdef CK_SESSION_HANDLE handle = self.session._handle
|
|
1329
|
+
cdef CK_MECHANISM *mech_data = mech.data
|
|
1330
|
+
cdef CK_OBJECT_HANDLE key = self._handle
|
|
1331
|
+
cdef CK_BYTE *data_ptr = data
|
|
1332
|
+
cdef CK_ULONG data_len = <CK_ULONG> len(data)
|
|
1333
|
+
cdef CK_BYTE [:] signature
|
|
1334
|
+
cdef CK_ULONG length
|
|
1335
|
+
cdef CK_USER_TYPE user_type
|
|
1336
|
+
cdef CK_UTF8CHAR *pin_data
|
|
1337
|
+
cdef CK_ULONG pin_length
|
|
1338
|
+
cdef CK_RV retval
|
|
1339
|
+
|
|
1340
|
+
if pin is not None:
|
|
1341
|
+
pin = pin.encode('utf-8')
|
|
1342
|
+
pin_data = pin
|
|
1343
|
+
pin_length = <CK_ULONG> len(pin)
|
|
1344
|
+
user_type = CKU_CONTEXT_SPECIFIC
|
|
1345
|
+
|
|
1346
|
+
with self.session._operation_lock:
|
|
1347
|
+
with nogil:
|
|
1348
|
+
retval = _funclist.C_SignInit(handle, mech_data, key)
|
|
1349
|
+
assertRV(retval)
|
|
1350
|
+
|
|
1351
|
+
# Log in if pin provided
|
|
1352
|
+
if pin is not None:
|
|
1353
|
+
with nogil:
|
|
1354
|
+
retval = _funclist.C_Login(handle, user_type, pin_data, pin_length)
|
|
1355
|
+
assertRV(retval)
|
|
1356
|
+
|
|
1357
|
+
# Call to find out the buffer length
|
|
1358
|
+
with nogil:
|
|
1359
|
+
retval = _funclist.C_Sign(handle, data_ptr, data_len, NULL, &length)
|
|
1360
|
+
assertRV(retval)
|
|
1361
|
+
|
|
1362
|
+
signature = CK_BYTE_buffer(length)
|
|
1363
|
+
|
|
1364
|
+
with nogil:
|
|
1365
|
+
retval = _funclist.C_Sign(handle, data_ptr, data_len, &signature[0], &length)
|
|
1366
|
+
assertRV(retval)
|
|
1367
|
+
|
|
1368
|
+
return bytes(signature[:length])
|
|
1369
|
+
|
|
1370
|
+
def _sign_generator(self, data,
|
|
1371
|
+
mechanism=None, mechanism_param=None, pin=None):
|
|
1372
|
+
|
|
1373
|
+
mech = MechanismWithParam(
|
|
1374
|
+
self.key_type, DEFAULT_SIGN_MECHANISMS,
|
|
1375
|
+
mechanism, mechanism_param)
|
|
1376
|
+
|
|
1377
|
+
cdef CK_SESSION_HANDLE handle = self.session._handle
|
|
1378
|
+
cdef CK_MECHANISM *mech_data = mech.data
|
|
1379
|
+
cdef CK_OBJECT_HANDLE key = self._handle
|
|
1380
|
+
cdef CK_BYTE *data_ptr
|
|
1381
|
+
cdef CK_ULONG data_len
|
|
1382
|
+
cdef CK_BYTE [:] signature
|
|
1383
|
+
cdef CK_ULONG length
|
|
1384
|
+
cdef CK_USER_TYPE user_type
|
|
1385
|
+
cdef CK_UTF8CHAR *pin_data
|
|
1386
|
+
cdef CK_ULONG pin_length
|
|
1387
|
+
cdef CK_RV retval
|
|
1388
|
+
|
|
1389
|
+
if pin is not None:
|
|
1390
|
+
pin = pin.encode('utf-8')
|
|
1391
|
+
pin_data = pin
|
|
1392
|
+
pin_length = <CK_ULONG> len(pin)
|
|
1393
|
+
user_type = CKU_CONTEXT_SPECIFIC
|
|
1394
|
+
|
|
1395
|
+
with self.session._operation_lock:
|
|
1396
|
+
with nogil:
|
|
1397
|
+
retval = _funclist.C_SignInit(handle, mech_data, key)
|
|
1398
|
+
assertRV(retval)
|
|
1399
|
+
|
|
1400
|
+
# Log in if pin provided
|
|
1401
|
+
if pin is not None:
|
|
1402
|
+
with nogil:
|
|
1403
|
+
retval = _funclist.C_Login(handle, user_type, pin_data, pin_length)
|
|
1404
|
+
assertRV(retval)
|
|
1405
|
+
|
|
1406
|
+
for part_in in data:
|
|
1407
|
+
if not part_in:
|
|
1408
|
+
continue
|
|
1409
|
+
|
|
1410
|
+
data_ptr = part_in
|
|
1411
|
+
data_len = <CK_ULONG> len(part_in)
|
|
1412
|
+
|
|
1413
|
+
with nogil:
|
|
1414
|
+
retval = _funclist.C_SignUpdate(handle, data_ptr, data_len)
|
|
1415
|
+
assertRV(retval)
|
|
1416
|
+
|
|
1417
|
+
# Finalize
|
|
1418
|
+
# Call to find out the buffer length
|
|
1419
|
+
with nogil:
|
|
1420
|
+
retval = _funclist.C_SignFinal(handle, NULL, &length)
|
|
1421
|
+
assertRV(retval)
|
|
1422
|
+
|
|
1423
|
+
signature = CK_BYTE_buffer(length)
|
|
1424
|
+
|
|
1425
|
+
with nogil:
|
|
1426
|
+
retval = _funclist.C_SignFinal(handle, &signature[0], &length)
|
|
1427
|
+
assertRV(retval)
|
|
1428
|
+
|
|
1429
|
+
return bytes(signature[:length])
|
|
1430
|
+
|
|
1431
|
+
|
|
1432
|
+
class VerifyMixin(types.VerifyMixin):
|
|
1433
|
+
"""Expand VerifyMixin with an implementation."""
|
|
1434
|
+
|
|
1435
|
+
def _verify(self, data, signature,
|
|
1436
|
+
mechanism=None, mechanism_param=None):
|
|
1437
|
+
|
|
1438
|
+
mech = MechanismWithParam(
|
|
1439
|
+
self.key_type, DEFAULT_SIGN_MECHANISMS,
|
|
1440
|
+
mechanism, mechanism_param)
|
|
1441
|
+
|
|
1442
|
+
cdef CK_SESSION_HANDLE handle = self.session._handle
|
|
1443
|
+
cdef CK_MECHANISM *mech_data = mech.data
|
|
1444
|
+
cdef CK_OBJECT_HANDLE key = self._handle
|
|
1445
|
+
cdef CK_BYTE *data_ptr = data
|
|
1446
|
+
cdef CK_ULONG data_len = <CK_ULONG> len(data)
|
|
1447
|
+
cdef CK_BYTE *sig_ptr = signature
|
|
1448
|
+
cdef CK_ULONG sig_len = <CK_ULONG> len(signature)
|
|
1449
|
+
cdef CK_RV retval
|
|
1450
|
+
|
|
1451
|
+
with self.session._operation_lock:
|
|
1452
|
+
with nogil:
|
|
1453
|
+
retval = _funclist.C_VerifyInit(handle, mech_data, key)
|
|
1454
|
+
assertRV(retval)
|
|
1455
|
+
|
|
1456
|
+
with nogil:
|
|
1457
|
+
retval = _funclist.C_Verify(handle, data_ptr, data_len, sig_ptr, sig_len)
|
|
1458
|
+
assertRV(retval)
|
|
1459
|
+
|
|
1460
|
+
def _verify_generator(self, data, signature,
|
|
1461
|
+
mechanism=None, mechanism_param=None):
|
|
1462
|
+
|
|
1463
|
+
mech = MechanismWithParam(
|
|
1464
|
+
self.key_type, DEFAULT_SIGN_MECHANISMS,
|
|
1465
|
+
mechanism, mechanism_param)
|
|
1466
|
+
|
|
1467
|
+
cdef CK_SESSION_HANDLE handle = self.session._handle
|
|
1468
|
+
cdef CK_MECHANISM *mech_data = mech.data
|
|
1469
|
+
cdef CK_OBJECT_HANDLE key = self._handle
|
|
1470
|
+
cdef CK_BYTE *data_ptr
|
|
1471
|
+
cdef CK_ULONG data_len
|
|
1472
|
+
cdef CK_BYTE *sig_ptr = signature
|
|
1473
|
+
cdef CK_ULONG sig_len = <CK_ULONG> len(signature)
|
|
1474
|
+
cdef CK_RV retval
|
|
1475
|
+
|
|
1476
|
+
with self.session._operation_lock:
|
|
1477
|
+
with nogil:
|
|
1478
|
+
retval = _funclist.C_VerifyInit(handle, mech_data, key)
|
|
1479
|
+
assertRV(retval)
|
|
1480
|
+
|
|
1481
|
+
for part_in in data:
|
|
1482
|
+
if not part_in:
|
|
1483
|
+
continue
|
|
1484
|
+
|
|
1485
|
+
data_ptr = part_in
|
|
1486
|
+
data_len = <CK_ULONG> len(part_in)
|
|
1487
|
+
|
|
1488
|
+
with nogil:
|
|
1489
|
+
retval = _funclist.C_VerifyUpdate(handle, data_ptr, data_len)
|
|
1490
|
+
assertRV(retval)
|
|
1491
|
+
|
|
1492
|
+
with nogil:
|
|
1493
|
+
retval = _funclist.C_VerifyFinal(handle, sig_ptr, sig_len)
|
|
1494
|
+
assertRV(retval)
|
|
1495
|
+
|
|
1496
|
+
|
|
1497
|
+
class WrapMixin(types.WrapMixin):
|
|
1498
|
+
"""Expand WrapMixin with an implementation."""
|
|
1499
|
+
|
|
1500
|
+
def wrap_key(self, key,
|
|
1501
|
+
mechanism=None, mechanism_param=None):
|
|
1502
|
+
|
|
1503
|
+
if not isinstance(key, types.Key):
|
|
1504
|
+
raise ArgumentsBad("`key` must be a Key.")
|
|
1505
|
+
|
|
1506
|
+
mech = MechanismWithParam(
|
|
1507
|
+
self.key_type, DEFAULT_WRAP_MECHANISMS,
|
|
1508
|
+
mechanism, mechanism_param)
|
|
1509
|
+
|
|
1510
|
+
cdef CK_SESSION_HANDLE handle = self.session._handle
|
|
1511
|
+
cdef CK_MECHANISM *mech_data = mech.data
|
|
1512
|
+
cdef CK_OBJECT_HANDLE wrapping_key = self._handle
|
|
1513
|
+
cdef CK_OBJECT_HANDLE key_to_wrap = key._handle
|
|
1514
|
+
cdef CK_ULONG length
|
|
1515
|
+
cdef CK_RV retval
|
|
1516
|
+
|
|
1517
|
+
# Find out how many bytes we need to allocate
|
|
1518
|
+
with nogil:
|
|
1519
|
+
retval = _funclist.C_WrapKey(handle, mech_data, wrapping_key, key_to_wrap, NULL, &length)
|
|
1520
|
+
assertRV(retval)
|
|
1521
|
+
|
|
1522
|
+
cdef CK_BYTE [:] data = CK_BYTE_buffer(length)
|
|
1523
|
+
|
|
1524
|
+
with nogil:
|
|
1525
|
+
retval = _funclist.C_WrapKey(handle, mech_data, wrapping_key, key_to_wrap, &data[0], &length)
|
|
1526
|
+
assertRV(retval)
|
|
1527
|
+
|
|
1528
|
+
return bytes(data[:length])
|
|
1529
|
+
|
|
1530
|
+
|
|
1531
|
+
class UnwrapMixin(types.UnwrapMixin):
|
|
1532
|
+
"""Expand UnwrapMixin with an implementation."""
|
|
1533
|
+
|
|
1534
|
+
def unwrap_key(self, object_class, key_type, key_data,
|
|
1535
|
+
id=None, label=None,
|
|
1536
|
+
mechanism=None, mechanism_param=None,
|
|
1537
|
+
store=False, capabilities=None,
|
|
1538
|
+
template=None):
|
|
1539
|
+
|
|
1540
|
+
if not isinstance(object_class, ObjectClass):
|
|
1541
|
+
raise ArgumentsBad("`object_class` must be ObjectClass.")
|
|
1542
|
+
|
|
1543
|
+
if not isinstance(key_type, KeyType):
|
|
1544
|
+
raise ArgumentsBad("`key_type` must be KeyType.")
|
|
1545
|
+
|
|
1546
|
+
if capabilities is None:
|
|
1547
|
+
try:
|
|
1548
|
+
capabilities = DEFAULT_KEY_CAPABILITIES[key_type]
|
|
1549
|
+
except KeyError:
|
|
1550
|
+
raise ArgumentsBad("No default capabilities for this key "
|
|
1551
|
+
"type. Please specify `capabilities`.")
|
|
1552
|
+
|
|
1553
|
+
mech = MechanismWithParam(
|
|
1554
|
+
self.key_type, DEFAULT_WRAP_MECHANISMS,
|
|
1555
|
+
mechanism, mechanism_param)
|
|
1556
|
+
|
|
1557
|
+
# Build attributes
|
|
1558
|
+
template_ = {
|
|
1559
|
+
Attribute.CLASS: object_class,
|
|
1560
|
+
Attribute.KEY_TYPE: key_type,
|
|
1561
|
+
Attribute.ID: id or b'',
|
|
1562
|
+
Attribute.LABEL: label or '',
|
|
1563
|
+
Attribute.TOKEN: store,
|
|
1564
|
+
# Capabilities
|
|
1565
|
+
Attribute.ENCRYPT: MechanismFlag.ENCRYPT & capabilities,
|
|
1566
|
+
Attribute.DECRYPT: MechanismFlag.DECRYPT & capabilities,
|
|
1567
|
+
Attribute.WRAP: MechanismFlag.WRAP & capabilities,
|
|
1568
|
+
Attribute.UNWRAP: MechanismFlag.UNWRAP & capabilities,
|
|
1569
|
+
Attribute.SIGN: MechanismFlag.SIGN & capabilities,
|
|
1570
|
+
Attribute.VERIFY: MechanismFlag.VERIFY & capabilities,
|
|
1571
|
+
Attribute.DERIVE: MechanismFlag.DERIVE & capabilities,
|
|
1572
|
+
}
|
|
1573
|
+
attrs = AttributeList(merge_templates(template_, template))
|
|
1574
|
+
|
|
1575
|
+
cdef CK_SESSION_HANDLE handle = self.session._handle
|
|
1576
|
+
cdef CK_MECHANISM *mech_data = mech.data
|
|
1577
|
+
cdef CK_OBJECT_HANDLE unwrapping_key = self._handle
|
|
1578
|
+
cdef CK_BYTE *wrapped_key_ptr = key_data
|
|
1579
|
+
cdef CK_ULONG wrapped_key_len = <CK_ULONG> len(key_data)
|
|
1580
|
+
cdef CK_ATTRIBUTE *attr_data = attrs.data
|
|
1581
|
+
cdef CK_ULONG attr_count = attrs.count
|
|
1582
|
+
cdef CK_OBJECT_HANDLE key
|
|
1583
|
+
cdef CK_RV retval
|
|
1584
|
+
|
|
1585
|
+
with nogil:
|
|
1586
|
+
retval = _funclist.C_UnwrapKey(handle, mech_data, unwrapping_key, wrapped_key_ptr, wrapped_key_len, attr_data, attr_count, &key)
|
|
1587
|
+
assertRV(retval)
|
|
1588
|
+
|
|
1589
|
+
return Object._make(self.session, key)
|
|
1590
|
+
|
|
1591
|
+
|
|
1592
|
+
class DeriveMixin(types.DeriveMixin):
|
|
1593
|
+
"""Expand DeriveMixin with an implementation."""
|
|
1594
|
+
|
|
1595
|
+
def derive_key(self, key_type, key_length,
|
|
1596
|
+
id=None, label=None,
|
|
1597
|
+
store=False, capabilities=None,
|
|
1598
|
+
mechanism=None, mechanism_param=None,
|
|
1599
|
+
template=None):
|
|
1600
|
+
|
|
1601
|
+
if not isinstance(key_type, KeyType):
|
|
1602
|
+
raise ArgumentsBad("`key_type` must be KeyType.")
|
|
1603
|
+
|
|
1604
|
+
if not isinstance(key_length, int):
|
|
1605
|
+
raise ArgumentsBad("`key_length` is the length in bits.")
|
|
1606
|
+
|
|
1607
|
+
if capabilities is None:
|
|
1608
|
+
try:
|
|
1609
|
+
capabilities = DEFAULT_KEY_CAPABILITIES[key_type]
|
|
1610
|
+
except KeyError:
|
|
1611
|
+
raise ArgumentsBad("No default capabilities for this key "
|
|
1612
|
+
"type. Please specify `capabilities`.")
|
|
1613
|
+
|
|
1614
|
+
mech = MechanismWithParam(
|
|
1615
|
+
self.key_type, DEFAULT_DERIVE_MECHANISMS,
|
|
1616
|
+
mechanism, mechanism_param)
|
|
1617
|
+
|
|
1618
|
+
# Build attributes
|
|
1619
|
+
template_ = {
|
|
1620
|
+
Attribute.CLASS: ObjectClass.SECRET_KEY,
|
|
1621
|
+
Attribute.KEY_TYPE: key_type,
|
|
1622
|
+
Attribute.ID: id or b'',
|
|
1623
|
+
Attribute.LABEL: label or '',
|
|
1624
|
+
Attribute.TOKEN: store,
|
|
1625
|
+
Attribute.VALUE_LEN: key_length // 8, # In bytes
|
|
1626
|
+
Attribute.PRIVATE: True,
|
|
1627
|
+
Attribute.SENSITIVE: True,
|
|
1628
|
+
# Capabilities
|
|
1629
|
+
Attribute.ENCRYPT: MechanismFlag.ENCRYPT & capabilities,
|
|
1630
|
+
Attribute.DECRYPT: MechanismFlag.DECRYPT & capabilities,
|
|
1631
|
+
Attribute.WRAP: MechanismFlag.WRAP & capabilities,
|
|
1632
|
+
Attribute.UNWRAP: MechanismFlag.UNWRAP & capabilities,
|
|
1633
|
+
Attribute.SIGN: MechanismFlag.SIGN & capabilities,
|
|
1634
|
+
Attribute.VERIFY: MechanismFlag.VERIFY & capabilities,
|
|
1635
|
+
Attribute.DERIVE: MechanismFlag.DERIVE & capabilities,
|
|
1636
|
+
}
|
|
1637
|
+
attrs = AttributeList(merge_templates(template_, template))
|
|
1638
|
+
|
|
1639
|
+
cdef CK_SESSION_HANDLE handle = self.session._handle
|
|
1640
|
+
cdef CK_MECHANISM *mech_data = mech.data
|
|
1641
|
+
cdef CK_OBJECT_HANDLE src_key = self._handle
|
|
1642
|
+
cdef CK_ATTRIBUTE *attr_data = attrs.data
|
|
1643
|
+
cdef CK_ULONG attr_count = attrs.count
|
|
1644
|
+
cdef CK_OBJECT_HANDLE key
|
|
1645
|
+
cdef CK_RV retval
|
|
1646
|
+
|
|
1647
|
+
with nogil:
|
|
1648
|
+
retval = _funclist.C_DeriveKey(handle, mech_data, src_key, attr_data, attr_count, &key)
|
|
1649
|
+
assertRV(retval)
|
|
1650
|
+
|
|
1651
|
+
return Object._make(self.session, key)
|
|
1652
|
+
|
|
1653
|
+
|
|
1654
|
+
_CLASS_MAP = {
|
|
1655
|
+
ObjectClass.SECRET_KEY: SecretKey,
|
|
1656
|
+
ObjectClass.PUBLIC_KEY: PublicKey,
|
|
1657
|
+
ObjectClass.PRIVATE_KEY: PrivateKey,
|
|
1658
|
+
ObjectClass.DOMAIN_PARAMETERS: DomainParameters,
|
|
1659
|
+
ObjectClass.CERTIFICATE: Certificate,
|
|
1660
|
+
}
|
|
1661
|
+
|
|
1662
|
+
cdef extern from "../extern/load_module.c":
|
|
1663
|
+
ctypedef struct P11_HANDLE:
|
|
1664
|
+
void *get_function_list_ptr
|
|
1665
|
+
|
|
1666
|
+
object p11_error()
|
|
1667
|
+
P11_HANDLE* p11_open(object path_str)
|
|
1668
|
+
int p11_close(P11_HANDLE* handle)
|
|
1669
|
+
|
|
1670
|
+
|
|
1671
|
+
|
|
1672
|
+
cdef class lib:
|
|
1673
|
+
"""
|
|
1674
|
+
Main entry point.
|
|
1675
|
+
|
|
1676
|
+
This class needs to be defined cdef, so it can't shadow a class in
|
|
1677
|
+
pkcs11.types.
|
|
1678
|
+
"""
|
|
1679
|
+
|
|
1680
|
+
cdef public str so
|
|
1681
|
+
cdef public str manufacturer_id
|
|
1682
|
+
cdef public str library_description
|
|
1683
|
+
cdef public tuple cryptoki_version
|
|
1684
|
+
cdef public tuple library_version
|
|
1685
|
+
cdef P11_HANDLE *_p11_handle
|
|
1686
|
+
|
|
1687
|
+
cdef _load_pkcs11_lib(self, so) with gil:
|
|
1688
|
+
"""Load a PKCS#11 library, and extract function calls.
|
|
1689
|
+
|
|
1690
|
+
This method will dynamically load a PKCS11 library, and attempt to
|
|
1691
|
+
resolve the symbol 'C_GetFunctionList()'. Once found, the entry point
|
|
1692
|
+
is called to populate an internal table of function pointers.
|
|
1693
|
+
|
|
1694
|
+
This is a private method, and must never be called directly.
|
|
1695
|
+
Called when a new lib class is instantiated.
|
|
1696
|
+
|
|
1697
|
+
:param so: the path to a valid PKCS#11 library
|
|
1698
|
+
:type so: str
|
|
1699
|
+
:raises: RuntimeError or PKCS11Error
|
|
1700
|
+
:rtype: None
|
|
1701
|
+
"""
|
|
1702
|
+
|
|
1703
|
+
# to keep a pointer to the C_GetFunctionList address returned by dlsym()
|
|
1704
|
+
cdef C_GetFunctionList_ptr populate_function_list
|
|
1705
|
+
cdef CK_RV retval
|
|
1706
|
+
|
|
1707
|
+
cdef P11_HANDLE *handle = p11_open(so)
|
|
1708
|
+
if handle == NULL:
|
|
1709
|
+
err = <str> p11_error()
|
|
1710
|
+
if err:
|
|
1711
|
+
raise RuntimeError(f"OS exception while loading {so}: {err}")
|
|
1712
|
+
else:
|
|
1713
|
+
raise RuntimeError(f"Unknown exception while loading {so}")
|
|
1714
|
+
populate_function_list = <C_GetFunctionList_ptr> handle.get_function_list_ptr
|
|
1715
|
+
self._p11_handle = handle
|
|
1716
|
+
|
|
1717
|
+
assertRV(populate_function_list(&_funclist))
|
|
1718
|
+
|
|
1719
|
+
|
|
1720
|
+
def __cinit__(self, so):
|
|
1721
|
+
cdef CK_RV retval
|
|
1722
|
+
self._load_pkcs11_lib(so)
|
|
1723
|
+
# at this point, _funclist contains all function pointers to the library
|
|
1724
|
+
with nogil:
|
|
1725
|
+
retval = _funclist.C_Initialize(NULL)
|
|
1726
|
+
assertRV(retval)
|
|
1727
|
+
|
|
1728
|
+
def __init__(self, so):
|
|
1729
|
+
self.so = so
|
|
1730
|
+
cdef CK_INFO info
|
|
1731
|
+
cdef CK_RV retval
|
|
1732
|
+
|
|
1733
|
+
with nogil:
|
|
1734
|
+
retval = _funclist.C_GetInfo(&info)
|
|
1735
|
+
assertRV(retval)
|
|
1736
|
+
|
|
1737
|
+
manufacturerID = info.manufacturerID[:sizeof(info.manufacturerID)]
|
|
1738
|
+
libraryDescription = info.libraryDescription[:sizeof(info.libraryDescription)]
|
|
1739
|
+
|
|
1740
|
+
self.manufacturer_id = _CK_UTF8CHAR_to_str(manufacturerID)
|
|
1741
|
+
self.library_description = _CK_UTF8CHAR_to_str(libraryDescription)
|
|
1742
|
+
self.cryptoki_version = _CK_VERSION_to_tuple(info.cryptokiVersion)
|
|
1743
|
+
self.library_version = _CK_VERSION_to_tuple(info.libraryVersion)
|
|
1744
|
+
|
|
1745
|
+
def __str__(self):
|
|
1746
|
+
return '\n'.join((
|
|
1747
|
+
"Library: %s" % self.so,
|
|
1748
|
+
"Manufacturer ID: %s" % self.manufacturer_id,
|
|
1749
|
+
"Library Description: %s" % self.library_description,
|
|
1750
|
+
"Cryptoki Version: %s.%s" % self.cryptoki_version,
|
|
1751
|
+
"Library Version: %s.%s" % self.library_version,
|
|
1752
|
+
))
|
|
1753
|
+
|
|
1754
|
+
def __repr__(self):
|
|
1755
|
+
return '<pkcs11.lib ({so})>'.format(
|
|
1756
|
+
so=self.so)
|
|
1757
|
+
|
|
1758
|
+
|
|
1759
|
+
def get_slots(self, token_present=False):
|
|
1760
|
+
"""Get all slots."""
|
|
1761
|
+
|
|
1762
|
+
cdef CK_BBOOL present = token_present
|
|
1763
|
+
cdef CK_ULONG count
|
|
1764
|
+
cdef CK_RV retval
|
|
1765
|
+
|
|
1766
|
+
with nogil:
|
|
1767
|
+
retval = _funclist.C_GetSlotList(present, NULL, &count)
|
|
1768
|
+
assertRV(retval)
|
|
1769
|
+
|
|
1770
|
+
if count == 0:
|
|
1771
|
+
return []
|
|
1772
|
+
|
|
1773
|
+
cdef CK_SLOT_ID [:] slot_list = CK_ULONG_buffer(count)
|
|
1774
|
+
|
|
1775
|
+
with nogil:
|
|
1776
|
+
retval = _funclist.C_GetSlotList(present, &slot_list[0], &count)
|
|
1777
|
+
assertRV(retval)
|
|
1778
|
+
|
|
1779
|
+
cdef CK_SLOT_ID slot_id
|
|
1780
|
+
cdef CK_SLOT_INFO info
|
|
1781
|
+
|
|
1782
|
+
slots = []
|
|
1783
|
+
|
|
1784
|
+
for slot_id in slot_list:
|
|
1785
|
+
with nogil:
|
|
1786
|
+
retval = _funclist.C_GetSlotInfo(slot_id, &info)
|
|
1787
|
+
assertRV(retval)
|
|
1788
|
+
|
|
1789
|
+
slotDescription = info.slotDescription[:sizeof(info.slotDescription)]
|
|
1790
|
+
manufacturerID = info.manufacturerID[:sizeof(info.manufacturerID)]
|
|
1791
|
+
|
|
1792
|
+
slots.append(
|
|
1793
|
+
Slot(self, slot_id, slotDescription, manufacturerID,
|
|
1794
|
+
info.hardwareVersion, info.firmwareVersion, info.flags)
|
|
1795
|
+
)
|
|
1796
|
+
|
|
1797
|
+
return slots
|
|
1798
|
+
|
|
1799
|
+
|
|
1800
|
+
def get_tokens(self,
|
|
1801
|
+
token_label=None,
|
|
1802
|
+
token_serial=None,
|
|
1803
|
+
token_flags=None,
|
|
1804
|
+
slot_flags=None,
|
|
1805
|
+
mechanisms=None):
|
|
1806
|
+
"""Search for a token matching the parameters."""
|
|
1807
|
+
|
|
1808
|
+
for slot in self.get_slots():
|
|
1809
|
+
try:
|
|
1810
|
+
token = slot.get_token()
|
|
1811
|
+
token_mechanisms = slot.get_mechanisms()
|
|
1812
|
+
|
|
1813
|
+
if token_label is not None and \
|
|
1814
|
+
token.label != token_label:
|
|
1815
|
+
continue
|
|
1816
|
+
|
|
1817
|
+
if token_serial is not None and \
|
|
1818
|
+
token.serial != token_serial:
|
|
1819
|
+
continue
|
|
1820
|
+
|
|
1821
|
+
if token_flags is not None and \
|
|
1822
|
+
not token.flags & token_flags:
|
|
1823
|
+
continue
|
|
1824
|
+
|
|
1825
|
+
if slot_flags is not None and \
|
|
1826
|
+
not slot.flags & slot_flags:
|
|
1827
|
+
continue
|
|
1828
|
+
|
|
1829
|
+
if mechanisms is not None and \
|
|
1830
|
+
set(mechanisms) not in token_mechanisms:
|
|
1831
|
+
continue
|
|
1832
|
+
|
|
1833
|
+
yield token
|
|
1834
|
+
except (TokenNotPresent, TokenNotRecognised):
|
|
1835
|
+
continue
|
|
1836
|
+
|
|
1837
|
+
def get_token(self, **kwargs):
|
|
1838
|
+
"""Get a single token."""
|
|
1839
|
+
iterator = self.get_tokens(**kwargs)
|
|
1840
|
+
|
|
1841
|
+
try:
|
|
1842
|
+
token = next(iterator)
|
|
1843
|
+
except StopIteration:
|
|
1844
|
+
raise NoSuchToken("No token matching %s" % kwargs)
|
|
1845
|
+
|
|
1846
|
+
try:
|
|
1847
|
+
next(iterator)
|
|
1848
|
+
raise MultipleTokensReturned(
|
|
1849
|
+
"More than 1 token matches %s" % kwargs)
|
|
1850
|
+
except StopIteration:
|
|
1851
|
+
return token
|
|
1852
|
+
|
|
1853
|
+
def wait_for_slot_event(self, blocking=True):
|
|
1854
|
+
cdef CK_SLOT_ID slot_id
|
|
1855
|
+
cdef CK_FLAGS flag = 0
|
|
1856
|
+
cdef CK_RV retval
|
|
1857
|
+
|
|
1858
|
+
if not blocking:
|
|
1859
|
+
flag |= CKF_DONT_BLOCK
|
|
1860
|
+
|
|
1861
|
+
with nogil:
|
|
1862
|
+
retval = _funclist.C_WaitForSlotEvent(flag, &slot_id, NULL)
|
|
1863
|
+
assertRV(retval)
|
|
1864
|
+
|
|
1865
|
+
cdef CK_SLOT_INFO info
|
|
1866
|
+
|
|
1867
|
+
with nogil:
|
|
1868
|
+
retval = _funclist.C_GetSlotInfo(slot_id, &info)
|
|
1869
|
+
assertRV(retval)
|
|
1870
|
+
|
|
1871
|
+
slotDescription = info.slotDescription[:sizeof(info.slotDescription)]
|
|
1872
|
+
manufacturerID = info.manufacturerID[:sizeof(info.manufacturerID)]
|
|
1873
|
+
|
|
1874
|
+
return Slot(self, slot_id, slotDescription, manufacturerID,
|
|
1875
|
+
info.hardwareVersion, info.firmwareVersion, info.flags)
|
|
1876
|
+
|
|
1877
|
+
def reinitialize(self):
|
|
1878
|
+
cdef CK_RV retval
|
|
1879
|
+
if _funclist != NULL:
|
|
1880
|
+
with nogil:
|
|
1881
|
+
retval = _funclist.C_Finalize(NULL)
|
|
1882
|
+
assertRV(retval)
|
|
1883
|
+
with nogil:
|
|
1884
|
+
retval = _funclist.C_Initialize(NULL)
|
|
1885
|
+
assertRV(retval)
|
|
1886
|
+
|
|
1887
|
+
def __dealloc__(self):
|
|
1888
|
+
if _funclist != NULL:
|
|
1889
|
+
with nogil:
|
|
1890
|
+
_funclist.C_Finalize(NULL)
|
|
1891
|
+
p11_close(self._p11_handle)
|