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