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