Package PyKCS11
[hide private]
[frames] | no frames]

Source Code for Package PyKCS11

   1  #   Copyright (C) 2006-2015 Ludovic Rousseau (ludovic.rousseau@free.fr) 
   2  #   Copyright (C) 2010 Giuseppe Amato (additions to original interface) 
   3  # 
   4  # This file is free software; you can redistribute it and/or modify it 
   5  # under the terms of the GNU General Public License as published by 
   6  # the Free Software Foundation; either version 2 of the License, or 
   7  # (at your option) any later version. 
   8  # 
   9  # This program is distributed in the hope that it will be useful, but 
  10  # WITHOUT ANY WARRANTY; without even the implied warranty of 
  11  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
  12  # General Public License for more details. 
  13  # 
  14  # You should have received a copy of the GNU General Public License 
  15  # along with this program; if not, write to the Free Software 
  16  # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA. 
  17   
  18  from __future__ import print_function 
  19   
  20  import PyKCS11.LowLevel 
  21  import os 
  22  import sys 
  23   
  24   
  25  # redefine PKCS#11 constants 
  26  CK_TRUE = PyKCS11.LowLevel.CK_TRUE 
  27  CK_FALSE = PyKCS11.LowLevel.CK_FALSE 
  28  CK_UNAVAILABLE_INFORMATION = PyKCS11.LowLevel.CK_UNAVAILABLE_INFORMATION 
  29  CK_EFFECTIVELY_INFINITE = PyKCS11.LowLevel.CK_EFFECTIVELY_INFINITE 
  30  CK_INVALID_HANDLE = PyKCS11.LowLevel.CK_INVALID_HANDLE 
  31   
  32  CKM = {} 
  33  CKR = {} 
  34  CKA = {} 
  35  CKO = {} 
  36  CKU = {} 
  37  CKK = {} 
  38  CKC = {} 
  39  CKF = {} 
  40  CKS = {} 
  41  CKG = {} 
  42  CKZ = {} 
  43   
  44  # redefine PKCS#11 constants using well known prefixes 
  45  for x in PyKCS11.LowLevel.__dict__.keys(): 
  46      if x[:4] == 'CKM_' \ 
  47        or x[:4] == 'CKR_' \ 
  48        or x[:4] == 'CKA_' \ 
  49        or x[:4] == 'CKO_' \ 
  50        or x[:4] == 'CKU_' \ 
  51        or x[:4] == 'CKK_' \ 
  52        or x[:4] == 'CKC_' \ 
  53        or x[:4] == 'CKF_' \ 
  54        or x[:4] == 'CKS_' \ 
  55        or x[:4] == 'CKG_' \ 
  56        or x[:4] == 'CKZ_': 
  57          a = "%s=PyKCS11.LowLevel.%s" % (x, x) 
  58          exec(a) 
  59          if x[3:] != "_VENDOR_DEFINED": 
  60              eval(x[:3])[eval(x)] = x  # => CKM[CKM_RSA_PKCS] = 'CKM_RSA_PKCS' 
  61              eval(x[:3])[x] = eval(x)  # => CKM['CKM_RSA_PKCS'] = CKM_RSA_PKCS 
  62   
  63  # special CKR[] values 
  64  CKR[-3] = "Unknown format" 
  65  CKR[-2] = "Unkown PKCS#11 type" 
  66  CKR[-1] = "Load" 
67 68 69 -class ckbytelist(PyKCS11.LowLevel.ckbytelist):
70 """ 71 add a __repr__() method to the LowLevel equivalent 72 """ 73
74 - def __init__(self, data=[]):
75 # default size of the vector 76 size = 0 77 if isinstance(data, int): 78 size = data 79 data = None 80 81 super(ckbytelist, self).__init__(size) 82 83 # No value to initialize 84 if data is None: 85 return 86 87 # b'abc' 88 if isinstance(data, bytes): 89 self.reserve(len(data)) 90 for x in data: 91 if sys.version_info[0] <= 2: 92 # Python 2 93 v = ord(x) 94 else: 95 # Python 3 and more 96 v = x 97 self.append(v) 98 99 # "abc" 100 elif isinstance(data, str): 101 tmp = bytes(data, "utf-8") 102 self.reserve(len(tmp)) 103 for x in tmp: 104 self.append(x) 105 106 # [141, 142, 143] 107 elif isinstance(data, list) or isinstance(data, ckbytelist): 108 self.reserve(len(data)) 109 for c in range(len(data)): 110 self.append(data[c]) 111 else: 112 raise PyKCS11.PyKCS11Error(-3, text=type(data))
113
114 - def __repr__(self):
115 """ 116 return the representation of a tuple 117 the __str__ method will use it also 118 """ 119 rep = [elt for elt in self] 120 return repr(rep)
121
122 123 -class CK_OBJECT_HANDLE(PyKCS11.LowLevel.CK_OBJECT_HANDLE):
124 """ 125 add a __repr__() method to the LowLevel equivalent 126 """ 127
128 - def __init__(self, session):
129 PyKCS11.LowLevel.CK_OBJECT_HANDLE.__init__(self) 130 self.session = session 131 pass
132
133 - def to_dict(self):
134 """ 135 convert the fields of the object into a dictionnary 136 """ 137 # all the attibutes defined by PKCS#11 138 all_attributes = PyKCS11.CKA.keys() 139 140 # only use the integer values and not the strings like 'CKM_RSA_PKCS' 141 all_attributes = [attr for attr in all_attributes if 142 isinstance(attr, int)] 143 144 # all the attributes of the object 145 attributes = self.session.getAttributeValue(self, all_attributes) 146 147 dico = dict() 148 for key, attr in zip(all_attributes, attributes): 149 if attr is None: 150 continue 151 if key == CKA_CLASS: 152 dico[PyKCS11.CKA[key]] = PyKCS11.CKO[attr] 153 elif key == CKA_CERTIFICATE_TYPE: 154 dico[PyKCS11.CKA[key]] = PyKCS11.CKC[attr] 155 elif key == CKA_KEY_TYPE: 156 dico[PyKCS11.CKA[key]] = PyKCS11.CKK[attr] 157 else: 158 dico[PyKCS11.CKA[key]] = attr 159 return dico
160
161 - def __repr__(self):
162 """ 163 text representation of the object 164 """ 165 dico = self.to_dict() 166 lines = list() 167 for key in sorted(dico.keys()): 168 lines.append("%s: %s" % (key, dico[key])) 169 return "\n".join(lines)
170
171 172 -class CkClass(object):
173 """ 174 Base class for CK_* classes 175 """ 176 177 # dictionnary of integer_value: text_value for the flags bits 178 flags_dict = dict() 179 180 # dictionnary of fields names and types 181 # type can be "pair", "flags" or "text" 182 fields = dict() 183 184 flags = 0 185
186 - def flags2text(self):
187 """ 188 parse the L{self.flags} field and create a list of "CKF_*" strings 189 corresponding to bits set in flags 190 191 @return: a list of strings 192 @rtype: list 193 """ 194 r = [] 195 for v in self.flags_dict.keys(): 196 if self.flags & v: 197 r.append(self.flags_dict[v]) 198 return r
199
200 - def to_dict(self):
201 """ 202 convert the fields of the object into a dictionnary 203 """ 204 dico = dict() 205 for field in self.fields.keys(): 206 if field == "flags": 207 dico[field] = self.flags2text() 208 else: 209 dico[field] = eval("self." + field) 210 return dico
211
212 - def __str__(self):
213 """ 214 text representation of the object 215 """ 216 dico = self.to_dict() 217 lines = list() 218 for key in sorted(dico.keys()): 219 type = self.fields[key] 220 if type == "flags": 221 lines.append("%s: %s" % (key, ", ".join(dico[key]))) 222 elif type == "pair": 223 lines.append("%s: " % key + "%d.%d" % dico[key]) 224 else: 225 lines.append("%s: %s" % (key, dico[key])) 226 return "\n".join(lines)
227
228 229 -class CK_SLOT_INFO(CkClass):
230 """ 231 matches the PKCS#11 CK_SLOT_INFO structure 232 233 @ivar slotDescription: blank padded 234 @type slotDescription: string 235 @ivar manufacturerID: blank padded 236 @type manufacturerID: string 237 @ivar flags: See L{flags2text} 238 @type flags: integer 239 @ivar hardwareVersion: 2 elements list 240 @type hardwareVersion: list 241 @ivar firmwareVersion: 2 elements list 242 @type firmwareVersion: list 243 """ 244 245 flags_dict = { 246 CKF_TOKEN_PRESENT: "CKF_TOKEN_PRESENT", 247 CKF_REMOVABLE_DEVICE: "CKF_REMOVABLE_DEVICE", 248 CKF_HW_SLOT: "CKF_HW_SLOT"} 249 250 fields = {"slotDescription": "text", 251 "manufacturerID": "text", 252 "flags": "flags", 253 "hardwareVersion": "text", 254 "firmwareVersion": "text"}
255
256 257 -class CK_INFO(CkClass):
258 """ 259 matches the PKCS#11 CK_INFO structure 260 261 @ivar cryptokiVersion: Cryptoki interface version 262 @type cryptokiVersion: integer 263 @ivar manufacturerID: blank padded 264 @type manufacturerID: string 265 @ivar flags: must be zero 266 @type flags: integer 267 @ivar libraryDescription: blank padded 268 @type libraryDescription: string 269 @ivar libraryVersion: 2 elements list 270 @type libraryVersion: list 271 """ 272 273 fields = {"cryptokiVersion": "pair", 274 "manufacturerID": "text", 275 "flags": "flags", 276 "libraryDescription": "text", 277 "libraryVersion": "pair"}
278
279 280 -class CK_SESSION_INFO(CkClass):
281 """ 282 matches the PKCS#11 CK_SESSION_INFO structure 283 284 @ivar slotID: ID of the slot that interfaces with the token 285 @type slotID: integer 286 @ivar state: state of the session 287 @type state: integer 288 @ivar flags: bit flags that define the type of session 289 @type flags: integer 290 @ivar ulDeviceError: an error code defined by the cryptographic token 291 @type ulDeviceError: integer 292 """ 293 294 flags_dict = { 295 CKF_RW_SESSION: "CKF_RW_SESSION", 296 CKF_SERIAL_SESSION: "CKF_SERIAL_SESSION", 297 } 298
299 - def state2text(self):
300 """ 301 parse the L{self.state} field and return a "CKS_*" string 302 corresponding to the state 303 304 @return: a string 305 @rtype: string 306 """ 307 return CKS[self.state]
308 309 fields = {"slotID": "text", 310 "state": "text", 311 "flags": "flags", 312 "ulDeviceError": "text"}
313
314 315 -class CK_TOKEN_INFO(CkClass):
316 """ 317 matches the PKCS#11 CK_TOKEN_INFO structure 318 319 @ivar label: blank padded 320 @type label: string 321 @ivar manufacturerID: blank padded 322 @type manufacturerID: string 323 @ivar model: string blank padded 324 @type model: string 325 @ivar serialNumber: string blank padded 326 @type serialNumber: string 327 @ivar flags: 328 @type flags: integer 329 @ivar ulMaxSessionCount: 330 @type ulMaxSessionCount: integer 331 @ivar ulSessionCount: 332 @type ulSessionCount: integer 333 @ivar ulMaxRwSessionCount: 334 @type ulMaxRwSessionCount: integer 335 @ivar ulRwSessionCount: 336 @type ulRwSessionCount: integer 337 @ivar ulMaxPinLen: 338 @type ulMaxPinLen: integer 339 @ivar ulMinPinLen: 340 @type ulMinPinLen: integer 341 @ivar ulTotalPublicMemory: 342 @type ulTotalPublicMemory: integer 343 @ivar ulFreePublicMemory: 344 @type ulFreePublicMemory: integer 345 @ivar ulTotalPrivateMemory: 346 @type ulTotalPrivateMemory: integer 347 @ivar ulFreePrivateMemory: 348 @type ulFreePrivateMemory: integer 349 @ivar hardwareVersion: 2 elements list 350 @type hardwareVersion: list 351 @ivar firmwareVersion: 2 elements list 352 @type firmwareVersion: list 353 @ivar utcTime: string 354 @type utcTime: string 355 """ 356 357 flags_dict = { 358 CKF_RNG: "CKF_RNG", 359 CKF_WRITE_PROTECTED: "CKF_WRITE_PROTECTED", 360 CKF_LOGIN_REQUIRED: "CKF_LOGIN_REQUIRED", 361 CKF_USER_PIN_INITIALIZED: "CKF_USER_PIN_INITIALIZED", 362 CKF_RESTORE_KEY_NOT_NEEDED: "CKF_RESTORE_KEY_NOT_NEEDED", 363 CKF_CLOCK_ON_TOKEN: "CKF_CLOCK_ON_TOKEN", 364 CKF_PROTECTED_AUTHENTICATION_PATH: "CKF_PROTECTED_AUTHENTICATION_PATH", 365 CKF_DUAL_CRYPTO_OPERATIONS: "CKF_DUAL_CRYPTO_OPERATIONS", 366 CKF_TOKEN_INITIALIZED: "CKF_TOKEN_INITIALIZED", 367 CKF_SECONDARY_AUTHENTICATION: "CKF_SECONDARY_AUTHENTICATION", 368 CKF_USER_PIN_COUNT_LOW: "CKF_USER_PIN_COUNT_LOW", 369 CKF_USER_PIN_FINAL_TRY: "CKF_USER_PIN_FINAL_TRY", 370 CKF_USER_PIN_LOCKED: "CKF_USER_PIN_LOCKED", 371 CKF_USER_PIN_TO_BE_CHANGED: "CKF_USER_PIN_TO_BE_CHANGED", 372 CKF_SO_PIN_COUNT_LOW: "CKF_SO_PIN_COUNT_LOW", 373 CKF_SO_PIN_FINAL_TRY: "CKF_SO_PIN_FINAL_TRY", 374 CKF_SO_PIN_LOCKED: "CKF_SO_PIN_LOCKED", 375 CKF_SO_PIN_TO_BE_CHANGED: "CKF_SO_PIN_TO_BE_CHANGED", 376 } 377 378 fields = {"label": "text", 379 "manufacturerID": "text", 380 "model": "text", 381 "serialNumber": "text", 382 "flags": "flags", 383 "ulMaxSessionCount": "text", 384 "ulSessionCount": "text", 385 "ulMaxRwSessionCount": "text", 386 "ulRwSessionCount": "text", 387 "ulMaxPinLen": "text", 388 "ulMinPinLen": "text", 389 "ulTotalPublicMemory": "text", 390 "ulFreePublicMemory": "text", 391 "ulTotalPrivateMemory": "text", 392 "ulFreePrivateMemory": "text", 393 "hardwareVersion": "pair", 394 "firmwareVersion": "pair", 395 "utcTime": "text"}
396
397 398 -class CK_MECHANISM_INFO(CkClass):
399 """ 400 matches the PKCS#11 CK_MECHANISM_INFO structure 401 402 @ivar ulMinKeySize: minimum size of the key 403 @type ulMinKeySize: integer 404 @ivar ulMaxKeySize: maximum size of the key 405 @type ulMaxKeySize: integer 406 @ivar flags: bit flags specifying mechanism capabilities 407 @type flags: integer 408 """ 409 410 flags_dict = { 411 CKF_HW: "CKF_HW", 412 CKF_ENCRYPT: "CKF_ENCRYPT", 413 CKF_DECRYPT: "CKF_DECRYPT", 414 CKF_DIGEST: "CKF_DIGEST", 415 CKF_SIGN: "CKF_SIGN", 416 CKF_SIGN_RECOVER: "CKF_SIGN_RECOVER", 417 CKF_VERIFY: "CKF_VERIFY", 418 CKF_VERIFY_RECOVER: "CKF_VERIFY_RECOVER", 419 CKF_GENERATE: "CKF_GENERATE", 420 CKF_GENERATE_KEY_PAIR: "CKF_GENERATE_KEY_PAIR", 421 CKF_WRAP: "CKF_WRAP", 422 CKF_UNWRAP: "CKF_UNWRAP", 423 CKF_DERIVE: "CKF_DERIVE", 424 CKF_EXTENSION: "CKF_EXTENSION", 425 } 426 427 fields = {"ulMinKeySize": "text", 428 "ulMaxKeySize": "text", 429 "flags": "flags"}
430
431 432 -class PyKCS11Error(Exception):
433 """ define the possible PKCS#11 error codes """ 434
435 - def __init__(self, value, text=""):
436 self.value = value 437 self.text = text
438
439 - def __str__(self):
440 """ 441 The text representation of a PKCS#11 error is something like: 442 "CKR_DEVICE_ERROR (0x00000030)" 443 """ 444 if (self.value < 0): 445 return CKR[self.value] + " (%s)" % self.text 446 else: 447 return CKR[self.value] + " (0x%08X)" % self.value
448
449 450 -class PyKCS11Lib(object):
451 """ high level PKCS#11 binding """ 452
453 - def __init__(self):
455
456 - def __del__(self):
457 if PyKCS11 and PyKCS11.__name__ and \ 458 PyKCS11.LowLevel and PyKCS11.LowLevel.__name__ and \ 459 PyKCS11.LowLevel._LowLevel and \ 460 PyKCS11.LowLevel._LowLevel.__name__: 461 self.lib.Unload()
462
463 - def load(self, pkcs11dll_filename=None, *init_string):
464 """ 465 load a PKCS#11 library 466 467 @type pkcs11dll_filename: string 468 @param pkcs11dll_filename: the library name. If this parameter 469 is not set the environment variable PYKCS11LIB is used instead 470 @return: a L{PyKCS11Lib} object 471 @raise PyKCS11Error(-1): when the load fails 472 """ 473 if pkcs11dll_filename is None: 474 pkcs11dll_filename = os.getenv("PYKCS11LIB") 475 if pkcs11dll_filename is None: 476 raise PyKCS11Error(-1, "No PKCS11 library specified (set PYKCS11LIB env variable)") 477 rv = self.lib.Load(pkcs11dll_filename) 478 if rv == 0: 479 raise PyKCS11Error(-1, pkcs11dll_filename)
480
481 - def initToken(self, slot, pin, label):
482 """ 483 C_InitToken 484 485 @param slot: slot number returned by L{getSlotList} 486 @type slot: integer 487 @param pin: SO's initial PIN 488 @param label: new label of the token 489 """ 490 rv = self.lib.C_InitToken(slot, pin, label) 491 if rv != CKR_OK: 492 raise PyKCS11Error(rv)
493
494 - def getInfo(self):
495 """ 496 C_GetInfo 497 498 @return: a L{CK_INFO} object 499 """ 500 info = PyKCS11.LowLevel.CK_INFO() 501 rv = self.lib.C_GetInfo(info) 502 if rv != CKR_OK: 503 raise PyKCS11Error(rv) 504 505 i = CK_INFO() 506 i.cryptokiVersion = (info.cryptokiVersion.major, info.cryptokiVersion.minor) 507 i.manufacturerID = info.GetManufacturerID() 508 i.flags = info.flags 509 i.libraryDescription = info.GetLibraryDescription() 510 i.libraryVersion = (info.libraryVersion.major, info.libraryVersion.minor) 511 return i
512
513 - def getSlotList(self, tokenPresent=False):
514 """ 515 C_GetSlotList 516 517 @param tokenPresent: L{False} (default) to list all slots, 518 L{True} to list only slots with present tokens 519 @type tokenPresent: bool 520 @return: a list of available slots 521 @rtype: list 522 """ 523 slotList = PyKCS11.LowLevel.ckintlist() 524 rv = self.lib.C_GetSlotList(CK_TRUE if tokenPresent else CK_FALSE, 525 slotList) 526 if rv != CKR_OK: 527 raise PyKCS11Error(rv) 528 529 s = [] 530 for x in range(len(slotList)): 531 s.append(slotList[x]) 532 return s
533
534 - def getSlotInfo(self, slot):
535 """ 536 C_GetSlotInfo 537 538 @param slot: slot number returned by L{getSlotList} 539 @type slot: integer 540 @return: a L{CK_SLOT_INFO} object 541 """ 542 slotInfo = PyKCS11.LowLevel.CK_SLOT_INFO() 543 rv = self.lib.C_GetSlotInfo(slot, slotInfo) 544 if rv != CKR_OK: 545 raise PyKCS11Error(rv) 546 547 s = CK_SLOT_INFO() 548 s.slotDescription = slotInfo.GetSlotDescription() 549 s.manufacturerID = slotInfo.GetManufacturerID() 550 s.flags = slotInfo.flags 551 s.hardwareVersion = slotInfo.GetHardwareVersion() 552 s.firmwareVersion = slotInfo.GetFirmwareVersion() 553 554 return s
555
556 - def getTokenInfo(self, slot):
557 """ 558 C_GetTokenInfo 559 560 @param slot: slot number returned by L{getSlotList} 561 @type slot: integer 562 @return: a L{CK_TOKEN_INFO} object 563 """ 564 tokeninfo = PyKCS11.LowLevel.CK_TOKEN_INFO() 565 rv = self.lib.C_GetTokenInfo(slot, tokeninfo) 566 if rv != CKR_OK: 567 raise PyKCS11Error(rv) 568 569 t = CK_TOKEN_INFO() 570 t.label = tokeninfo.GetLabel() 571 t.manufacturerID = tokeninfo.GetManufacturerID() 572 t.model = tokeninfo.GetModel() 573 t.serialNumber = tokeninfo.GetSerialNumber() 574 t.flags = tokeninfo.flags 575 t.ulMaxSessionCount = tokeninfo.ulMaxSessionCount 576 if t.ulMaxSessionCount == CK_UNAVAILABLE_INFORMATION: 577 t.ulMaxSessionCount = -1 578 t.ulSessionCount = tokeninfo.ulSessionCount 579 if t.ulSessionCount == CK_UNAVAILABLE_INFORMATION: 580 t.ulSessionCount = -1 581 t.ulMaxRwSessionCount = tokeninfo.ulMaxRwSessionCount 582 if t.ulMaxRwSessionCount == CK_UNAVAILABLE_INFORMATION: 583 t.ulMaxRwSessionCount = -1 584 t.ulRwSessionCount = tokeninfo.ulRwSessionCount 585 if t.ulRwSessionCount == CK_UNAVAILABLE_INFORMATION: 586 t.ulRwSessionCount = -1 587 t.ulMaxPinLen = tokeninfo.ulMaxPinLen 588 t.ulMinPinLen = tokeninfo.ulMinPinLen 589 t.ulTotalPublicMemory = tokeninfo.ulTotalPublicMemory 590 591 if t.ulTotalPublicMemory == CK_UNAVAILABLE_INFORMATION: 592 t.ulTotalPublicMemory = -1 593 t.ulFreePublicMemory = tokeninfo.ulFreePublicMemory 594 if t.ulFreePublicMemory == CK_UNAVAILABLE_INFORMATION: 595 t.ulFreePublicMemory = -1 596 t.ulTotalPrivateMemory = tokeninfo.ulTotalPrivateMemory 597 if t.ulTotalPrivateMemory == CK_UNAVAILABLE_INFORMATION: 598 t.ulTotalPrivateMemory = -1 599 t.ulFreePrivateMemory = tokeninfo.ulFreePrivateMemory 600 if t.ulFreePrivateMemory == CK_UNAVAILABLE_INFORMATION: 601 t.ulFreePrivateMemory = -1 602 t.hardwareVersion = (tokeninfo.hardwareVersion.major, tokeninfo.hardwareVersion.minor) 603 t.firmwareVersion = (tokeninfo.firmwareVersion.major, tokeninfo.firmwareVersion.minor) 604 t.utcTime = tokeninfo.GetUtcTime() 605 606 return t
607
608 - def openSession(self, slot, flags=0):
609 """ 610 C_OpenSession 611 612 @param slot: slot number returned by L{getSlotList} 613 @type slot: integer 614 @param flags: 0 (default), CKF_RW_SESSION for RW session 615 @type flags: integer 616 @return: a L{Session} object 617 """ 618 se = PyKCS11.LowLevel.CK_SESSION_HANDLE() 619 flags |= CKF_SERIAL_SESSION 620 rv = self.lib.C_OpenSession(slot, flags, se) 621 if rv != CKR_OK: 622 raise PyKCS11Error(rv) 623 624 return Session(self, se)
625
626 - def closeAllSessions(self, slot):
627 """ 628 C_CloseAllSessions 629 630 @param slot: slot number 631 @type slot: integer 632 """ 633 rv = self.lib.C_CloseAllSessions(slot) 634 if rv != CKR_OK: 635 raise PyKCS11Error(rv)
636
637 - def getMechanismList(self, slot):
638 """ 639 C_GetMechanismList 640 641 @param slot: slot number returned by L{getSlotList} 642 @type slot: integer 643 @return: the list of available mechanisms for a slot 644 @rtype: list 645 """ 646 mechanismList = PyKCS11.LowLevel.ckintlist() 647 rv = self.lib.C_GetMechanismList(slot, mechanismList) 648 if rv != CKR_OK: 649 raise PyKCS11Error(rv) 650 651 m = [] 652 for x in range(len(mechanismList)): 653 mechanism = mechanismList[x] 654 if mechanism >= CKM_VENDOR_DEFINED: 655 k = 'CKR_VENDOR_DEFINED_%X' % (mechanism - CKM_VENDOR_DEFINED) 656 CKM[k] = mechanism 657 CKM[mechanism] = k 658 m.append(CKM[mechanism]) 659 return m
660
661 - def getMechanismInfo(self, slot, type):
662 """ 663 C_GetMechanismInfo 664 665 @param slot: slot number returned by L{getSlotList} 666 @type slot: integer 667 @param type: a CKM_* type 668 @type type: integer 669 @return: information about a mechanism 670 @rtype: a L{CK_MECHANISM_INFO} object 671 """ 672 info = PyKCS11.LowLevel.CK_MECHANISM_INFO() 673 rv = self.lib.C_GetMechanismInfo(slot, CKM[type], info) 674 if rv != CKR_OK: 675 raise PyKCS11Error(rv) 676 677 i = CK_MECHANISM_INFO() 678 i.ulMinKeySize = info.ulMinKeySize 679 i.ulMaxKeySize = info.ulMaxKeySize 680 i.flags = info.flags 681 682 return i
683
684 - def waitForSlotEvent(self, flags=0):
685 """ 686 C_WaitForSlotEvent 687 688 @param flags: 0 (default) or CKF_DONT_BLOCK 689 @type flags: integer 690 @return: slot 691 @rtype: integer 692 """ 693 tmp = 0 694 (rv, slot) = self.lib.C_WaitForSlotEvent(flags, tmp) 695 if rv != CKR_OK: 696 raise PyKCS11Error(rv) 697 698 return slot
699
700 701 -class Mechanism(object):
702 """Wraps CK_MECHANISM""" 703
704 - def __init__(self, mechanism, param=None):
705 """ 706 @param mechanism: the mechanism to be used 707 @type mechanism: integer, any CKM_* value 708 @param param: data to be used as crypto operation parameter 709 (i.e. the IV for some algorithms) 710 @type param: string or list/tuple of bytes 711 712 @see: L{Session.decrypt}, L{Session.sign} 713 """ 714 self._mech = PyKCS11.LowLevel.CK_MECHANISM() 715 self._mech.mechanism = mechanism 716 self._param = None 717 if param: 718 self._param = ckbytelist(param) 719 self._mech.pParameter = self._param 720 self._mech.ulParameterLen = len(param)
721
722 - def to_native(self):
723 return self._mech
724 725 MechanismSHA1 = Mechanism(CKM_SHA_1, None) 726 MechanismRSAPKCS1 = Mechanism(CKM_RSA_PKCS, None) 727 MechanismRSAGENERATEKEYPAIR = Mechanism(CKM_RSA_PKCS_KEY_PAIR_GEN, None) 728 MechanismECGENERATEKEYPAIR = Mechanism(CKM_EC_KEY_PAIR_GEN, None) 729 MechanismAESGENERATEKEY = Mechanism(CKM_AES_KEY_GEN, None)
730 731 732 -class RSAOAEPMechanism(object):
733 """RSA OAEP Wrapping mechanism""" 734
735 - def __init__(self, hashAlg, mgf, label=None):
736 """ 737 @param hashAlg: the hash algorithm to use (like CKM_SHA256) 738 @param mgf: the mask generation function to use (like 739 CKG_MGF1_SHA256) 740 @param label: the (optional) label to use 741 """ 742 self._param = PyKCS11.LowLevel.CK_RSA_PKCS_OAEP_PARAMS() 743 self._param.hashAlg = hashAlg 744 self._param.mgf = mgf 745 self._source = None 746 self._param.src = CKZ_DATA_SPECIFIED 747 if label: 748 self._source = ckbytelist(label) 749 self._param.ulSourceDataLen = len(self._source) 750 else: 751 self._param.ulSourceDataLen = 0 752 self._param.pSourceData = self._source 753 self._mech = PyKCS11.LowLevel.CK_MECHANISM() 754 self._mech.mechanism = CKM_RSA_PKCS_OAEP 755 self._mech.pParameter = self._param 756 self._mech.ulParameterLen = PyKCS11.LowLevel.CK_RSA_PKCS_OAEP_PARAMS_LENGTH
757
758 - def to_native(self):
759 return self._mech
760
761 762 -class RSA_PSS_Mechanism(object):
763 """RSA PSS Wrapping mechanism""" 764
765 - def __init__(self, hashAlg, mgf, sLen):
766 """ 767 @param hashAlg: the hash algorithm to use (like CKM_SHA384) 768 @param mgf: the mask generation function to use (like 769 CKG_MGF1_SHA384) 770 @param sLen: length, in bytes, of the salt value used in the PSS 771 encoding 772 """ 773 self._param = PyKCS11.LowLevel.CK_RSA_PKCS_PSS_PARAMS() 774 self._param.hashAlg = hashAlg 775 self._param.mgf = mgf 776 self._param.sLen = sLen 777 self._mech = PyKCS11.LowLevel.CK_MECHANISM() 778 self._mech.mechanism = CKM_RSA_PKCS_PSS 779 self._mech.pParameter = self._param 780 self._mech.ulParameterLen = PyKCS11.LowLevel.CK_RSA_PKCS_PSS_PARAMS_LENGTH
781
782 - def to_native(self):
783 return self._mech
784
785 786 -class DigestSession(object):
787 - def __init__(self, lib, session, mecha):
788 self._lib = lib 789 self._session = session 790 self._mechanism = mecha.to_native() 791 rv = self._lib.C_DigestInit(self._session, self._mechanism) 792 if rv != CKR_OK: 793 raise PyKCS11Error(rv)
794
795 - def update(self, data):
796 """ 797 C_DigestUpdate 798 799 @param data: data to add to the digest 800 @type data: bytes or string 801 """ 802 data1 = ckbytelist(data) 803 rv = self._lib.C_DigestUpdate(self._session, data1) 804 if rv != CKR_OK: 805 raise PyKCS11Error(rv) 806 return self
807
808 - def digestKey(self, handle):
809 """ 810 C_DigestKey 811 812 @param handle: key handle 813 @type handle: CK_OBJECT_HANDLE 814 """ 815 rv = self._lib.C_DigestKey(self._session, handle) 816 if rv != CKR_OK: 817 raise PyKCS11Error(rv) 818 return self
819
820 - def final(self):
821 """ 822 C_DigestFinal 823 824 @return: the digest 825 @rtype: ckbytelist 826 """ 827 digest = ckbytelist() 828 # Get the size of the digest 829 rv = self._lib.C_DigestFinal(self._session, digest) 830 if rv != CKR_OK: 831 raise PyKCS11Error(rv) 832 # Get the actual digest 833 rv = self._lib.C_DigestFinal(self._session, digest) 834 if rv != CKR_OK: 835 raise PyKCS11Error(rv) 836 return digest
837
838 839 -class Session(object):
840 """ Manage L{PyKCS11Lib.openSession} objects """ 841
842 - def __init__(self, pykcs11, session):
843 """ 844 @param pykcs11: PyKCS11 library object 845 @type pykcs11: PyKCS11Lib 846 @param session: session handle 847 @type session: instance of CK_SESSION_HANDLE 848 """ 849 if not isinstance(pykcs11, PyKCS11Lib): 850 raise TypeError("pykcs11 must be a PyKCS11Lib") 851 if not isinstance(session, LowLevel.CK_SESSION_HANDLE): 852 raise TypeError("session must be a CK_SESSION_HANDLE") 853 854 # hold the PyKCS11Lib reference, so that it's not Garbage Collection'd 855 self.pykcs11 = pykcs11 856 self.session = session
857 858 @property
859 - def lib(self):
860 """ 861 Get the low level lib of the owning PyKCS11Lib 862 """ 863 return self.pykcs11.lib
864
865 - def closeSession(self):
866 """ 867 C_CloseSession 868 """ 869 rv = self.lib.C_CloseSession(self.session) 870 if rv != CKR_OK: 871 raise PyKCS11Error(rv)
872
873 - def getSessionInfo(self):
874 """ 875 C_GetSessionInfo 876 877 @return: a L{CK_SESSION_INFO} object 878 """ 879 sessioninfo = PyKCS11.LowLevel.CK_SESSION_INFO() 880 rv = self.lib.C_GetSessionInfo(self.session, sessioninfo) 881 if rv != CKR_OK: 882 raise PyKCS11Error(rv) 883 884 s = CK_SESSION_INFO() 885 s.slotID = sessioninfo.slotID 886 s.state = sessioninfo.state 887 s.flags = sessioninfo.flags 888 s.ulDeviceError = sessioninfo.ulDeviceError 889 return s
890
891 - def login(self, pin, user_type=CKU_USER):
892 """ 893 C_Login 894 895 @param pin: the user's PIN or None for CKF_PROTECTED_AUTHENTICATION_PATH 896 @type pin: string 897 @param user_type: the user type. The default value is 898 CKU_USER. You may also use CKU_SO 899 @type user_type: integer 900 """ 901 rv = self.lib.C_Login(self.session, user_type, pin) 902 if rv != CKR_OK: 903 raise PyKCS11Error(rv)
904
905 - def logout(self):
906 """ 907 C_Logout 908 """ 909 rv = self.lib.C_Logout(self.session) 910 if rv != CKR_OK: 911 raise PyKCS11Error(rv) 912 913 del self
914
915 - def initPin(self, new_pin):
916 """ 917 C_InitPIN 918 919 @param new_pin: new PIN 920 """ 921 rv = self.lib.C_InitPIN(self.session, new_pin) 922 if rv != CKR_OK: 923 raise PyKCS11Error(rv)
924
925 - def setPin(self, old_pin, new_pin):
926 """ 927 C_SetPIN 928 929 @param old_pin: old PIN 930 @param new_pin: new PIN 931 """ 932 rv = self.lib.C_SetPIN(self.session, old_pin, new_pin) 933 if rv != CKR_OK: 934 raise PyKCS11Error(rv)
935
936 - def createObject(self, template):
937 """ 938 C_CreateObject 939 940 @param template: object template 941 """ 942 attrs = self._template2ckattrlist(template) 943 handle = PyKCS11.LowLevel.CK_OBJECT_HANDLE() 944 rv = self.lib.C_CreateObject(self.session, attrs, handle) 945 if rv != PyKCS11.CKR_OK: 946 raise PyKCS11.PyKCS11Error(rv) 947 return handle
948
949 - def destroyObject(self, obj):
950 """ 951 C_DestroyObject 952 953 @param obj: object ID 954 """ 955 rv = self.lib.C_DestroyObject(self.session, obj) 956 if rv != CKR_OK: 957 raise PyKCS11Error(rv)
958
959 - def digestSession(self, mecha=MechanismSHA1):
960 """ 961 C_DigestInit/C_DigestUpdate/C_DigestKey/C_DigestFinal 962 @param mecha: the digesting mechanism to be used 963 @type mecha: L{Mechanism} instance or L{MechanismSHA1} 964 for CKM_SHA_1 965 @return: A L{DigestSession} object 966 @rtype: DigestSession 967 """ 968 return DigestSession(self.lib, self.session, mecha)
969
970 - def digest(self, data, mecha=MechanismSHA1):
971 """ 972 C_DigestInit/C_Digest 973 974 @param data: the data to be digested 975 @type data: (binary) sring or list/tuple of bytes 976 @param mecha: the digesting mechanism to be used 977 @type mecha: L{Mechanism} instance or L{MechanismSHA1} 978 for CKM_SHA_1 979 @return: the computed digest 980 @rtype: list of bytes 981 982 @note: the returned value is an istance of L{ckbytelist}. 983 You can easly convert it to a binary string with:: 984 bytes(ckbytelistDigest) 985 or, for Python 2:: 986 ''.join(chr(i) for i in ckbytelistDigest) 987 988 """ 989 digest = ckbytelist() 990 m = mecha.to_native() 991 data1 = ckbytelist(data) 992 rv = self.lib.C_DigestInit(self.session, m) 993 if rv != CKR_OK: 994 raise PyKCS11Error(rv) 995 # first call get digest size 996 rv = self.lib.C_Digest(self.session, data1, digest) 997 if rv != CKR_OK: 998 raise PyKCS11Error(rv) 999 # second call get actual digest data 1000 rv = self.lib.C_Digest(self.session, data1, digest) 1001 if rv != CKR_OK: 1002 raise PyKCS11Error(rv) 1003 return digest
1004
1005 - def sign(self, key, data, mecha=MechanismRSAPKCS1):
1006 """ 1007 C_SignInit/C_Sign 1008 1009 @param key: a key handle, obtained calling L{findObjects}. 1010 @type key: integer 1011 @param data: the data to be signed 1012 @type data: (binary) string or list/tuple of bytes 1013 @param mecha: the signing mechanism to be used 1014 @type mecha: L{Mechanism} instance or L{MechanismRSAPKCS1} 1015 for CKM_RSA_PKCS 1016 @return: the computed signature 1017 @rtype: list of bytes 1018 1019 @note: the returned value is an instance of L{ckbytelist}. 1020 You can easly convert it to a binary string with:: 1021 bytes(ckbytelistSignature) 1022 or, for Python 2:: 1023 ''.join(chr(i) for i in ckbytelistSignature) 1024 1025 """ 1026 m = mecha.to_native() 1027 signature = ckbytelist() 1028 data1 = ckbytelist(data) 1029 rv = self.lib.C_SignInit(self.session, m, key) 1030 if rv != CKR_OK: 1031 raise PyKCS11Error(rv) 1032 # first call get signature size 1033 rv = self.lib.C_Sign(self.session, data1, signature) 1034 if rv != CKR_OK: 1035 raise PyKCS11Error(rv) 1036 # second call get actual signature data 1037 rv = self.lib.C_Sign(self.session, data1, signature) 1038 if rv != CKR_OK: 1039 raise PyKCS11Error(rv) 1040 return signature
1041
1042 - def verify(self, key, data, signature, mecha=MechanismRSAPKCS1):
1043 """ 1044 C_VerifyInit/C_Verify 1045 1046 @param key: a key handle, obtained calling L{findObjects}. 1047 @type key: integer 1048 @param data: the data that was signed 1049 @type data: (binary) string or list/tuple of bytes 1050 @param signature: the signature to be verified 1051 @type signature: (binary) string or list/tuple of bytes 1052 @param mecha: the signing mechanism to be used 1053 @type mecha: L{Mechanism} instance or L{MechanismRSAPKCS1} 1054 for CKM_RSA_PKCS 1055 @return: True if signature is valid, False otherwise 1056 @rtype: bool 1057 1058 """ 1059 m = mecha.to_native() 1060 data1 = ckbytelist(data) 1061 rv = self.lib.C_VerifyInit(self.session, m, key) 1062 if rv != CKR_OK: 1063 raise PyKCS11Error(rv) 1064 rv = self.lib.C_Verify(self.session, data1, signature) 1065 if rv == CKR_OK: 1066 return True 1067 elif rv == CKR_SIGNATURE_INVALID: 1068 return False 1069 else: 1070 raise PyKCS11Error(rv)
1071
1072 - def encrypt(self, key, data, mecha=MechanismRSAPKCS1):
1073 """ 1074 C_EncryptInit/C_Encrypt 1075 1076 @param key: a key handle, obtained calling L{findObjects}. 1077 @type key: integer 1078 @param data: the data to be encrypted 1079 @type data: (binary) string or list/tuple of bytes 1080 @param mecha: the encryption mechanism to be used 1081 @type mecha: L{Mechanism} instance or L{MechanismRSAPKCS1} 1082 for CKM_RSA_PKCS 1083 @return: the encrypted data 1084 @rtype: list of bytes 1085 1086 @note: the returned value is an instance of L{ckbytelist}. 1087 You can easly convert it to a binary string with:: 1088 bytes(ckbytelistEncrypted) 1089 or, for Python 2:: 1090 ''.join(chr(i) for i in ckbytelistEncrypted) 1091 1092 """ 1093 encrypted = ckbytelist() 1094 m = mecha.to_native() 1095 data1 = ckbytelist(data) 1096 rv = self.lib.C_EncryptInit(self.session, m, key) 1097 if rv != CKR_OK: 1098 raise PyKCS11Error(rv) 1099 # first call get encrypted size 1100 rv = self.lib.C_Encrypt(self.session, data1, encrypted) 1101 if rv != CKR_OK: 1102 raise PyKCS11Error(rv) 1103 # second call get actual encrypted data 1104 rv = self.lib.C_Encrypt(self.session, data1, encrypted) 1105 if rv != CKR_OK: 1106 raise PyKCS11Error(rv) 1107 return encrypted
1108
1109 - def decrypt(self, key, data, mecha=MechanismRSAPKCS1):
1110 """ 1111 C_DecryptInit/C_Decrypt 1112 1113 @param key: a key handle, obtained calling L{findObjects}. 1114 @type key: integer 1115 @param data: the data to be decrypted 1116 @type data: (binary) string or list/tuple of bytes 1117 @param mecha: the decrypt mechanism to be used 1118 @type mecha: L{Mechanism} instance or L{MechanismRSAPKCS1} 1119 for CKM_RSA_PKCS 1120 @return: the decrypted data 1121 @rtype: list of bytes 1122 1123 @note: the returned value is an instance of L{ckbytelist}. 1124 You can easly convert it to a binary string with:: 1125 bytes(ckbytelistData) 1126 or, for Python 2:: 1127 ''.join(chr(i) for i in ckbytelistData) 1128 1129 """ 1130 m = mecha.to_native() 1131 decrypted = ckbytelist() 1132 data1 = ckbytelist(data) 1133 rv = self.lib.C_DecryptInit(self.session, m, key) 1134 if rv != CKR_OK: 1135 raise PyKCS11Error(rv) 1136 # first call get decrypted size 1137 rv = self.lib.C_Decrypt(self.session, data1, decrypted) 1138 if rv != CKR_OK: 1139 raise PyKCS11Error(rv) 1140 # second call get actual decrypted data 1141 rv = self.lib.C_Decrypt(self.session, data1, decrypted) 1142 if rv != CKR_OK: 1143 raise PyKCS11Error(rv) 1144 return decrypted
1145
1146 - def wrapKey(self, wrappingKey, key, mecha=MechanismRSAPKCS1):
1147 """ 1148 C_WrapKey 1149 1150 @param wrappingKey: a wrapping key handle 1151 @type wrappingKey: integer 1152 @param key: a handle of the key to be wrapped 1153 @type key: integer 1154 @param mecha: the encrypt mechanism to be used 1155 @type mecha: L{Mechanism} instance or L{MechanismRSAPKCS1} 1156 for CKM_RSA_PKCS 1157 @return: the wrapped key bytes 1158 @rtype: list of bytes 1159 1160 @note: the returned value is an instance of L{ckbytelist}. 1161 You can easily convert it to a binary string with:: 1162 bytes(ckbytelistData) 1163 or, for Python 2:: 1164 ''.join(chr(i) for i in ckbytelistData) 1165 1166 """ 1167 wrapped = ckbytelist() 1168 native = mecha.to_native() 1169 # first call get wrapped size 1170 rv = self.lib.C_WrapKey(self.session, native, wrappingKey, key, wrapped) 1171 if rv != CKR_OK: 1172 raise PyKCS11Error(rv) 1173 # second call get actual wrapped key data 1174 rv = self.lib.C_WrapKey(self.session, native, wrappingKey, key, wrapped) 1175 if rv != CKR_OK: 1176 raise PyKCS11Error(rv) 1177 return wrapped
1178
1179 - def unwrapKey(self, unwrappingKey, wrappedKey, template, mecha=MechanismRSAPKCS1):
1180 """ 1181 C_UnwrapKey 1182 1183 @param unwrappingKey: the unwrapping key handle 1184 @type unwrappingKey: integer 1185 @param wrappedKey: the bytes of the wrapped key 1186 @type wrappedKey: (binary) string or list/tuple of bytes 1187 @param template: template for the unwrapped key 1188 @param mecha: the decrypt mechanism to be used 1189 @type mecha: L{Mechanism} instance or L{MechanismRSAPKCS1} 1190 for CKM_RSA_PKCS 1191 @return: the unwrapped key object 1192 @rtype: integer 1193 1194 """ 1195 m = mecha.to_native() 1196 data1 = ckbytelist(wrappedKey) 1197 handle = PyKCS11.LowLevel.CK_OBJECT_HANDLE() 1198 attrs = self._template2ckattrlist(template) 1199 rv = self.lib.C_UnwrapKey(self.session, m, unwrappingKey, data1, attrs, handle) 1200 if rv != CKR_OK: 1201 raise PyKCS11Error(rv) 1202 return handle
1203
1204 - def isNum(self, type):
1205 """ 1206 is the type a numerical value? 1207 1208 @param type: PKCS#11 type like CKA_CERTIFICATE_TYPE 1209 @rtype: bool 1210 """ 1211 if type in (CKA_CERTIFICATE_TYPE, 1212 CKA_CLASS, 1213 CKA_KEY_GEN_MECHANISM, 1214 CKA_KEY_TYPE, 1215 CKA_MODULUS_BITS, 1216 CKA_VALUE_BITS, 1217 CKA_VALUE_LEN): 1218 return True 1219 return False
1220
1221 - def isString(self, type):
1222 """ 1223 is the type a string value? 1224 1225 @param type: PKCS#11 type like CKA_LABEL 1226 @rtype: bool 1227 """ 1228 if type in (CKA_LABEL, 1229 CKA_APPLICATION): 1230 return True 1231 return False
1232
1233 - def isBool(self, type):
1234 """ 1235 is the type a boolean value? 1236 1237 @param type: PKCS#11 type like CKA_ALWAYS_SENSITIVE 1238 @rtype: bool 1239 """ 1240 if type in (CKA_ALWAYS_SENSITIVE, 1241 CKA_DECRYPT, 1242 CKA_DERIVE, 1243 CKA_ENCRYPT, 1244 CKA_EXTRACTABLE, 1245 CKA_HAS_RESET, 1246 CKA_LOCAL, 1247 CKA_MODIFIABLE, 1248 CKA_NEVER_EXTRACTABLE, 1249 CKA_PRIVATE, 1250 CKA_RESET_ON_INIT, 1251 CKA_SECONDARY_AUTH, 1252 CKA_SENSITIVE, 1253 CKA_SIGN, 1254 CKA_SIGN_RECOVER, 1255 CKA_TOKEN, 1256 CKA_TRUSTED, 1257 CKA_UNWRAP, 1258 CKA_VERIFY, 1259 CKA_VERIFY_RECOVER, 1260 CKA_WRAP, 1261 CKA_WRAP_WITH_TRUSTED): 1262 return True 1263 return False
1264
1265 - def isBin(self, type):
1266 """ 1267 is the type a byte array value? 1268 1269 @param type: PKCS#11 type like CKA_MODULUS 1270 @rtype: bool 1271 """ 1272 return (not self.isBool(type)) and (not self.isString(type)) and (not self.isNum(type))
1273
1274 - def _template2ckattrlist(self, template):
1275 t = PyKCS11.LowLevel.ckattrlist(len(template)) 1276 for x in range(len(template)): 1277 attr = template[x] 1278 if self.isNum(attr[0]): 1279 t[x].SetNum(attr[0], int(attr[1])) 1280 elif self.isString(attr[0]): 1281 t[x].SetString(attr[0], str(attr[1])) 1282 elif self.isBool(attr[0]): 1283 t[x].SetBool(attr[0], attr[1] == CK_TRUE) 1284 elif self.isBin(attr[0]): 1285 attrBin = attr[1] 1286 attrStr = attr[1] 1287 if isinstance(attr[1], int): 1288 attrStr = str(attr[1]) 1289 if isinstance(attr[1], bytes): 1290 attrBin = ckbytelist(attrStr) 1291 t[x].SetBin(attr[0], attrBin) 1292 else: 1293 raise PyKCS11Error(-2) 1294 return t
1295
1296 - def generateKey(self, template, mecha=MechanismAESGENERATEKEY):
1297 """ 1298 generate a secret key 1299 1300 @param template: template for the secret key 1301 @param mecha: mechanism to use 1302 @return: handle of the generated key 1303 @rtype: PyKCS11.LowLevel.CK_OBJECT_HANDLE 1304 """ 1305 t = self._template2ckattrlist(template) 1306 ck_handle = PyKCS11.LowLevel.CK_OBJECT_HANDLE() 1307 m = mecha.to_native() 1308 rv = self.lib.C_GenerateKey(self.session, m, t, ck_handle) 1309 if rv != CKR_OK: 1310 raise PyKCS11Error(rv) 1311 return ck_handle
1312
1313 - def generateKeyPair(self, templatePub, templatePriv, mecha=MechanismRSAGENERATEKEYPAIR):
1314 """ 1315 generate a key pair 1316 1317 @param templatePub: template for the public key 1318 @param templatePriv: template for the private key 1319 @param mecha: mechanism to use 1320 @return: a tuple of handles (pub, priv) 1321 @rtype: tuple 1322 """ 1323 tPub = self._template2ckattrlist(templatePub) 1324 tPriv = self._template2ckattrlist(templatePriv) 1325 ck_pub_handle = PyKCS11.LowLevel.CK_OBJECT_HANDLE() 1326 ck_prv_handle = PyKCS11.LowLevel.CK_OBJECT_HANDLE() 1327 m = mecha.to_native() 1328 rv = self.lib.C_GenerateKeyPair(self.session, m, tPub, tPriv, 1329 ck_pub_handle, ck_prv_handle) 1330 1331 if rv != CKR_OK: 1332 raise PyKCS11Error(rv) 1333 return ck_pub_handle, ck_prv_handle
1334
1335 - def findObjects(self, template=()):
1336 """ 1337 find the objects matching the template pattern 1338 1339 @param template: list of attributes tuples (attribute,value). 1340 The default value is () and all the objects are returned 1341 @type template: list 1342 @return: a list of object ids 1343 @rtype: list 1344 """ 1345 t = self._template2ckattrlist(template) 1346 1347 # we search for 10 objects by default. speed/memory tradeoff 1348 result = PyKCS11.LowLevel.ckobjlist(10) 1349 1350 rv = self.lib.C_FindObjectsInit(self.session, t) 1351 if rv != CKR_OK: 1352 raise PyKCS11Error(rv) 1353 1354 res = [] 1355 while True: 1356 rv = self.lib.C_FindObjects(self.session, result) 1357 if rv != CKR_OK: 1358 raise PyKCS11Error(rv) 1359 for x in result: 1360 # make a copy of the handle: the original value get 1361 # corrupted (!!) 1362 a = CK_OBJECT_HANDLE(self) 1363 a.assign(x.value()) 1364 res.append(a) 1365 if len(result) == 0: 1366 break 1367 1368 rv = self.lib.C_FindObjectsFinal(self.session) 1369 if rv != CKR_OK: 1370 raise PyKCS11Error(rv) 1371 return res
1372
1373 - def getAttributeValue(self, obj_id, attr, allAsBinary=False):
1374 """ 1375 C_GetAttributeValue 1376 1377 @param obj_id: object ID returned by L{findObjects} 1378 @type obj_id: integer 1379 @param attr: list of attributes 1380 @type attr: list 1381 @param allAsBinary: return all values as binary data; default is False. 1382 @type allAsBinary: Boolean 1383 @return: a list of values corresponding to the list of attributes 1384 @rtype: list 1385 1386 @see: L{getAttributeValue_fragmented} 1387 1388 @note: if allAsBinary is True the function do not convert results to 1389 Python types (i.e.: CKA_TOKEN to Bool, CKA_CLASS to int, ...). 1390 1391 Binary data is returned as L{ckbytelist} type, usable 1392 as a list containing only bytes. 1393 You can easly convert it to a binary string with:: 1394 bytes(ckbytelistVariable) 1395 or, for Python 2:: 1396 ''.join(chr(i) for i in ckbytelistVariable) 1397 1398 """ 1399 valTemplate = PyKCS11.LowLevel.ckattrlist(len(attr)) 1400 for x in range(len(attr)): 1401 valTemplate[x].SetType(attr[x]) 1402 # first call to get the attribute size and reserve the memory 1403 rv = self.lib.C_GetAttributeValue(self.session, obj_id, valTemplate) 1404 if rv in (CKR_ATTRIBUTE_TYPE_INVALID, CKR_ATTRIBUTE_SENSITIVE, 1405 CKR_ARGUMENTS_BAD): 1406 return self.getAttributeValue_fragmented(obj_id, attr, allAsBinary) 1407 1408 if rv != CKR_OK: 1409 raise PyKCS11Error(rv) 1410 # second call to get the attribute value 1411 rv = self.lib.C_GetAttributeValue(self.session, obj_id, valTemplate) 1412 if rv != CKR_OK: 1413 raise PyKCS11Error(rv) 1414 1415 res = [] 1416 for x in range(len(attr)): 1417 if (allAsBinary): 1418 res.append(valTemplate[x].GetBin()) 1419 elif valTemplate[x].IsNum(): 1420 res.append(valTemplate[x].GetNum()) 1421 elif valTemplate[x].IsBool(): 1422 res.append(valTemplate[x].GetBool()) 1423 elif valTemplate[x].IsString(): 1424 res.append(valTemplate[x].GetString()) 1425 elif valTemplate[x].IsBin(): 1426 res.append(valTemplate[x].GetBin()) 1427 else: 1428 raise PyKCS11Error(-2) 1429 1430 return res
1431
1432 - def getAttributeValue_fragmented(self, obj_id, attr, allAsBinary=False):
1433 """ 1434 Same as L{getAttributeValue} except that when some attribute 1435 is sensitive or unknown an empty value (None) is returned. 1436 1437 Note: this is achived by getting attributes one by one. 1438 1439 @see: L{getAttributeValue} 1440 """ 1441 # some attributes does not exists or is sensitive 1442 # but we don't know which ones. So try one by one 1443 valTemplate = PyKCS11.LowLevel.ckattrlist(1) 1444 res = [] 1445 for x in range(len(attr)): 1446 valTemplate[0].Reset() 1447 valTemplate[0].SetType(attr[x]) 1448 # first call to get the attribute size and reserve the memory 1449 rv = self.lib.C_GetAttributeValue(self.session, obj_id, valTemplate) 1450 if rv in (CKR_ATTRIBUTE_TYPE_INVALID, 1451 CKR_ATTRIBUTE_SENSITIVE, CKR_ARGUMENTS_BAD): 1452 # append an empty value 1453 res.append(None) 1454 continue 1455 1456 if rv != CKR_OK: 1457 raise PyKCS11Error(rv) 1458 # second call to get the attribute value 1459 rv = self.lib.C_GetAttributeValue(self.session, obj_id, valTemplate) 1460 if rv != CKR_OK: 1461 raise PyKCS11Error(rv) 1462 1463 if (allAsBinary): 1464 res.append(valTemplate[0].GetBin()) 1465 elif valTemplate[0].IsNum(): 1466 res.append(valTemplate[0].GetNum()) 1467 elif valTemplate[0].IsBool(): 1468 res.append(valTemplate[0].GetBool()) 1469 elif valTemplate[0].IsString(): 1470 res.append(valTemplate[0].GetString()) 1471 elif valTemplate[0].IsBin(): 1472 res.append(valTemplate[0].GetBin()) 1473 else: 1474 raise PyKCS11Error(-2) 1475 1476 return res
1477
1478 - def seedRandom(self, seed):
1479 """ 1480 C_SeedRandom 1481 1482 @param seed: seed material 1483 @type seed: iterable 1484 """ 1485 low_seed = ckbytelist(len(seed)) 1486 for c in range(len(seed)): 1487 low_seed.append(seed[c]) 1488 rv = self.lib.C_SeedRandom(self.session, low_seed) 1489 if rv != CKR_OK: 1490 raise PyKCS11Error(rv)
1491
1492 - def generateRandom(self, size=16):
1493 """ 1494 C_GenerateRandom 1495 1496 @param size: number of random bytes to get 1497 @type size: integer 1498 1499 @note: the returned value is an instance of L{ckbytelist}. 1500 You can easly convert it to a binary string with:: 1501 bytes(random) 1502 or, for Python 2:: 1503 ''.join(chr(i) for i in random) 1504 """ 1505 low_rand = ckbytelist(size) 1506 rv = self.lib.C_GenerateRandom(self.session, low_rand) 1507 if rv != CKR_OK: 1508 raise PyKCS11Error(rv) 1509 return low_rand
1510 1511 if __name__ == "__main__": 1512 # sample test/debug code 1513 p = PyKCS11Lib() 1514 p.load() 1515 1516 print("getInfo") 1517 print(p.getInfo()) 1518 1519 print() 1520 print("getSlotList") 1521 s = p.getSlotList() 1522 print("slots:", s) 1523 slot = s[0] 1524 print("using slot:", slot) 1525 1526 print() 1527 print("getSlotInfo") 1528 print(p.getSlotInfo(slot)) 1529 1530 print() 1531 print("getTokenInfo") 1532 print(p.getTokenInfo(slot)) 1533 1534 print() 1535 print("openSession") 1536 se = p.openSession(slot) 1537 1538 print() 1539 print("sessionInfo") 1540 print(se.getSessionInfo()) 1541 1542 print() 1543 print("seedRandom") 1544 try: 1545 se.seedRandom([1, 2, 3, 4]) 1546 except PyKCS11Error as e: 1547 print(e) 1548 print("generateRandom") 1549 print(se.generateRandom()) 1550 1551 print() 1552 print("login") 1553 se.login(pin="0000") 1554 1555 print() 1556 print("sessionInfo") 1557 print(se.getSessionInfo()) 1558 1559 print() 1560 print("findObjects") 1561 objs = se.findObjects([(CKA_CLASS, CKO_CERTIFICATE)]) 1562 print("Nb objetcs:", len(objs)) 1563 print(objs) 1564 1565 print() 1566 print("getAttributeValue") 1567 for o in objs: 1568 attr = se.getAttributeValue(o, [CKA_LABEL, CKA_CLASS]) 1569 print(attr) 1570 1571 print() 1572 print("logout") 1573 se.logout() 1574 1575 print() 1576 print("closeSession") 1577 se.closeSession() 1578