1.. _pkcs11: 2 3PKCS#11 4======================================== 5 6.. versionadded:: 1.11.31 7 8| 9 10PKCS#11 is a platform-independent interface for accessing smart cards and 11hardware security modules (HSM). Vendors of PKCS#11 compatible devices usually 12provide a so called middleware or "PKCS#11 module" which implements the PKCS#11 13standard. This middleware translates calls from the platform-independent PKCS#11 14API to device specific calls. So application developers don't have to write smart card 15or HSM specific code for each device they want to support. 16 17 .. note:: 18 19 The Botan PKCS#11 interface is implemented against version v2.40 of the standard. 20 21Botan wraps the C PKCS#11 API to provide a C++ PKCS#11 interface. This is done 22in two levels of abstraction: a low level API (see :ref:`pkcs11_low_level`) and 23a high level API (see :ref:`pkcs11_high_level`). The low level API provides 24access to all functions that are specified by the standard. The high level API 25represents an object oriented approach to use PKCS#11 compatible devices but 26only provides a subset of the functions described in the standard. 27 28To use the PKCS#11 implementation the ``pkcs11`` module has to be enabled. 29 30 .. note:: 31 32 Both PKCS#11 APIs live in the namespace ``Botan::PKCS11`` 33 34.. _pkcs11_low_level: 35 36Low Level API 37---------------------------------------- 38 39The PKCS#11 standards committee provides header files (``pkcs11.h``, ``pkcs11f.h`` and 40``pkcs11t.h``) which define the PKCS#11 API in the C programming language. These 41header files could be used directly to access PKCS#11 compatible smart cards or 42HSMs. The external header files are shipped with Botan in version v2.4 of the standard. The PKCS#11 low 43level API wraps the original PKCS#11 API, but still allows to access all functions described in the 44standard and has the advantage that it is a C++ interface with features like RAII, exceptions 45and automatic memory management. 46 47The low level API is implemented by the :cpp:class:`LowLevel` class and can be accessed by 48including the header ``botan/p11.h``. 49 50Preface 51^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 52 53All constants that belong together in the PKCS#11 standard are grouped into C++ 54enum classes. For example the different user types are grouped in the 55:cpp:enum:`UserType` enumeration: 56 57.. cpp:enum-class:: UserType : CK_USER_TYPE 58 59 .. cpp:enumerator:: UserType::SO = CKU_SO 60 .. cpp:enumerator:: UserType::User = CKU_USER 61 .. cpp:enumerator:: UserType::ContextSpecific = CKU_CONTEXT_SPECIFIC 62 63Additionally, all types that are used by the low or high level API are mapped by 64type aliases to more C++ like names. For instance: 65 66.. cpp:type:: FunctionListPtr = CK_FUNCTION_LIST_PTR 67 68.. rubric:: C-API Wrapping 69 70There is at least one method in the :cpp:class:`LowLevel` class that corresponds to a PKCS#11 71function. For example the :cpp:func:`C_GetSlotList` method in the :cpp:class:`LowLevel` class is defined as follows: 72 73.. cpp:class:: LowLevel 74 75 .. cpp:function:: bool C_GetSlotList(Bbool token_present, SlotId* slot_list_ptr, Ulong* count_ptr, ReturnValue* return_value = ThrowException) const 76 77The :cpp:class:`LowLevel` class calls the PKCS#11 function from the function list of the PKCS#11 module: 78 79 .. code-block:: c 80 81 CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)( CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, 82 CK_ULONG_PTR pulCount ) 83 84Where it makes sense there is also an overload of the :cpp:class:`LowLevel` method to make usage easier and safer: 85 86 .. cpp:function:: bool C_GetSlotList( bool token_present, std::vector<SlotId>& slot_ids, ReturnValue* return_value = ThrowException ) const 87 88With this overload the user of this API just has to pass a vector of :cpp:type:`SlotId` instead of pointers 89to preallocated memory for the slot list and the number of elements. Additionally, there is no need 90to call the method twice in order to determine the number of elements first. 91 92Another example is the :cpp:func:`C_InitPIN` overload: 93 94 .. cpp:function:: template<typename Talloc> bool C_InitPIN( SessionHandle session, const std::vector<uint8_t, TAlloc>& pin, ReturnValue* return_value = ThrowException ) const 95 96The templated ``pin`` parameter allows to pass the PIN as a ``std::vector<uint8_t>`` or a ``secure_vector<uint8_t>``. 97If used with a ``secure_vector`` it is assured that the memory is securely erased when the ``pin`` object is no longer needed. 98 99Error Handling 100~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 101 102All possible PKCS#11 return values are represented by the enum class: 103 104.. cpp:enum-class:: ReturnValue : CK_RV 105 106All methods of the :cpp:class:`LowLevel` class have a default parameter ``ReturnValue* return_value = ThrowException``. 107This parameter controls the error handling of all :cpp:class:`LowLevel` methods. The default 108behavior ``return_value = ThrowException`` is to throw an exception if the method does 109not complete successfully. If a non-``NULL`` pointer is passed, ``return_value`` receives the 110return value of the PKCS#11 function and no exception is thrown. In case ``nullptr`` is 111passed as ``return_value``, the exact return value is ignored and the method just returns 112``true`` if the function succeeds and ``false`` otherwise. 113 114Getting started 115^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 116 117An object of this class can be instantiated by providing a :cpp:type:`FunctionListPtr` to the :cpp:class:`LowLevel` constructor: 118 119 .. cpp:function:: explicit LowLevel(FunctionListPtr ptr) 120 121The :cpp:class:`LowLevel` class provides a static method to retrieve a :cpp:type:`FunctionListPtr` 122from a PKCS#11 module file: 123 124 .. cpp:function:: static bool C_GetFunctionList(Dynamically_Loaded_Library& pkcs11_module, FunctionListPtr* function_list_ptr_ptr, ReturnValue* return_value = ThrowException) 125 126---------- 127 128Code Example: Object Instantiation 129 130 .. code-block:: cpp 131 132 Botan::Dynamically_Loaded_Library pkcs11_module( "C:\\pkcs11-middleware\\library.dll" ); 133 Botan::PKCS11::FunctionListPtr func_list = nullptr; 134 Botan::PKCS11::LowLevel::C_GetFunctionList( pkcs11_module, &func_list ); 135 Botan::PKCS11::LowLevel p11_low_level( func_list ); 136 137---------- 138 139Code Example: PKCS#11 Module Initialization 140 141 .. code-block:: cpp 142 143 Botan::PKCS11::LowLevel p11_low_level(func_list); 144 145 Botan::PKCS11::C_InitializeArgs init_args = { nullptr, nullptr, nullptr, nullptr, 146 static_cast<CK_FLAGS>(Botan::PKCS11::Flag::OsLockingOk), nullptr }; 147 148 p11_low_level.C_Initialize(&init_args); 149 150 // work with the token 151 152 p11_low_level.C_Finalize(nullptr); 153 154More code examples can be found in the test suite in the ``test_pkcs11_low_level.cpp`` file. 155 156.. _pkcs11_high_level: 157 158High Level API 159---------------------------------------- 160 161The high level API provides access to the most commonly used PKCS#11 functionality in an 162object oriented manner. Functionality of the high level API includes: 163 164* Loading/unloading of PKCS#11 modules 165* Initialization of tokens 166* Change of PIN/SO-PIN 167* Session management 168* Random number generation 169* Enumeration of objects on the token (certificates, public keys, private keys) 170* Import/export/deletion of certificates 171* Generation/import/export/deletion of RSA and EC public and private keys 172* Encryption/decryption using RSA with support for OAEP and PKCS1-v1_5 (and raw) 173* Signature generation/verification using RSA with support for PSS and PKCS1-v1_5 (and raw) 174* Signature generation/verification using ECDSA 175* Key derivation using ECDH 176 177Module 178^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 179 180The :cpp:class:`Module` class represents a PKCS#11 shared library (module) and is defined in 181``botan/p11_module.h``. 182 183It is constructed from a a file path to a PKCS#11 module and optional :cpp:type:`C_InitializeArgs`: 184 185.. cpp:class:: Module 186 187 .. code-block:: cpp 188 189 Module(const std::string& file_path, C_InitializeArgs init_args = 190 { nullptr, nullptr, nullptr, nullptr, static_cast<CK_FLAGS>(Flag::OsLockingOk), nullptr }) 191 192 It loads the shared library and calls :cpp:func:`C_Initialize` with the provided :cpp:type:`C_InitializeArgs`. 193 On destruction of the object :cpp:func:`C_Finalize` is called. 194 195There are two more methods in this class. One is for reloading the shared library 196and reinitializing the PKCS#11 module: 197 198 .. code-block:: cpp 199 200 void reload(C_InitializeArgs init_args = 201 { nullptr, nullptr, nullptr, nullptr, static_cast< CK_FLAGS >(Flag::OsLockingOk), nullptr }); 202 203The other one is for getting general information about the PKCS#11 module: 204 205 .. cpp:function:: Info get_info() const 206 207 This function calls :cpp:func:`C_GetInfo` internally. 208 209---------- 210 211Code example: 212 213 .. code-block:: cpp 214 215 Botan::PKCS11::Module module( "C:\\pkcs11-middleware\\library.dll" ); 216 217 // Sometimes useful if a newly connected token is not detected by the PKCS#11 module 218 module.reload(); 219 220 Botan::PKCS11::Info info = module.get_info(); 221 222 // print library version 223 std::cout << std::to_string( info.libraryVersion.major ) << "." 224 << std::to_string( info.libraryVersion.minor ) << std::endl; 225 226Slot 227^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 228 229The :cpp:class:`Slot` class represents a PKCS#11 slot and is defined in 230``botan/p11_slot.h``. 231 232A PKCS#11 slot is usually a smart card reader that potentially contains a token. 233 234.. cpp:class:: Slot 235 236 .. cpp:function:: Slot(Module& module, SlotId slot_id) 237 238 To instantiate this class a reference to a :cpp:class:`Module` object and a ``slot_id`` have to be passed 239 to the constructor. 240 241 .. cpp:function:: static std::vector<SlotId> get_available_slots(Module& module, bool token_present) 242 243 Retrieve available slot ids by calling this static method. 244 245 The parameter ``token_present`` controls whether all slots or only slots with a 246 token attached are returned by this method. This method calls :cpp:func:`C_GetSlotList()`. 247 248 .. cpp:function:: SlotInfo get_slot_info() const 249 250 Returns information about the slot. Calls :cpp:func:`C_GetSlotInfo`. 251 252 .. cpp:function:: TokenInfo get_token_info() const 253 254 Obtains information about a particular token in the system. Calls :cpp:func:`C_GetTokenInfo`. 255 256 .. cpp:function:: std::vector<MechanismType> get_mechanism_list() const 257 258 Obtains a list of mechanism types supported by the slot. Calls :cpp:func:`C_GetMechanismList`. 259 260 .. cpp:function:: MechanismInfo get_mechanism_info(MechanismType mechanism_type) const 261 262 Obtains information about a particular mechanism possibly supported by a slot. 263 Calls :cpp:func:`C_GetMechanismInfo`. 264 265 .. cpp:function:: void initialize(const std::string& label, const secure_string& so_pin) const 266 267 Calls :cpp:func:`C_InitToken` to initialize the token. The ``label`` must not exceed 32 bytes. 268 The current PIN of the security officer must be passed in ``so_pin`` if the token 269 is reinitialized or if it's a factory new token, the ``so_pin`` that is passed will initially be set. 270 271---------- 272 273Code example: 274 275 .. code-block:: cpp 276 277 // only slots with connected token 278 std::vector<Botan::PKCS11::SlotId> slots = Botan::PKCS11::Slot::get_available_slots( module, true ); 279 280 // use first slot 281 Botan::PKCS11::Slot slot( module, slots.at( 0 ) ); 282 283 // print firmware version of the slot 284 Botan::PKCS11::SlotInfo slot_info = slot.get_slot_info(); 285 std::cout << std::to_string( slot_info.firmwareVersion.major ) << "." 286 << std::to_string( slot_info.firmwareVersion.minor ) << std::endl; 287 288 // print firmware version of the token 289 Botan::PKCS11::TokenInfo token_info = slot.get_token_info(); 290 std::cout << std::to_string( token_info.firmwareVersion.major ) << "." 291 << std::to_string( token_info.firmwareVersion.minor ) << std::endl; 292 293 // retrieve all mechanisms supported by the token 294 std::vector<Botan::PKCS11::MechanismType> mechanisms = slot.get_mechanism_list(); 295 296 // retrieve information about a particular mechanism 297 Botan::PKCS11::MechanismInfo mech_info = 298 slot.get_mechanism_info( Botan::PKCS11::MechanismType::RsaPkcsOaep ); 299 300 // maximum RSA key length supported: 301 std::cout << mech_info.ulMaxKeySize << std::endl; 302 303 // initialize the token 304 Botan::PKCS11::secure_string so_pin( 8, '0' ); 305 slot.initialize( "Botan PKCS11 documentation test label", so_pin ); 306 307Session 308^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 309 310The :cpp:class:`Session` class represents a PKCS#11 session and is defined in ``botan/p11_session.h``. 311 312A session is a logical connection between an application and a token. 313 314.. cpp:class:: Session 315 316 There are two constructors to create a new session and one constructor to 317 take ownership of an existing session. The destructor calls 318 :cpp:func:`C_Logout` if a user is logged in to this session and always 319 :cpp:func:`C_CloseSession`. 320 321 .. cpp:function:: Session(Slot& slot, bool read_only) 322 323 To initialize a session object a :cpp:class:`Slot` has to be specified on which the session 324 should operate. ``read_only`` specifies whether the session should be read only or read write. 325 Calls :cpp:func:`C_OpenSession`. 326 327 .. cpp:function:: Session(Slot& slot, Flags flags, VoidPtr callback_data, Notify notify_callback) 328 329 Creates a new session by passing a :cpp:class:`Slot`, session ``flags``, ``callback_data`` and a 330 ``notify_callback``. Calls :cpp:func:`C_OpenSession`. 331 332 .. cpp:function:: Session(Slot& slot, SessionHandle handle) 333 334 Takes ownership of an existing session by passing :cpp:class:`Slot` and a session ``handle``. 335 336 .. cpp:function:: SessionHandle release() 337 338 Returns the released :cpp:type:`SessionHandle` 339 340 .. cpp:function:: void login(UserType userType, const secure_string& pin) 341 342 Login to this session by passing :cpp:enum:`UserType` and ``pin``. Calls :cpp:func:`C_Login`. 343 344 .. cpp:function:: void logoff() 345 346 Logout from this session. Not mandatory because on destruction of the :cpp:class:`Session` object 347 this is done automatically. 348 349 .. cpp:function:: SessionInfo get_info() const 350 351 Returns information about this session. Calls :cpp:func:`C_GetSessionInfo`. 352 353 .. cpp:function:: void set_pin(const secure_string& old_pin, const secure_string& new_pin) const 354 355 Calls :cpp:func:`C_SetPIN` to change the PIN of the logged in user using the ``old_pin``. 356 357 .. cpp:function:: void init_pin(const secure_string& new_pin) 358 359 Calls :cpp:func:`C_InitPIN` to change or initialize the PIN using the SO_PIN (requires a logged in session). 360 361---------- 362 363Code example: 364 365 .. code-block:: cpp 366 367 // open read only session 368 { 369 Botan::PKCS11::Session read_only_session( slot, true ); 370 } 371 372 // open read write session 373 { 374 Botan::PKCS11::Session read_write_session( slot, false ); 375 } 376 377 // open read write session by passing flags 378 { 379 Botan::PKCS11::Flags flags = 380 Botan::PKCS11::flags( Botan::PKCS11::Flag::SerialSession | Botan::PKCS11::Flag::RwSession ); 381 382 Botan::PKCS11::Session read_write_session( slot, flags, nullptr, nullptr ); 383 } 384 385 // move ownership of a session 386 { 387 Botan::PKCS11::Session session( slot, false ); 388 Botan::PKCS11::SessionHandle handle = session.release(); 389 390 Botan::PKCS11::Session session2( slot, handle ); 391 } 392 393 Botan::PKCS11::Session session( slot, false ); 394 395 // get session info 396 Botan::PKCS11::SessionInfo info = session.get_info(); 397 std::cout << info.slotID << std::endl; 398 399 // login 400 Botan::PKCS11::secure_string pin = { '1', '2', '3', '4', '5', '6' }; 401 session.login( Botan::PKCS11::UserType::User, pin ); 402 403 // set pin 404 Botan::PKCS11::secure_string new_pin = { '6', '5', '4', '3', '2', '1' }; 405 session.set_pin( pin, new_pin ); 406 407 // logoff 408 session.logoff(); 409 410 // log in as security officer 411 Botan::PKCS11::secure_string so_pin = { '0', '0', '0', '0', '0', '0', '0', '0' }; 412 session.login( Botan::PKCS11::UserType::SO, so_pin ); 413 414 // change pin to old pin 415 session.init_pin( pin ); 416 417Objects 418^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 419 420PKCS#11 objects consist of various attributes (:c:type:`CK_ATTRIBUTE`). For example :c:macro:`CKA_TOKEN` 421describes if a PKCS#11 object is a session object or a token object. The helper class :cpp:class:`AttributeContainer` 422helps with storing these attributes. The class is defined in ``botan/p11_object.h``. 423 424.. cpp:class:: AttributeContainer 425 426Attributes can be set in an :cpp:class:`AttributeContainer` by various ``add_`` methods: 427 428 .. cpp:function:: void add_class(ObjectClass object_class) 429 430 Add a class attribute (:c:macro:`CKA_CLASS` / :cpp:enumerator:`AttributeType::Class`) 431 432 .. cpp:function:: void add_string(AttributeType attribute, const std::string& value) 433 434 Add a string attribute (e.g. :c:macro:`CKA_LABEL` / :cpp:enumerator:`AttributeType::Label`). 435 436 .. cpp:function:: void AttributeContainer::add_binary(AttributeType attribute, const uint8_t* value, size_t length) 437 438 Add a binary attribute (e.g. :c:macro:`CKA_ID` / :cpp:enumerator:`AttributeType::Id`). 439 440 .. cpp:function:: template<typename TAlloc> void AttributeContainer::add_binary(AttributeType attribute, const std::vector<uint8_t, TAlloc>& binary) 441 442 Add a binary attribute by passing a ``vector``/``secure_vector`` (e.g. :c:macro:`CKA_ID` / :cpp:enumerator:`AttributeType::Id`). 443 444 .. cpp:function:: void AttributeContainer::add_bool(AttributeType attribute, bool value) 445 446 Add a bool attribute (e.g. :c:macro:`CKA_SENSITIVE` / :cpp:enumerator:`AttributeType::Sensitive`). 447 448 .. cpp:function:: template<typename T> void AttributeContainer::add_numeric(AttributeType attribute, T value) 449 450 Add a numeric attribute (e.g. :c:macro:`CKA_MODULUS_BITS` / :cpp:enumerator:`AttributeType::ModulusBits`). 451 452.. rubric:: Object Properties 453 454The PKCS#11 standard defines the mandatory and optional attributes for each object class. 455The mandatory and optional attribute requirements are mapped in so called property classes. 456Mandatory attributes are set in the constructor, optional attributes can be set via ``set_`` methods. 457 458In the top hierarchy is the :cpp:class:`ObjectProperties` class which inherits from the :cpp:class:`AttributeContainer`. 459This class represents the common attributes of all PKCS#11 objects. 460 461.. cpp:class:: ObjectProperties : public AttributeContainer 462 463The constructor is defined as follows: 464 465 .. cpp:function:: ObjectProperties(ObjectClass object_class) 466 467 Every PKCS#11 object needs an object class attribute. 468 469The next level defines the :cpp:class:`StorageObjectProperties` class which inherits from 470:cpp:class:`ObjectProperties`. 471 472.. cpp:class:: StorageObjectProperties : public ObjectProperties 473 474The only mandatory attribute is the object class, so the constructor is 475defined as follows: 476 477 .. cpp:function:: StorageObjectProperties(ObjectClass object_class) 478 479But in contrast to the :cpp:class:`ObjectProperties` class there are various setter methods. For example to 480set the :cpp:enumerator:`AttributeType::Label`: 481 482 .. cpp:function:: void set_label(const std::string& label) 483 484 Sets the label description of the object (RFC2279 string). 485 486The remaining hierarchy is defined as follows: 487 488* :cpp:class:`DataObjectProperties` inherits from :cpp:class:`StorageObjectProperties` 489* :cpp:class:`CertificateProperties` inherits from :cpp:class:`StorageObjectProperties` 490* :cpp:class:`DomainParameterProperties` inherits from :cpp:class:`StorageObjectProperties` 491* :cpp:class:`KeyProperties` inherits from :cpp:class:`StorageObjectProperties` 492* :cpp:class:`PublicKeyProperties` inherits from :cpp:class:`KeyProperties` 493* :cpp:class:`PrivateKeyProperties` inherits from :cpp:class:`KeyProperties` 494* :cpp:class:`SecretKeyProperties` inherits from :cpp:class:`KeyProperties` 495 496PKCS#11 objects themselves are represented by the :cpp:class:`Object` class. 497 498.. cpp:class:: Object 499 500Following constructors are defined: 501 502 .. cpp:function:: Object(Session& session, ObjectHandle handle) 503 504 Takes ownership over an existing object. 505 506 .. cpp:function:: Object(Session& session, const ObjectProperties& obj_props) 507 508 Creates a new object with the :cpp:class:`ObjectProperties` provided in ``obj_props``. 509 510The other methods are: 511 512 .. cpp:function:: secure_vector<uint8_t> get_attribute_value(AttributeType attribute) const 513 514 Returns the value of the given attribute (using :cpp:func:`C_GetAttributeValue`) 515 516 .. cpp:function:: void set_attribute_value(AttributeType attribute, const secure_vector<uint8_t>& value) const 517 518 Sets the given value for the attribute (using :cpp:func:`C_SetAttributeValue`) 519 520 .. cpp:function:: void destroy() const 521 522 Destroys the object. 523 524 .. cpp:function:: ObjectHandle copy(const AttributeContainer& modified_attributes) const 525 526 Allows to copy the object with modified attributes. 527 528And static methods to search for objects: 529 530 .. cpp:function:: template<typename T> static std::vector<T> search(Session& session, const std::vector<Attribute>& search_template) 531 532 Searches for all objects of the given type that match ``search_template``. 533 534 .. cpp:function:: template<typename T> static std::vector<T> search(Session& session, const std::string& label) 535 536 Searches for all objects of the given type using the label (:c:macro:`CKA_LABEL`). 537 538 .. cpp:function:: template<typename T> static std::vector<T> search(Session& session, const std::vector<uint8_t>& id) 539 540 Searches for all objects of the given type using the id (:c:macro:`CKA_ID`). 541 542 .. cpp:function:: template<typename T> static std::vector<T> search(Session& session, const std::string& label, const std::vector<uint8_t>& id) 543 544 Searches for all objects of the given type using the label (:c:macro:`CKA_LABEL`) and id (:c:macro:`CKA_ID`). 545 546 .. cpp:function:: template<typename T> static std::vector<T> search(Session& session) 547 548 Searches for all objects of the given type. 549 550.. rubric:: The ObjectFinder 551 552Another way for searching objects is to use the :cpp:class:`ObjectFinder` class. This class 553manages calls to the ``C_FindObjects*`` functions: :cpp:func:`C_FindObjectsInit`, :cpp:func:`C_FindObjects` 554and :cpp:func:`C_FindObjectsFinal`. 555 556.. cpp:class:: ObjectFinder 557 558The constructor has the following signature: 559 560 .. cpp:function:: ObjectFinder(Session& session, const std::vector<Attribute>& search_template) 561 562 A search can be prepared with an :cpp:class:`ObjectSearcher` by passing a :cpp:class:`Session` and a ``search_template``. 563 564The actual search operation is started by calling the :cpp:func:`find` method: 565 566 .. cpp:function:: std::vector<ObjectHandle> find(std::uint32_t max_count = 100) const 567 568 Starts or continues a search for token and session objects that match a template. ``max_count`` 569 specifies the maximum number of search results (object handles) that are returned. 570 571 .. cpp:function:: void finish() 572 573 Finishes the search operation manually to allow a new :cpp:class:`ObjectFinder` to exist. 574 Otherwise the search is finished by the destructor. 575 576---------- 577 578Code example: 579 580 .. code-block:: cpp 581 582 // create an simple data object 583 Botan::secure_vector<uint8_t> value = { 0x00, 0x01 ,0x02, 0x03 }; 584 std::size_t id = 1337; 585 std::string label = "test data object"; 586 587 // set properties of the new object 588 Botan::PKCS11::DataObjectProperties data_obj_props; 589 data_obj_props.set_label( label ); 590 data_obj_props.set_value( value ); 591 data_obj_props.set_token( true ); 592 data_obj_props.set_modifiable( true ); 593 data_obj_props.set_object_id( Botan::DER_Encoder().encode( id ).get_contents_unlocked() ); 594 595 // create the object 596 Botan::PKCS11::Object data_obj( session, data_obj_props ); 597 598 // get label of this object 599 Botan::PKCS11::secure_string retrieved_label = 600 data_obj.get_attribute_value( Botan::PKCS11::AttributeType::Label ); 601 602 // set a new label 603 Botan::PKCS11::secure_string new_label = { 'B', 'o', 't', 'a', 'n' }; 604 data_obj.set_attribute_value( Botan::PKCS11::AttributeType::Label, new_label ); 605 606 // copy the object 607 Botan::PKCS11::AttributeContainer copy_attributes; 608 copy_attributes.add_string( Botan::PKCS11::AttributeType::Label, "copied object" ); 609 Botan::PKCS11::ObjectHandle copied_obj_handle = data_obj.copy( copy_attributes ); 610 611 // search for an object 612 Botan::PKCS11::AttributeContainer search_template; 613 search_template.add_string( Botan::PKCS11::AttributeType::Label, "Botan" ); 614 auto found_objs = 615 Botan::PKCS11::Object::search<Botan::PKCS11::Object>( session, search_template.attributes() ); 616 617 // destroy the object 618 data_obj.destroy(); 619 620RSA 621^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 622 623PKCS#11 RSA support is implemented in ``<botan/p11_rsa.h>``. 624 625.. rubric:: RSA Public Keys 626 627PKCS#11 RSA public keys are provided by the class :cpp:class:`PKCS11_RSA_PublicKey`. This class 628inherits from :cpp:class:`RSA_PublicKey` and :cpp:class:`Object`. Furthermore there are two property classes defined 629to generate and import RSA public keys analogous to the other property classes described 630before: :cpp:class:`RSA_PublicKeyGenerationProperties` and :cpp:class:`RSA_PublicKeyImportProperties`. 631 632.. cpp:class:: PKCS11_RSA_PublicKey : public RSA_PublicKey, public Object 633 634 .. cpp:function:: PKCS11_RSA_PublicKey(Session& session, ObjectHandle handle) 635 636 Existing PKCS#11 RSA public keys can be used by providing an :cpp:type:`ObjectHandle` to the 637 constructor. 638 639 .. cpp:function:: PKCS11_RSA_PublicKey(Session& session, const RSA_PublicKeyImportProperties& pubkey_props) 640 641 This constructor can be used to import an existing RSA public key with the :cpp:class:`RSA_PublicKeyImportProperties` 642 passed in ``pubkey_props`` to the token. 643 644.. rubric:: RSA Private Keys 645 646The support for PKCS#11 RSA private keys is implemented in a similar way. There are two property 647classes: :cpp:class:`RSA_PrivateKeyGenerationProperties` and :cpp:class:`RSA_PrivateKeyImportProperties`. The :cpp:class:`PKCS11_RSA_PrivateKey` 648class implements the actual support for PKCS#11 RSA private keys. This class inherits from :cpp:class:`Private_Key`, 649:cpp:class:`RSA_PublicKey` and :cpp:class:`Object`. In contrast to the public key class there is a third constructor 650to generate private keys directly on the token or in the session and one method to export private keys. 651 652.. cpp:class:: PKCS11_RSA_PrivateKey : public Private_Key, public RSA_PublicKey, public Object 653 654 .. cpp:function:: PKCS11_RSA_PrivateKey(Session& session, ObjectHandle handle) 655 656 Existing PKCS#11 RSA private keys can be used by providing an :cpp:type:`ObjectHandle` to the 657 constructor. 658 659 .. cpp:function:: PKCS11_RSA_PrivateKey(Session& session, const RSA_PrivateKeyImportProperties& priv_key_props) 660 661 This constructor can be used to import an existing RSA private key with the :cpp:class:`RSA_PrivateKeyImportProperties` 662 passed in ``priv_key_props`` to the token. 663 664 .. cpp:function:: PKCS11_RSA_PrivateKey(Session& session, uint32_t bits, const RSA_PrivateKeyGenerationProperties& priv_key_props) 665 666 Generates a new PKCS#11 RSA private key with bit length provided in ``bits`` and the :cpp:class:`RSA_PrivateKeyGenerationProperties` 667 passed in ``priv_key_props``. 668 669 .. cpp:function:: RSA_PrivateKey export_key() const 670 671 Returns the exported :cpp:class:`RSA_PrivateKey`. 672 673PKCS#11 RSA key pairs can be generated with the following free function: 674 675 .. cpp:function:: PKCS11_RSA_KeyPair PKCS11::generate_rsa_keypair(Session& session, const RSA_PublicKeyGenerationProperties& pub_props, const RSA_PrivateKeyGenerationProperties& priv_props) 676 677---------- 678 679Code example: 680 681 .. code-block:: cpp 682 683 Botan::PKCS11::secure_string pin = { '1', '2', '3', '4', '5', '6' }; 684 session.login( Botan::PKCS11::UserType::User, pin ); 685 686 /************ import RSA private key *************/ 687 688 // create private key in software 689 Botan::AutoSeeded_RNG rng; 690 Botan::RSA_PrivateKey priv_key_sw( rng, 2048 ); 691 692 // set the private key import properties 693 Botan::PKCS11::RSA_PrivateKeyImportProperties 694 priv_import_props( priv_key_sw.get_n(), priv_key_sw.get_d() ); 695 696 priv_import_props.set_pub_exponent( priv_key_sw.get_e() ); 697 priv_import_props.set_prime_1( priv_key_sw.get_p() ); 698 priv_import_props.set_prime_2( priv_key_sw.get_q() ); 699 priv_import_props.set_coefficient( priv_key_sw.get_c() ); 700 priv_import_props.set_exponent_1( priv_key_sw.get_d1() ); 701 priv_import_props.set_exponent_2( priv_key_sw.get_d2() ); 702 703 priv_import_props.set_token( true ); 704 priv_import_props.set_private( true ); 705 priv_import_props.set_decrypt( true ); 706 priv_import_props.set_sign( true ); 707 708 // import 709 Botan::PKCS11::PKCS11_RSA_PrivateKey priv_key( session, priv_import_props ); 710 711 /************ export PKCS#11 RSA private key *************/ 712 Botan::RSA_PrivateKey exported = priv_key.export_key(); 713 714 /************ import RSA public key *************/ 715 716 // set the public key import properties 717 Botan::PKCS11::RSA_PublicKeyImportProperties pub_import_props( priv_key.get_n(), priv_key.get_e() ); 718 pub_import_props.set_token( true ); 719 pub_import_props.set_encrypt( true ); 720 pub_import_props.set_private( false ); 721 722 // import 723 Botan::PKCS11::PKCS11_RSA_PublicKey public_key( session, pub_import_props ); 724 725 /************ generate RSA private key *************/ 726 727 Botan::PKCS11::RSA_PrivateKeyGenerationProperties priv_generate_props; 728 priv_generate_props.set_token( true ); 729 priv_generate_props.set_private( true ); 730 priv_generate_props.set_sign( true ); 731 priv_generate_props.set_decrypt( true ); 732 priv_generate_props.set_label( "BOTAN_TEST_RSA_PRIV_KEY" ); 733 734 Botan::PKCS11::PKCS11_RSA_PrivateKey private_key2( session, 2048, priv_generate_props ); 735 736 /************ generate RSA key pair *************/ 737 738 Botan::PKCS11::RSA_PublicKeyGenerationProperties pub_generate_props( 2048UL ); 739 pub_generate_props.set_pub_exponent(); 740 pub_generate_props.set_label( "BOTAN_TEST_RSA_PUB_KEY" ); 741 pub_generate_props.set_token( true ); 742 pub_generate_props.set_encrypt( true ); 743 pub_generate_props.set_verify( true ); 744 pub_generate_props.set_private( false ); 745 746 Botan::PKCS11::PKCS11_RSA_KeyPair rsa_keypair = 747 Botan::PKCS11::generate_rsa_keypair( session, pub_generate_props, priv_generate_props ); 748 749 /************ RSA encrypt *************/ 750 751 Botan::secure_vector<uint8_t> plaintext = { 0x00, 0x01, 0x02, 0x03 }; 752 Botan::PK_Encryptor_EME encryptor( rsa_keypair.first, rng, "Raw" ); 753 auto ciphertext = encryptor.encrypt( plaintext, rng ); 754 755 /************ RSA decrypt *************/ 756 757 Botan::PK_Decryptor_EME decryptor( rsa_keypair.second, rng, "Raw" ); 758 plaintext = decryptor.decrypt( ciphertext ); 759 760 /************ RSA sign *************/ 761 762 Botan::PK_Signer signer( rsa_keypair.second, rng, "EMSA4(SHA-256)", Botan::IEEE_1363 ); 763 auto signature = signer.sign_message( plaintext, rng ); 764 765 /************ RSA verify *************/ 766 767 Botan::PK_Verifier verifier( rsa_keypair.first, "EMSA4(SHA-256)", Botan::IEEE_1363 ); 768 auto ok = verifier.verify_message( plaintext, signature ); 769 770ECDSA 771^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 772 773PKCS#11 ECDSA support is implemented in ``<botan/p11_ecdsa.h>``. 774 775.. rubric:: ECDSA Public Keys 776 777PKCS#11 ECDSA public keys are provided by the class :cpp:class:`PKCS11_ECDSA_PublicKey`. This class 778inherits from :cpp:class:`PKCS11_EC_PublicKey` and :cpp:class:`ECDSA_PublicKey`. The necessary property classes 779are defined in ``<botan/p11_ecc_key.h>``. For public keys there are :cpp:class:`EC_PublicKeyGenerationProperties` 780and :cpp:class:`EC_PublicKeyImportProperties`. 781 782.. cpp:class:: PKCS11_ECDSA_PublicKey : public PKCS11_EC_PublicKey, public virtual ECDSA_PublicKey 783 784 .. cpp:function:: PKCS11_ECDSA_PublicKey(Session& session, ObjectHandle handle) 785 786 Existing PKCS#11 ECDSA private keys can be used by providing an :cpp:type:`ObjectHandle` to the 787 constructor. 788 789 .. cpp:function:: PKCS11_ECDSA_PublicKey(Session& session, const EC_PublicKeyImportProperties& props) 790 791 This constructor can be used to import an existing ECDSA public key with the :cpp:class:`EC_PublicKeyImportProperties` 792 passed in ``props`` to the token. 793 794 .. cpp:function:: ECDSA_PublicKey PKCS11_ECDSA_PublicKey::export_key() const 795 796 Returns the exported :cpp:class:`ECDSA_PublicKey`. 797 798.. rubric:: ECDSA Private Keys 799 800The class :cpp:class:`PKCS11_ECDSA_PrivateKey` inherits from :cpp:class:`PKCS11_EC_PrivateKey` and implements support 801for PKCS#11 ECDSA private keys. There are two property classes for key generation 802and import: :cpp:class:`EC_PrivateKeyGenerationProperties` and :cpp:class:`EC_PrivateKeyImportProperties`. 803 804.. cpp:class:: PKCS11_ECDSA_PrivateKey : public PKCS11_EC_PrivateKey 805 806 .. cpp:function:: PKCS11_ECDSA_PrivateKey(Session& session, ObjectHandle handle) 807 808 Existing PKCS#11 ECDSA private keys can be used by providing an :cpp:type:`ObjectHandle` to the 809 constructor. 810 811 .. cpp:function:: PKCS11_ECDSA_PrivateKey(Session& session, const EC_PrivateKeyImportProperties& props) 812 813 This constructor can be used to import an existing ECDSA private key with the :cpp:class:`EC_PrivateKeyImportProperties` 814 passed in ``props`` to the token. 815 816 .. cpp:function:: PKCS11_ECDSA_PrivateKey(Session& session, const std::vector<uint8_t>& ec_params, const EC_PrivateKeyGenerationProperties& props) 817 818 This constructor can be used to generate a new ECDSA private key with the :cpp:class:`EC_PrivateKeyGenerationProperties` 819 passed in ``props`` on the token. The ``ec_params`` parameter is the DER-encoding of an 820 ANSI X9.62 Parameters value. 821 822 .. cpp:function:: ECDSA_PrivateKey export_key() const 823 824 Returns the exported :cpp:class:`ECDSA_PrivateKey`. 825 826PKCS#11 ECDSA key pairs can be generated with the following free function: 827 828 .. cpp:function:: PKCS11_ECDSA_KeyPair PKCS11::generate_ecdsa_keypair(Session& session, const EC_PublicKeyGenerationProperties& pub_props, const EC_PrivateKeyGenerationProperties& priv_props) 829 830---------- 831 832Code example: 833 834 .. code-block:: cpp 835 836 Botan::PKCS11::secure_string pin = { '1', '2', '3', '4', '5', '6' }; 837 session.login( Botan::PKCS11::UserType::User, pin ); 838 839 /************ import ECDSA private key *************/ 840 841 // create private key in software 842 Botan::AutoSeeded_RNG rng; 843 844 Botan::ECDSA_PrivateKey priv_key_sw( rng, Botan::EC_Group( "secp256r1" ) ); 845 priv_key_sw.set_parameter_encoding( Botan::EC_Group_Encoding::EC_DOMPAR_ENC_OID ); 846 847 // set the private key import properties 848 Botan::PKCS11::EC_PrivateKeyImportProperties priv_import_props( 849 priv_key_sw.DER_domain(), priv_key_sw.private_value() ); 850 851 priv_import_props.set_token( true ); 852 priv_import_props.set_private( true ); 853 priv_import_props.set_sign( true ); 854 priv_import_props.set_extractable( true ); 855 856 // label 857 std::string label = "test ECDSA key"; 858 priv_import_props.set_label( label ); 859 860 // import to card 861 Botan::PKCS11::PKCS11_ECDSA_PrivateKey priv_key( session, priv_import_props ); 862 863 /************ export PKCS#11 ECDSA private key *************/ 864 Botan::ECDSA_PrivateKey priv_exported = priv_key.export_key(); 865 866 /************ import ECDSA public key *************/ 867 868 // import to card 869 Botan::PKCS11::EC_PublicKeyImportProperties pub_import_props( priv_key_sw.DER_domain(), 870 Botan::DER_Encoder().encode( EC2OSP( priv_key_sw.public_point(), Botan::PointGFp::UNCOMPRESSED ), 871 Botan::OCTET_STRING ).get_contents_unlocked() ); 872 873 pub_import_props.set_token( true ); 874 pub_import_props.set_verify( true ); 875 pub_import_props.set_private( false ); 876 877 // label 878 label = "test ECDSA pub key"; 879 pub_import_props.set_label( label ); 880 881 Botan::PKCS11::PKCS11_ECDSA_PublicKey public_key( session, pub_import_props ); 882 883 /************ export PKCS#11 ECDSA public key *************/ 884 Botan::ECDSA_PublicKey pub_exported = public_key.export_key(); 885 886 /************ generate PKCS#11 ECDSA private key *************/ 887 Botan::PKCS11::EC_PrivateKeyGenerationProperties priv_generate_props; 888 priv_generate_props.set_token( true ); 889 priv_generate_props.set_private( true ); 890 priv_generate_props.set_sign( true ); 891 892 Botan::PKCS11::PKCS11_ECDSA_PrivateKey pk( session, 893 Botan::EC_Group( "secp256r1" ).DER_encode( Botan::EC_Group_Encoding::EC_DOMPAR_ENC_OID ), 894 priv_generate_props ); 895 896 /************ generate PKCS#11 ECDSA key pair *************/ 897 898 Botan::PKCS11::EC_PublicKeyGenerationProperties pub_generate_props( 899 Botan::EC_Group( "secp256r1" ).DER_encode(Botan::EC_Group_Encoding::EC_DOMPAR_ENC_OID ) ); 900 901 pub_generate_props.set_label( "BOTAN_TEST_ECDSA_PUB_KEY" ); 902 pub_generate_props.set_token( true ); 903 pub_generate_props.set_verify( true ); 904 pub_generate_props.set_private( false ); 905 pub_generate_props.set_modifiable( true ); 906 907 Botan::PKCS11::PKCS11_ECDSA_KeyPair key_pair = Botan::PKCS11::generate_ecdsa_keypair( session, 908 pub_generate_props, priv_generate_props ); 909 910 /************ PKCS#11 ECDSA sign and verify *************/ 911 912 std::vector<uint8_t> plaintext( 20, 0x01 ); 913 914 Botan::PK_Signer signer( key_pair.second, rng, "Raw", Botan::IEEE_1363, "pkcs11" ); 915 auto signature = signer.sign_message( plaintext, rng ); 916 917 Botan::PK_Verifier token_verifier( key_pair.first, "Raw", Botan::IEEE_1363, "pkcs11" ); 918 bool ecdsa_ok = token_verifier.verify_message( plaintext, signature ); 919 920ECDH 921^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 922 923PKCS#11 ECDH support is implemented in ``<botan/p11_ecdh.h>``. 924 925.. rubric:: ECDH Public Keys 926 927PKCS#11 ECDH public keys are provided by the class :cpp:class:`PKCS11_ECDH_PublicKey`. This class 928inherits from :cpp:class:`PKCS11_EC_PublicKey`. The necessary property classes 929are defined in ``<botan/p11_ecc_key.h>``. For public keys there are :cpp:class:`EC_PublicKeyGenerationProperties` 930and :cpp:class:`EC_PublicKeyImportProperties`. 931 932.. cpp:class:: PKCS11_ECDH_PublicKey : public PKCS11_EC_PublicKey 933 934 .. cpp:function:: PKCS11_ECDH_PublicKey(Session& session, ObjectHandle handle) 935 936 Existing PKCS#11 ECDH private keys can be used by providing an :cpp:type:`ObjectHandle` to the 937 constructor. 938 939 .. cpp:function:: PKCS11_ECDH_PublicKey(Session& session, const EC_PublicKeyImportProperties& props) 940 941 This constructor can be used to import an existing ECDH public key with the :cpp:class:`EC_PublicKeyImportProperties` 942 passed in ``props`` to the token. 943 944 .. cpp:function:: ECDH_PublicKey export_key() const 945 946 Returns the exported :cpp:class:`ECDH_PublicKey`. 947 948.. rubric:: ECDH Private Keys 949 950The class :cpp:class:`PKCS11_ECDH_PrivateKey` inherits from :cpp:class:`PKCS11_EC_PrivateKey` and :cpp:class:`PK_Key_Agreement_Key` 951and implements support for PKCS#11 ECDH private keys. There are two 952property classes. One for key generation and one for import: :cpp:class:`EC_PrivateKeyGenerationProperties` and 953:cpp:class:`EC_PrivateKeyImportProperties`. 954 955.. cpp:class:: PKCS11_ECDH_PrivateKey : public virtual PKCS11_EC_PrivateKey, public virtual PK_Key_Agreement_Key 956 957 .. cpp:function:: PKCS11_ECDH_PrivateKey(Session& session, ObjectHandle handle) 958 959 Existing PKCS#11 ECDH private keys can be used by providing an :cpp:type:`ObjectHandle` to the 960 constructor. 961 962 .. cpp:function:: PKCS11_ECDH_PrivateKey(Session& session, const EC_PrivateKeyImportProperties& props) 963 964 This constructor can be used to import an existing ECDH private key with the :cpp:class:`EC_PrivateKeyImportProperties` 965 passed in ``props`` to the token. 966 967 .. cpp:function:: PKCS11_ECDH_PrivateKey(Session& session, const std::vector<uint8_t>& ec_params, const EC_PrivateKeyGenerationProperties& props) 968 969 This constructor can be used to generate a new ECDH private key with the :cpp:class:`EC_PrivateKeyGenerationProperties` 970 passed in ``props`` on the token. The ``ec_params`` parameter is the DER-encoding of an 971 ANSI X9.62 Parameters value. 972 973 .. cpp:function:: ECDH_PrivateKey export_key() const 974 975 Returns the exported :cpp:class:`ECDH_PrivateKey`. 976 977PKCS#11 ECDH key pairs can be generated with the following free function: 978 979.. cpp:function:: PKCS11_ECDH_KeyPair PKCS11::generate_ecdh_keypair(Session& session, const EC_PublicKeyGenerationProperties& pub_props, const EC_PrivateKeyGenerationProperties& priv_props) 980 981---------- 982 983Code example: 984 985 .. code-block:: cpp 986 987 Botan::PKCS11::secure_string pin = { '1', '2', '3', '4', '5', '6' }; 988 session.login( Botan::PKCS11::UserType::User, pin ); 989 990 /************ import ECDH private key *************/ 991 992 Botan::AutoSeeded_RNG rng; 993 994 // create private key in software 995 Botan::ECDH_PrivateKey priv_key_sw( rng, Botan::EC_Group( "secp256r1" ) ); 996 priv_key_sw.set_parameter_encoding( Botan::EC_Group_Encoding::EC_DOMPAR_ENC_OID ); 997 998 // set import properties 999 Botan::PKCS11::EC_PrivateKeyImportProperties priv_import_props( 1000 priv_key_sw.DER_domain(), priv_key_sw.private_value() ); 1001 1002 priv_import_props.set_token( true ); 1003 priv_import_props.set_private( true ); 1004 priv_import_props.set_derive( true ); 1005 priv_import_props.set_extractable( true ); 1006 1007 // label 1008 std::string label = "test ECDH key"; 1009 priv_import_props.set_label( label ); 1010 1011 // import to card 1012 Botan::PKCS11::PKCS11_ECDH_PrivateKey priv_key( session, priv_import_props ); 1013 1014 /************ export ECDH private key *************/ 1015 Botan::ECDH_PrivateKey exported = priv_key.export_key(); 1016 1017 /************ import ECDH public key *************/ 1018 1019 // set import properties 1020 Botan::PKCS11::EC_PublicKeyImportProperties pub_import_props( priv_key_sw.DER_domain(), 1021 Botan::DER_Encoder().encode( EC2OSP( priv_key_sw.public_point(), Botan::PointGFp::UNCOMPRESSED ), 1022 Botan::OCTET_STRING ).get_contents_unlocked() ); 1023 1024 pub_import_props.set_token( true ); 1025 pub_import_props.set_private( false ); 1026 pub_import_props.set_derive( true ); 1027 1028 // label 1029 label = "test ECDH pub key"; 1030 pub_import_props.set_label( label ); 1031 1032 // import 1033 Botan::PKCS11::PKCS11_ECDH_PublicKey pub_key( session, pub_import_props ); 1034 1035 /************ export ECDH private key *************/ 1036 Botan::ECDH_PublicKey exported_pub = pub_key.export_key(); 1037 1038 /************ generate ECDH private key *************/ 1039 1040 Botan::PKCS11::EC_PrivateKeyGenerationProperties priv_generate_props; 1041 priv_generate_props.set_token( true ); 1042 priv_generate_props.set_private( true ); 1043 priv_generate_props.set_derive( true ); 1044 1045 Botan::PKCS11::PKCS11_ECDH_PrivateKey priv_key2( session, 1046 Botan::EC_Group( "secp256r1" ).DER_encode( Botan::EC_Group_Encoding::EC_DOMPAR_ENC_OID ), 1047 priv_generate_props ); 1048 1049 /************ generate ECDH key pair *************/ 1050 1051 Botan::PKCS11::EC_PublicKeyGenerationProperties pub_generate_props( 1052 Botan::EC_Group( "secp256r1" ).DER_encode( Botan::EC_Group_Encoding::EC_DOMPAR_ENC_OID ) ); 1053 1054 pub_generate_props.set_label( label + "_PUB_KEY" ); 1055 pub_generate_props.set_token( true ); 1056 pub_generate_props.set_derive( true ); 1057 pub_generate_props.set_private( false ); 1058 pub_generate_props.set_modifiable( true ); 1059 1060 Botan::PKCS11::PKCS11_ECDH_KeyPair key_pair = Botan::PKCS11::generate_ecdh_keypair( 1061 session, pub_generate_props, priv_generate_props ); 1062 1063 /************ ECDH derive *************/ 1064 1065 Botan::PKCS11::PKCS11_ECDH_KeyPair key_pair_other = Botan::PKCS11::generate_ecdh_keypair( 1066 session, pub_generate_props, priv_generate_props ); 1067 1068 Botan::PK_Key_Agreement ka( key_pair.second, rng, "Raw", "pkcs11" ); 1069 Botan::PK_Key_Agreement kb( key_pair_other.second, rng, "Raw", "pkcs11" ); 1070 1071 Botan::SymmetricKey alice_key = ka.derive_key( 32, 1072 Botan::unlock( Botan::EC2OSP( key_pair_other.first.public_point(), 1073 Botan::PointGFp::UNCOMPRESSED ) ) ); 1074 1075 Botan::SymmetricKey bob_key = kb.derive_key( 32, 1076 Botan::unlock( Botan::EC2OSP( key_pair.first.public_point(), 1077 Botan::PointGFp::UNCOMPRESSED ) ) ); 1078 1079 bool eq = alice_key == bob_key; 1080 1081RNG 1082^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1083 1084The PKCS#11 RNG is defined in ``<botan/p11_randomgenerator.h>``. The class :cpp:class:`PKCS11_RNG` 1085implements the :cpp:class:`Hardware_RNG` interface. 1086 1087.. cpp:class:: PKCS11_RNG : public Hardware_RNG 1088 1089 .. cpp:function:: PKCS11_RNG(Session& session) 1090 1091 A PKCS#11 :cpp:class:`Session` must be passed to instantiate a ``PKCS11_RNG``. 1092 1093 .. cpp:function:: void randomize(uint8_t output[], std::size_t length) override 1094 1095 Calls :cpp:func:`C_GenerateRandom` to generate random data. 1096 1097 .. cpp:function:: void add_entropy(const uint8_t in[], std::size_t length) override 1098 1099 Calls :cpp:func:`C_SeedRandom` to add entropy to the random generation function of the token/middleware. 1100 1101---------- 1102 1103Code example: 1104 1105 .. code-block:: cpp 1106 1107 Botan::PKCS11::PKCS11_RNG p11_rng( session ); 1108 1109 /************ generate random data *************/ 1110 std::vector<uint8_t> random( 20 ); 1111 p11_rng.randomize( random.data(), random.size() ); 1112 1113 /************ add entropy *************/ 1114 Botan::AutoSeeded_RNG auto_rng; 1115 auto auto_rng_random = auto_rng.random_vec( 20 ); 1116 p11_rng.add_entropy( auto_rng_random.data(), auto_rng_random.size() ); 1117 1118 /************ use PKCS#11 RNG to seed HMAC_DRBG *************/ 1119 Botan::HMAC_DRBG drbg( Botan::MessageAuthenticationCode::create( "HMAC(SHA-512)" ), p11_rng ); 1120 drbg.randomize( random.data(), random.size() ); 1121 1122Token Management Functions 1123^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1124 1125The header file ``<botan/p11.h>`` also defines some free functions for token management: 1126 1127 .. cpp:function:: void initialize_token(Slot& slot, const std::string& label, const secure_string& so_pin, const secure_string& pin) 1128 1129 Initializes a token by passing a :cpp:class:`Slot`, a ``label`` and the ``so_pin`` of the security officer. 1130 1131 .. cpp:function:: void change_pin(Slot& slot, const secure_string& old_pin, const secure_string& new_pin) 1132 1133 Change PIN with ``old_pin`` to ``new_pin``. 1134 1135 .. cpp:function:: void change_so_pin(Slot& slot, const secure_string& old_so_pin, const secure_string& new_so_pin) 1136 1137 Change SO_PIN with ``old_so_pin`` to new ``new_so_pin``. 1138 1139 .. cpp:function:: void set_pin(Slot& slot, const secure_string& so_pin, const secure_string& pin) 1140 1141 Sets user ``pin`` with ``so_pin``. 1142 1143---------- 1144 1145Code example: 1146 1147 .. code-block:: cpp 1148 1149 /************ set pin *************/ 1150 1151 Botan::PKCS11::Module module( Middleware_path ); 1152 1153 // only slots with connected token 1154 std::vector<Botan::PKCS11::SlotId> slots = Botan::PKCS11::Slot::get_available_slots( module, true ); 1155 1156 // use first slot 1157 Botan::PKCS11::Slot slot( module, slots.at( 0 ) ); 1158 1159 Botan::PKCS11::secure_string so_pin = { '1', '2', '3', '4', '5', '6', '7', '8' }; 1160 Botan::PKCS11::secure_string pin = { '1', '2', '3', '4', '5', '6' }; 1161 Botan::PKCS11::secure_string test_pin = { '6', '5', '4', '3', '2', '1' }; 1162 1163 // set pin 1164 Botan::PKCS11::set_pin( slot, so_pin, test_pin ); 1165 1166 // change back 1167 Botan::PKCS11::set_pin( slot, so_pin, pin ); 1168 1169 /************ initialize *************/ 1170 Botan::PKCS11::initialize_token( slot, "Botan handbook example", so_pin, pin ); 1171 1172 /************ change pin *************/ 1173 Botan::PKCS11::change_pin( slot, pin, test_pin ); 1174 1175 // change back 1176 Botan::PKCS11::change_pin( slot, test_pin, pin ); 1177 1178 /************ change security officer pin *************/ 1179 Botan::PKCS11::change_so_pin( slot, so_pin, test_pin ); 1180 1181 // change back 1182 Botan::PKCS11::change_so_pin( slot, test_pin, so_pin ); 1183 1184X.509 1185^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1186 1187The header file ``<botan/p11_x509.h>`` defines the property class :cpp:class:`X509_CertificateProperties` 1188and the class :cpp:class:`PKCS11_X509_Certificate`. 1189 1190.. cpp:class:: PKCS11_X509_Certificate : public Object, public X509_Certificate 1191 1192 .. cpp:function:: PKCS11_X509_Certificate(Session& session, ObjectHandle handle) 1193 1194 Allows to use existing certificates on the token by passing a valid :cpp:type:`ObjectHandle`. 1195 1196 .. cpp:function:: PKCS11_X509_Certificate(Session& session, const X509_CertificateProperties& props) 1197 1198 Allows to import an existing X.509 certificate to the token with the :cpp:class:`X509_CertificateProperties` 1199 passed in ``props``. 1200 1201---------- 1202 1203Code example: 1204 1205 .. code-block:: cpp 1206 1207 // load existing certificate 1208 Botan::X509_Certificate root( "test.crt" ); 1209 1210 // set props 1211 Botan::PKCS11::X509_CertificateProperties props( 1212 Botan::DER_Encoder().encode( root.subject_dn() ).get_contents_unlocked(), root.BER_encode() ); 1213 1214 props.set_label( "Botan PKCS#11 test certificate" ); 1215 props.set_private( false ); 1216 props.set_token( true ); 1217 1218 // import 1219 Botan::PKCS11::PKCS11_X509_Certificate pkcs11_cert( session, props ); 1220 1221 // load by handle 1222 Botan::PKCS11::PKCS11_X509_Certificate pkcs11_cert2( session, pkcs11_cert.handle() ); 1223 1224Tests 1225^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1226 1227The PKCS#11 tests are not executed automatically because the depend on an external 1228PKCS#11 module/middleware. The test tool has to be executed with ``--pkcs11-lib=`` 1229followed with the path of the PKCS#11 module and a second argument which controls the 1230PKCS#11 tests that are executed. Passing ``pkcs11`` will execute all PKCS#11 tests but it's 1231also possible to execute only a subset with the following arguments: 1232 1233- pkcs11-ecdh 1234- pkcs11-ecdsa 1235- pkcs11-lowlevel 1236- pkcs11-manage 1237- pkcs11-module 1238- pkcs11-object 1239- pkcs11-rng 1240- pkcs11-rsa 1241- pkcs11-session 1242- pkcs11-slot 1243- pkcs11-x509 1244 1245The following PIN and SO-PIN/PUK values are used in tests: 1246 1247- PIN 123456 1248- SO-PIN/PUK 12345678 1249 1250 .. warning:: 1251 1252 Unlike the CardOS (4.4, 5.0, 5.3), the aforementioned SO-PIN/PUK is 1253 inappropriate for Gemalto (IDPrime MD 3840) cards, as it must be a byte array 1254 of length 24. For this reason some of the tests for Gemalto card involving 1255 SO-PIN will fail. You run into a risk of exceding login attempts and as a 1256 result locking your card! Currently, specifying pin via command-line option 1257 is not implemented, and therefore the desired PIN must be modified in the 1258 header src/tests/test_pkcs11.h: 1259 1260 .. code-block:: cpp 1261 1262 // SO PIN is expected to be set to "12345678" prior to running the tests 1263 const std::string SO_PIN = "12345678"; 1264 const auto SO_PIN_SECVEC = Botan::PKCS11::secure_string(SO_PIN.begin(), SO_PIN.end()); 1265 1266 1267Tested/Supported Smartcards 1268^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1269 1270You are very welcome to contribute your own test results for other testing environments or other cards. 1271 1272 1273Test results 1274 1275+-------------------------------------+-------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+ 1276| Smartcard | Status | OS | Midleware | Botan | Errors | 1277+=====================================+===========================================+===================================================+===================================================+===================================================+===================================================+ 1278| CardOS 4.4 | mostly works | Windows 10, 64-bit, version 1709 | API Version 5.4.9.77 (Cryptoki v2.11) | 2.4.0, Cryptoki v2.40 | [50]_ | 1279+-------------------------------------+-------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+ 1280| CardOS 5.0 | mostly works | Windows 10, 64-bit, version 1709 | API Version 5.4.9.77 (Cryptoki v2.11) | 2.4.0, Cryptoki v2.40 | [51]_ | 1281+-------------------------------------+-------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+ 1282| CardOS 5.3 | mostly works | Windows 10, 64-bit, version 1709 | API Version 5.4.9.77 (Cryptoki v2.11) | 2.4.0, Cryptoki v2.40 | [52]_ | 1283+-------------------------------------+-------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+ 1284| CardOS 5.3 | mostly works | Windows 10, 64-bit, version 1903 | API Version 5.5.1 (Cryptoki v2.11) | 2.12.0 unreleased, Cryptoki v2.40 | [53]_ | 1285+-------------------------------------+-------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+ 1286| Gemalto IDPrime MD 3840 | mostly works | Windows 10, 64-bit, version 1709 | IDGo 800, v1.2.4 (Cryptoki v2.20) | 2.4.0, Cryptoki v2.40 | [54]_ | 1287+-------------------------------------+-------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+ 1288| SoftHSM 2.3.0 (OpenSSL 1.0.2g) | works | Windows 10, 64-bit, version 1709 | Cryptoki v2.40 | 2.4.0, Cryptoki v2.40 | | 1289+-------------------------------------+-------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+ 1290| SoftHSM 2.5.0 (OpenSSL 1.1.1) | works | Windows 10, 64-bit, version 1803 | Cryptoki v2.40 | 2.11.0, Cryptoki v2.40 | | 1291+-------------------------------------+-------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+ 1292 1293.. [50] Failing operations for CardOS 4.4: 1294 1295 - object_copy [20]_ 1296 1297 - rsa_privkey_export [21]_ 1298 - rsa_generate_private_key [22]_ 1299 - rsa_sign_verify [23]_ 1300 1301 - ecdh_privkey_import [3]_ 1302 - ecdh_privkey_export [2]_ 1303 - ecdh_pubkey_import [4]_ 1304 - ecdh_pubkey_export [4]_ 1305 - ecdh_generate_private_key [3]_ 1306 - ecdh_generate_keypair [3]_ 1307 - ecdh_derive [3]_ 1308 1309 - ecdsa_privkey_import [3]_ 1310 - ecdsa_privkey_export [2]_ 1311 - ecdsa_pubkey_import [4]_ 1312 - ecdsa_pubkey_export [4]_ 1313 - ecdsa_generate_private_key [3]_ 1314 - ecdsa_generate_keypair [3]_ 1315 - ecdsa_sign_verify [3]_ 1316 1317 - rng_add_entropy [5]_ 1318 1319 1320.. [51] Failing operations for CardOS 5.0 1321 1322 - object_copy [20]_ 1323 1324 - rsa_privkey_export [21]_ 1325 - rsa_generate_private_key [22]_ 1326 - rsa_sign_verify [23]_ 1327 1328 - ecdh_privkey_export [2]_ 1329 - ecdh_pubkey_import [4]_ 1330 - ecdh_generate_private_key [32]_ 1331 - ecdh_generate_keypair [3]_ 1332 - ecdh_derive [33]_ 1333 1334 - ecdsa_privkey_export [2]_ 1335 - ecdsa_generate_private_key [30]_ 1336 - ecdsa_generate_keypair [30]_ 1337 - ecdsa_sign_verify [30]_ 1338 1339 - rng_add_entropy [5]_ 1340 1341.. [52] Failing operations for CardOS 5.3 1342 1343 - object_copy [20]_ 1344 1345 - rsa_privkey_export [21]_ 1346 - rsa_generate_private_key [22]_ 1347 - rsa_sign_verify [23]_ 1348 1349 - ecdh_privkey_export [2]_ 1350 - ecdh_pubkey_import [6]_ 1351 - ecdh_pubkey_export [6]_ 1352 - ecdh_generate_private_key [30]_ 1353 - ecdh_generate_keypair [31]_ 1354 - ecdh_derive [30]_ 1355 1356 - ecdsa_privkey_export [2]_ 1357 - ecdsa_pubkey_import [6]_ 1358 - ecdsa_pubkey_export [6]_ 1359 - ecdsa_generate_private_key [31]_ 1360 - ecdsa_generate_keypair [31]_ 1361 - ecdsa_sign_verify [34]_ 1362 1363 - rng_add_entropy [5]_ 1364 1365.. [53] Failing operations for CardOS 5.3 (middelware 5.5.1) 1366 1367 - ecdh_privkey_export [2]_ 1368 - ecdh_generate_private_key [35]_ 1369 - ecdsa_privkey_export [2]_ 1370 - ecdsa_generate_private_key [36]_ 1371 - c_copy_object [4]_ 1372 1373 - object_copy [4]_ 1374 1375 - rng_add_entropy [5]_ 1376 1377 - rsa_sign_verify [3]_ 1378 - rsa_privkey_export [2]_ 1379 - rsa_generate_private_key [9]_ 1380 1381.. [54] Failing operations for Gemalto IDPrime MD 3840 1382 1383 - session_login_logout [2]_ 1384 - session_info [2]_ 1385 - set_pin [2]_ 1386 - initialize [2]_ 1387 - change_so_pin [2]_ 1388 1389 - object_copy [20]_ 1390 1391 - rsa_generate_private_key [7]_ 1392 - rsa_encrypt_decrypt [8]_ 1393 - rsa_sign_verify [2]_ 1394 1395 - rng_add_entropy [5]_ 1396 1397Error descriptions 1398 1399.. [2] CKR_ARGUMENTS_BAD (0x7=7) 1400.. [3] CKR_MECHANISM_INVALID (0x70=112) 1401.. [4] CKR_FUNCTION_NOT_SUPPORTED (0x54=84) 1402.. [5] CKR_RANDOM_SEED_NOT_SUPPORTED (0x120=288) 1403.. [6] CKM_X9_42_DH_KEY_PAIR_GEN | CKR_DEVICE_ERROR (0x30=48) 1404.. [7] CKR_TEMPLATE_INCONSISTENT (0xD1=209) 1405.. [8] CKR_ENCRYPTED_DATA_INVALID | CKM_SHA256_RSA_PKCS (0x40=64) 1406.. [9] CKR_TEMPLATE_INCOMPLETE (0xD0=208) 1407 1408.. [20] Test fails due to unsupported copy function (CKR_FUNCTION_NOT_SUPPORTED) 1409.. [21] Generating private key for extraction with property extractable fails (CKR_ARGUMENTS_BAD) 1410.. [22] Generate rsa private key operation fails (CKR_TEMPLATE_INCOMPLETE) 1411.. [23] Raw RSA sign-verify fails (CKR_MECHANISM_INVALID) 1412 1413.. [30] Invalid argument Decoding error: BER: Value truncated 1414.. [31] Invalid argument Decoding error: BER: Length field is to large 1415.. [32] Invalid argument OS2ECP: Unknown format type 155 1416.. [33] Invalid argument OS2ECP: Unknown format type 92 1417.. [34] Invalid argument OS2ECP: Unknown format type 57 1418.. [35] Invalid argument OS2ECP: Unknown format type 82 1419.. [36] Invalid argument OS2ECP: Unknown format type 102 1420