4
========================================
6
.. versionadded:: 1.11.31
10
PKCS#11 is a platform-independent interface for accessing smart cards and
11
hardware security modules (HSM). Vendors of PKCS#11 compatible devices usually
12
provide a so called middleware or "PKCS#11 module" which implements the PKCS#11
13
standard. This middleware translates calls from the platform-independent PKCS#11
14
API to device specific calls. So application developers don't have to write smart card
15
or HSM specific code for each device they want to support.
19
The Botan PKCS#11 interface is implemented against version v2.40 of the standard.
21
Botan wraps the C PKCS#11 API to provide a C++ PKCS#11 interface. This is done in two
22
levels of abstraction: a low level API (see :ref:`pkcs11_low_level`) and a high level API (see :ref:`pkcs11_high_level`). The low level API provides
23
access to all functions that are specified by the standard. The high level API represents
24
an object oriented approach to use PKCS#11 compatible devices but only provides a subset
25
of the functions described in the standard.
27
To use the PKCS#11 implementation the ``pkcs11`` module has to be enabled.
31
Both PKCS#11 APIs live in the namespace ``Botan::PKCS11``
36
----------------------------------------
38
The PKCS#11 standards committee provides header files (``pkcs11.h``, ``pkcs11f.h`` and
39
``pkcs11t.h``) which define the PKCS#11 API in the C programming language. These
40
header files could be used directly to access PKCS#11 compatible smart cards or
41
HSMs. The external header files are shipped with Botan in version v2.4 of the standard. The PKCS#11 low
42
level API wraps the original PKCS#11 API, but still allows to access all functions described in the
43
standard and has the advantage that it is a C++ interface with features like RAII, exceptions
44
and automatic memory management.
46
The low level API is implemented by the :cpp:class:`LowLevel` class and can be accessed by
47
including the header ``botan/p11.h``.
50
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
52
All constants that belong together in the PKCS#11 standard are grouped into C++
53
enum classes. For example the different user types are grouped in the
54
:cpp:enum:`UserType` enumeration:
56
.. cpp:enum-class:: UserType : CK_USER_TYPE
58
.. cpp:enumerator:: UserType::SO = CKU_SO
59
.. cpp:enumerator:: UserType::User = CKU_USER
60
.. cpp:enumerator:: UserType::ContextSpecific = CKU_CONTEXT_SPECIFIC
62
Additionally, all types that are used by the low or high level API are mapped by
63
type aliases to more C++ like names. For instance:
65
.. cpp:type:: FunctionListPtr = CK_FUNCTION_LIST_PTR
67
.. rubric:: C-API Wrapping
69
There is at least one method in the :cpp:class:`LowLevel` class that corresponds to a PKCS#11
70
function. For example the :cpp:func:`C_GetSlotList` method in the :cpp:class:`LowLevel` class is defined as follows:
72
.. cpp:class:: LowLevel
74
.. cpp:function:: bool C_GetSlotList(Bbool token_present, SlotId* slot_list_ptr, Ulong* count_ptr, ReturnValue* return_value = ThrowException) const
76
The :cpp:class:`LowLevel` class calls the PKCS#11 function from the function list of the PKCS#11 module:
80
CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)( CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList,
81
CK_ULONG_PTR pulCount )
83
Where it makes sense there is also an overload of the :cpp:class:`LowLevel` method to make usage easier and safer:
85
.. cpp:function:: bool C_GetSlotList( bool token_present, std::vector<SlotId>& slot_ids, ReturnValue* return_value = ThrowException ) const
87
With this overload the user of this API just has to pass a vector of :cpp:type:`SlotId` instead of pointers
88
to preallocated memory for the slot list and the number of elements. Additionally, there is no need
89
to call the method twice in order to determine the number of elements first.
91
Another example is the :cpp:func:`C_InitPIN` overload:
93
.. cpp:function:: template<typename Talloc> bool C_InitPIN( SessionHandle session, const std::vector<uint8_t, TAlloc>& pin, ReturnValue* return_value = ThrowException ) const
95
The templated ``pin`` parameter allows to pass the PIN as a ``std::vector<uint8_t>`` or a ``secure_vector<uint8_t>``.
96
If used with a ``secure_vector`` it is assured that the memory is securely erased when the ``pin`` object is no longer needed.
99
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
101
All possible PKCS#11 return values are represented by the enum class:
103
.. cpp:enum-class:: ReturnValue : CK_RV
105
All methods of the :cpp:class:`LowLevel` class have a default parameter ``ReturnValue* return_value = ThrowException``.
106
This parameter controls the error handling of all :cpp:class:`LowLevel` methods. The default
107
behaviour ``return_value = ThrowException`` is to throw an exception if the method does
108
not complete successfully. If a non-``NULL`` pointer is passed, ``return_value`` receives the
109
return value of the PKCS#11 function and no exception is thrown. In case ``nullptr`` is
110
passed as ``return_value``, the exact return value is ignored and the method just returns
111
``true`` if the function succeeds and ``false`` otherwise.
114
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
116
An object of this class can be instantiated by providing a :cpp:type:`FunctionListPtr` to the :cpp:class:`LowLevel` constructor:
118
.. cpp:function:: explicit LowLevel(FunctionListPtr ptr)
120
The :cpp:class:`LowLevel` class provides a static method to retrieve a :cpp:type:`FunctionListPtr`
121
from a PKCS#11 module file:
123
.. cpp:function:: static bool C_GetFunctionList(Dynamically_Loaded_Library& pkcs11_module, FunctionListPtr* function_list_ptr_ptr, ReturnValue* return_value = ThrowException)
127
Code Example: Object Instantiation
131
Botan::Dynamically_Loaded_Library pkcs11_module( "C:\\pkcs11-middleware\\library.dll" );
132
Botan::PKCS11::FunctionListPtr func_list = nullptr;
133
Botan::PKCS11::LowLevel::C_GetFunctionList( pkcs11_module, &func_list );
134
Botan::PKCS11::LowLevel p11_low_level( func_list );
138
Code Example: PKCS#11 Module Initialization
142
Botan::PKCS11::LowLevel p11_low_level(func_list);
144
Botan::PKCS11::C_InitializeArgs init_args = { nullptr, nullptr, nullptr, nullptr,
145
static_cast<CK_FLAGS>(Botan::PKCS11::Flag::OsLockingOk), nullptr };
147
p11_low_level.C_Initialize(&init_args);
149
// work with the token
151
p11_low_level.C_Finalize(nullptr);
153
More code examples can be found in the test suite in the ``test_pkcs11_low_level.cpp`` file.
155
.. _pkcs11_high_level:
158
----------------------------------------
160
The high level API provides access to the most commonly used PKCS#11 functionality in an
161
object oriented manner. Functionality of the high level API includes:
163
* Loading/unloading of PKCS#11 modules
164
* Initialization of tokens
165
* Change of PIN/SO-PIN
167
* Random number generation
168
* Enumeration of objects on the token (certificates, public keys, private keys)
169
* Import/export/deletion of certificates
170
* Generation/import/export/deletion of RSA and EC public and private keys
171
* Encryption/decryption using RSA with support for OAEP and PKCS1-v1_5 (and raw)
172
* Signature generation/verification using RSA with support for PSS and PKCS1-v1_5 (and raw)
173
* Signature generation/verification using ECDSA
174
* Key derivation using ECDH
177
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
179
The :cpp:class:`Module` class represents a PKCS#11 shared library (module) and is defined in
180
``botan/p11_module.h``.
182
It is constructed from a a file path to a PKCS#11 module and optional :cpp:type:`C_InitializeArgs`:
184
.. cpp:class:: Module
188
Module(const std::string& file_path, C_InitializeArgs init_args =
189
{ nullptr, nullptr, nullptr, nullptr, static_cast<CK_FLAGS>(Flag::OsLockingOk), nullptr })
191
It loads the shared library and calls :cpp:func:`C_Initialize` with the provided :cpp:type:`C_InitializeArgs`.
192
On destruction of the object :cpp:func:`C_Finalize` is called.
194
There are two more methods in this class. One is for reloading the shared library
195
and reinitializing the PKCS#11 module:
199
void reload(C_InitializeArgs init_args =
200
{ nullptr, nullptr, nullptr, nullptr, static_cast< CK_FLAGS >(Flag::OsLockingOk), nullptr });
202
The other one is for getting general information about the PKCS#11 module:
204
.. cpp:function:: Info get_info() const
206
This function calls :cpp:func:`C_GetInfo` internally.
214
Botan::PKCS11::Module module( "C:\\pkcs11-middleware\\library.dll" );
216
// Sometimes useful if a newly connected token is not detected by the PKCS#11 module
219
Botan::PKCS11::Info info = module.get_info();
221
// print library version
222
std::cout << std::to_string( info.libraryVersion.major ) << "."
223
<< std::to_string( info.libraryVersion.minor ) << std::endl;
226
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
228
The :cpp:class:`Slot` class represents a PKCS#11 slot and is defined in
229
``botan/p11_slot.h``.
231
A PKCS#11 slot is usually a smart card reader that potentially contains a token.
235
.. cpp:function:: Slot(Module& module, SlotId slot_id)
237
To instantiate this class a reference to a :cpp:class:`Module` object and a ``slot_id`` have to be passed
240
To retrieve available slot ids this class has the following static method:
242
.. cpp:function:: static std::vector<SlotId> get_available_slots(Module& module, bool token_present)
244
The parameter ``token_present`` controls whether all slots or only slots with a
245
token attached are returned by this method. This method calls :cpp:func:`C_GetSlotList()`.
249
.. cpp:function:: SlotInfo get_slot_info() const
251
Returns information about the slot. Calls :cpp:func:`C_GetSlotInfo`.
253
.. cpp:function:: TokenInfo get_token_info() const
255
Obtains information about a particular token in the system. Calls :cpp:func:`C_GetTokenInfo`.
257
.. cpp:function:: std::vector<MechanismType> get_mechanism_list() const
259
Obtains a list of mechanism types supported by the slot. Calls :cpp:func:`C_GetMechanismList`.
261
.. cpp:function:: MechanismInfo get_mechanism_info(MechanismType mechanism_type) const
263
Obtains information about a particular mechanism possibly supported by a slot.
264
Calls :cpp:func:`C_GetMechanismInfo`.
266
.. cpp:function:: void initialize(const std::string& label, const secure_string& so_pin) const
268
Calls :cpp:func:`C_InitToken` to initialize the token. The :cpp:func:`label` must not exceed 32 bytes.
269
The current PIN of the security officer must be passed in ``so_pin`` if the token
270
is reinitialized or if it's a factory new token, the ``so_pin`` that is passed will initially be set.
278
// only slots with connected token
279
std::vector<Botan::PKCS11::SlotId> slots = Botan::PKCS11::Slot::get_available_slots( module, true );
282
Botan::PKCS11::Slot slot( module, slots.at( 0 ) );
284
// print firmware version of the slot
285
Botan::PKCS11::SlotInfo slot_info = slot.get_slot_info();
286
std::cout << std::to_string( slot_info.firmwareVersion.major ) << "."
287
<< std::to_string( slot_info.firmwareVersion.minor ) << std::endl;
289
// print firmware version of the token
290
Botan::PKCS11::TokenInfo token_info = slot.get_token_info();
291
std::cout << std::to_string( token_info.firmwareVersion.major ) << "."
292
<< std::to_string( token_info.firmwareVersion.minor ) << std::endl;
294
// retrieve all mechanisms supported by the token
295
std::vector<Botan::PKCS11::MechanismType> mechanisms = slot.get_mechanism_list();
297
// retrieve information about a particular mechanism
298
Botan::PKCS11::MechanismInfo mech_info =
299
slot.get_mechanism_info( Botan::PKCS11::MechanismType::RsaPkcsOaep );
301
// maximum RSA key length supported:
302
std::cout << mech_info.ulMaxKeySize << std::endl;
304
// initialize the token
305
Botan::PKCS11::secure_string so_pin( 8, '0' );
306
slot.initialize( "Botan PKCS11 documentation test label", so_pin );
309
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
311
The :cpp:class:`Session` class represents a PKCS#11 session and is defined in ``botan/p11_session.h``.
313
A session is a logical connection between an application and a token.
315
.. cpp:class:: Session
317
There are two constructors to create a new session and one constructor to take ownership
318
of an existing session.
320
.. cpp:function:: Session(Slot& slot, bool read_only)
322
To initialize a session object a :cpp:class:`Slot` has to be specified on which the session
323
should operate. ``read_only`` specifies whether the session should be read only or read write.
324
Calls :cpp:func:`C_OpenSession`.
326
.. cpp:function:: Session(Slot& slot, Flags flags, VoidPtr callback_data, Notify notify_callback)
328
Creates a new session by passing a :cpp:class:`Slot`, session ``flags``, ``callback_data`` and a
329
``notify_callback``. Calls :cpp:func:`C_OpenSession`.
331
.. cpp:function:: Session(Slot& slot, SessionHandle handle)
333
Takes ownership of an existing session by passing :cpp:class:`Slot` and a session ``handle``.
335
The destructor calls :cpp:func:`C_Logout` if a user is logged in to this session and always :cpp:func:`C_CloseSession`.
337
.. cpp:function:: SessionHandle release()
339
Returns the released :cpp:type:`SessionHandle`
341
.. cpp:function:: void login(UserType userType, const secure_string& pin)
343
Login to this session by passing :cpp:enum:`UserType` and ``pin``. Calls :cpp:func:`C_Login`.
345
.. cpp:function:: void logoff()
347
Logout from this session. Not mandatory because on destruction of the :cpp:class:`Session` object
348
this is done automatically.
350
.. cpp:function:: SessionInfo get_info() const
352
Returns information about this session. Calls :cpp:func:`C_GetSessionInfo`.
354
.. cpp:function:: void set_pin(const secure_string& old_pin, const secure_string& new_pin) const
356
Calls :cpp:func:`C_SetPIN` to change the PIN of the logged in user using the ``old_pin``.
358
.. cpp:function:: void init_pin(const secure_string& new_pin)
360
Calls :cpp:func:`C_InitPIN` to change or initialize the PIN using the SO_PIN (requires a logged in session).
368
// open read only session
370
Botan::PKCS11::Session read_only_session( slot, true );
373
// open read write session
375
Botan::PKCS11::Session read_write_session( slot, false );
378
// open read write session by passing flags
380
Botan::PKCS11::Flags flags =
381
Botan::PKCS11::flags( Botan::PKCS11::Flag::SerialSession | Botan::PKCS11::Flag::RwSession );
383
Botan::PKCS11::Session read_write_session( slot, flags, nullptr, nullptr );
386
// move ownership of a session
388
Botan::PKCS11::Session session( slot, false );
389
Botan::PKCS11::SessionHandle handle = session.release();
391
Botan::PKCS11::Session session2( slot, handle );
394
Botan::PKCS11::Session session( slot, false );
397
Botan::PKCS11::SessionInfo info = session.get_info();
398
std::cout << info.slotID << std::endl;
401
Botan::PKCS11::secure_string pin = { '1', '2', '3', '4', '5', '6' };
402
session.login( Botan::PKCS11::UserType::User, pin );
405
Botan::PKCS11::secure_string new_pin = { '6', '5', '4', '3', '2', '1' };
406
session.set_pin( pin, new_pin );
411
// log in as security officer
412
Botan::PKCS11::secure_string so_pin = { '0', '0', '0', '0', '0', '0', '0', '0' };
413
session.login( Botan::PKCS11::UserType::SO, so_pin );
415
// change pin to old pin
416
session.init_pin( pin );
419
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
421
PKCS#11 objects consist of various attributes (:c:type:`CK_ATTRIBUTE`). For example :c:macro:`CKA_TOKEN`
422
describes if a PKCS#11 object is a session object or a token object. The helper class :cpp:class:`AttributeContainer`
423
helps with storing these attributes. The class is defined in ``botan/p11_object.h``.
425
.. cpp:class:: AttributeContainer
427
Attributes can be set in an :cpp:class:`AttributeContainer` by various ``add_`` methods:
429
.. cpp:function:: void add_class(ObjectClass object_class)
431
Add a class attribute (:c:macro:`CKA_CLASS` / :cpp:enumerator:`AttributeType::Class`)
433
.. cpp:function:: void add_string(AttributeType attribute, const std::string& value)
435
Add a string attribute (e.g. :c:macro:`CKA_LABEL` / :cpp:enumerator:`AttributeType::Label`).
437
.. cpp:function:: void AttributeContainer::add_binary(AttributeType attribute, const uint8_t* value, size_t length)
439
Add a binary attribute (e.g. :c:macro:`CKA_ID` / :cpp:enumerator:`AttributeType::Id`).
441
.. cpp:function:: template<typename TAlloc> void AttributeContainer::add_binary(AttributeType attribute, const std::vector<uint8_t, TAlloc>& binary)
443
Add a binary attribute by passing a ``vector``/``secure_vector`` (e.g. :c:macro:`CKA_ID` / :cpp:enumerator:`AttributeType::Id`).
445
.. cpp:function:: void AttributeContainer::add_bool(AttributeType attribute, bool value)
447
Add a bool attribute (e.g. :c:macro:`CKA_SENSITIVE` / :cpp:enumerator:`AttributeType::Sensitive`).
449
.. cpp:function:: template<typename T> void AttributeContainer::add_numeric(AttributeType attribute, T value)
451
Add a numeric attribute (e.g. :c:macro:`CKA_MODULUS_BITS` / :cpp:enumerator:`AttributeType::ModulusBits`).
453
.. rubric:: Object Properties
455
The PKCS#11 standard defines the mandatory and optional attributes for each object class.
456
The mandatory and optional attribute requirements are mapped in so called property classes.
457
Mandatory attributes are set in the constructor, optional attributes can be set via ``set_`` methods.
459
In the top hierarchy is the :cpp:class:`ObjectProperties` class which inherits from the :cpp:class:`AttributeContainer`.
460
This class represents the common attributes of all PKCS#11 objects.
462
.. cpp:class:: ObjectProperties : public AttributeContainer
464
The constructor is defined as follows:
466
.. cpp:function:: ObjectProperties(ObjectClass object_class)
468
Every PKCS#11 object needs an object class attribute.
470
The next level defines the :cpp:class:`StorageObjectProperties` class which inherits from
471
:cpp:class:`ObjectProperties`.
473
.. cpp:class:: StorageObjectProperties : public ObjectProperties
475
The only mandatory attribute is the object class, so the constructor is
478
.. cpp:function:: StorageObjectProperties(ObjectClass object_class)
480
But in contrast to the :cpp:class:`ObjectProperties` class there are various setter methods. For example to
481
set the :cpp:enumerator:`AttributeType::Label`:
483
.. cpp:function:: void set_label(const std::string& label)
485
Sets the label description of the object (RFC2279 string).
487
The remaining hierarchy is defined as follows:
489
* :cpp:class:`DataObjectProperties` inherits from :cpp:class:`StorageObjectProperties`
490
* :cpp:class:`CertificateProperties` inherits from :cpp:class:`StorageObjectProperties`
491
* :cpp:class:`DomainParameterProperties` inherits from :cpp:class:`StorageObjectProperties`
492
* :cpp:class:`KeyProperties` inherits from :cpp:class:`StorageObjectProperties`
493
* :cpp:class:`PublicKeyProperties` inherits from :cpp:class:`KeyProperties`
494
* :cpp:class:`PrivateKeyProperties` inherits from :cpp:class:`KeyProperties`
495
* :cpp:class:`SecretKeyProperties` inherits from :cpp:class:`KeyProperties`
497
PKCS#11 objects themself are represented by the :cpp:class:`Object` class.
499
.. cpp:class:: Object
501
Following constructors are defined:
503
.. cpp:function:: Object(Session& session, ObjectHandle handle)
505
Takes ownership over an existing object.
507
.. cpp:function:: Object(Session& session, const ObjectProperties& obj_props)
509
Creates a new object with the :cpp:class:`ObjectProperties` provided in ``obj_props``.
511
The other methods are:
513
.. cpp:function:: secure_vector<uint8_t> get_attribute_value(AttributeType attribute) const
515
Returns the value of the given attribute (using :cpp:func:`C_GetAttributeValue`)
517
.. cpp:function:: void set_attribute_value(AttributeType attribute, const secure_vector<uint8_t>& value) const
519
Sets the given value for the attribute (using :cpp:func:`C_SetAttributeValue`)
521
.. cpp:function:: void destroy() const
525
.. cpp:function:: ObjectHandle copy(const AttributeContainer& modified_attributes) const
527
Allows to copy the object with modified attributes.
529
And static methods to search for objects:
531
.. cpp:function:: template<typename T> static std::vector<T> search(Session& session, const std::vector<Attribute>& search_template)
533
Searches for all objects of the given type that match ``search_template``.
535
.. cpp:function:: template<typename T> static std::vector<T> search(Session& session, const std::string& label)
537
Searches for all objects of the given type using the label (:c:macro:`CKA_LABEL`).
539
.. cpp:function:: template<typename T> static std::vector<T> search(Session& session, const std::vector<uint8_t>& id)
541
Searches for all objects of the given type using the id (:c:macro:`CKA_ID`).
543
.. cpp:function:: template<typename T> static std::vector<T> search(Session& session, const std::string& label, const std::vector<uint8_t>& id)
545
Searches for all objects of the given type using the label (:c:macro:`CKA_LABEL`) and id (:c:macro:`CKA_ID`).
547
.. cpp:function:: template<typename T> static std::vector<T> search(Session& session)
549
Searches for all objects of the given type.
551
.. rubric:: The ObjectFinder
553
Another way for searching objects is to use the :cpp:class:`ObjectFinder` class. This class
554
manages calls to the ``C_FindObjects*`` functions: :cpp:func:`C_FindObjectsInit`, :cpp:func:`C_FindObjects`
555
and :cpp:func:`C_FindObjectsFinal`.
557
.. cpp:class:: ObjectFinder
559
The constructor has the following signature:
561
.. cpp:function:: ObjectFinder(Session& session, const std::vector<Attribute>& search_template)
563
A search can be prepared with an :cpp:class:`ObjectSearcher` by passing a :cpp:class:`Session` and a ``search_template``.
565
The actual search operation is started by calling the :cpp:func:`find` method:
567
.. cpp:function:: std::vector<ObjectHandle> find(std::uint32_t max_count = 100) const
569
Starts or continues a search for token and session objects that match a template. ``max_count``
570
specifies the maximum number of search results (object handles) that are returned.
572
.. cpp:function:: void finish()
574
Finishes the search operation manually to allow a new :cpp:class:`ObjectFinder` to exist.
575
Otherwise the search is finished by the destructor.
583
// create an simple data object
584
Botan::secure_vector<uint8_t> value = { 0x00, 0x01 ,0x02, 0x03 };
585
std::size_t id = 1337;
586
std::string label = "test data object";
588
// set properties of the new object
589
Botan::PKCS11::DataObjectProperties data_obj_props;
590
data_obj_props.set_label( label );
591
data_obj_props.set_value( value );
592
data_obj_props.set_token( true );
593
data_obj_props.set_modifiable( true );
594
data_obj_props.set_object_id( Botan::DER_Encoder().encode( id ).get_contents_unlocked() );
597
Botan::PKCS11::Object data_obj( session, data_obj_props );
599
// get label of this object
600
Botan::PKCS11::secure_string retrieved_label =
601
data_obj.get_attribute_value( Botan::PKCS11::AttributeType::Label );
604
Botan::PKCS11::secure_string new_label = { 'B', 'o', 't', 'a', 'n' };
605
data_obj.set_attribute_value( Botan::PKCS11::AttributeType::Label, new_label );
608
Botan::PKCS11::AttributeContainer copy_attributes;
609
copy_attributes.add_string( Botan::PKCS11::AttributeType::Label, "copied object" );
610
Botan::PKCS11::ObjectHandle copied_obj_handle = data_obj.copy( copy_attributes );
612
// search for an object
613
Botan::PKCS11::AttributeContainer search_template;
614
search_template.add_string( Botan::PKCS11::AttributeType::Label, "Botan" );
616
Botan::PKCS11::Object::search<Botan::PKCS11::Object>( session, search_template.attributes() );
618
// destroy the object
622
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
624
PKCS#11 RSA support is implemented in ``<botan/p11_rsa.h>``.
626
.. rubric:: RSA Public Keys
628
PKCS#11 RSA public keys are provided by the class :cpp:class:`PKCS11_RSA_PublicKey`. This class
629
inherits from :cpp:class:`RSA_PublicKey` and :cpp:class:`Object`. Furthermore there are two property classes defined
630
to generate and import RSA public keys analogous to the other property classes described
631
before: :cpp:class:`RSA_PublicKeyGenerationProperties` and :cpp:class:`RSA_PublicKeyImportProperties`.
633
.. cpp:class:: PKCS11_RSA_PublicKey : public RSA_PublicKey, public Object
635
.. cpp:function:: PKCS11_RSA_PublicKey(Session& session, ObjectHandle handle)
637
Existing PKCS#11 RSA public keys can be used by providing an :cpp:type:`ObjectHandle` to the
640
.. cpp:function:: PKCS11_RSA_PublicKey(Session& session, const RSA_PublicKeyImportProperties& pubkey_props)
642
This constructor can be used to import an existing RSA public key with the :cpp:class:`RSA_PublicKeyImportProperties`
643
passed in ``pubkey_props`` to the token.
645
.. rubric:: RSA Private Keys
647
The support for PKCS#11 RSA private keys is implemented in a similar way. There are two property
648
classes: :cpp:class:`RSA_PrivateKeyGenerationProperties` and :cpp:class:`RSA_PrivateKeyImportProperties`. The :cpp:class:`PKCS11_RSA_PrivateKey`
649
class implements the actual support for PKCS#11 RSA private keys. This class inherits from :cpp:class:`Private_Key`,
650
:cpp:class:`RSA_PublicKey` and :cpp:class:`Object`. In contrast to the public key class there is a third constructor
651
to generate private keys directly on the token or in the session and one method to export private keys.
653
.. cpp:class:: PKCS11_RSA_PrivateKey : public Private_Key, public RSA_PublicKey, public Object
655
.. cpp:function:: PKCS11_RSA_PrivateKey(Session& session, ObjectHandle handle)
657
Existing PKCS#11 RSA private keys can be used by providing an :cpp:type:`ObjectHandle` to the
660
.. cpp:function:: PKCS11_RSA_PrivateKey(Session& session, const RSA_PrivateKeyImportProperties& priv_key_props)
662
This constructor can be used to import an existing RSA private key with the :cpp:class:`RSA_PrivateKeyImportProperties`
663
passed in ``priv_key_props`` to the token.
665
.. cpp:function:: PKCS11_RSA_PrivateKey(Session& session, uint32_t bits, const RSA_PrivateKeyGenerationProperties& priv_key_props)
667
Generates a new PKCS#11 RSA private key with bit length provided in ``bits`` and the :cpp:class:`RSA_PrivateKeyGenerationProperties`
668
passed in ``priv_key_props``.
670
.. cpp:function:: RSA_PrivateKey export_key() const
672
Returns the exported :cpp:class:`RSA_PrivateKey`.
674
PKCS#11 RSA key pairs can be generated with the following free function:
676
.. cpp:function:: PKCS11_RSA_KeyPair PKCS11::generate_rsa_keypair(Session& session, const RSA_PublicKeyGenerationProperties& pub_props, const RSA_PrivateKeyGenerationProperties& priv_props)
684
Botan::PKCS11::secure_string pin = { '1', '2', '3', '4', '5', '6' };
685
session.login( Botan::PKCS11::UserType::User, pin );
687
/************ import RSA private key *************/
689
// create private key in software
690
Botan::AutoSeeded_RNG rng;
691
Botan::RSA_PrivateKey priv_key_sw( rng, 2048 );
693
// set the private key import properties
694
Botan::PKCS11::RSA_PrivateKeyImportProperties
695
priv_import_props( priv_key_sw.get_n(), priv_key_sw.get_d() );
697
priv_import_props.set_pub_exponent( priv_key_sw.get_e() );
698
priv_import_props.set_prime_1( priv_key_sw.get_p() );
699
priv_import_props.set_prime_2( priv_key_sw.get_q() );
700
priv_import_props.set_coefficient( priv_key_sw.get_c() );
701
priv_import_props.set_exponent_1( priv_key_sw.get_d1() );
702
priv_import_props.set_exponent_2( priv_key_sw.get_d2() );
704
priv_import_props.set_token( true );
705
priv_import_props.set_private( true );
706
priv_import_props.set_decrypt( true );
707
priv_import_props.set_sign( true );
710
Botan::PKCS11::PKCS11_RSA_PrivateKey priv_key( session, priv_import_props );
712
/************ export PKCS#11 RSA private key *************/
713
Botan::RSA_PrivateKey exported = priv_key.export_key();
715
/************ import RSA public key *************/
717
// set the public key import properties
718
Botan::PKCS11::RSA_PublicKeyImportProperties pub_import_props( priv_key.get_n(), priv_key.get_e() );
719
pub_import_props.set_token( true );
720
pub_import_props.set_encrypt( true );
721
pub_import_props.set_private( false );
724
Botan::PKCS11::PKCS11_RSA_PublicKey public_key( session, pub_import_props );
726
/************ generate RSA private key *************/
728
Botan::PKCS11::RSA_PrivateKeyGenerationProperties priv_generate_props;
729
priv_generate_props.set_token( true );
730
priv_generate_props.set_private( true );
731
priv_generate_props.set_sign( true );
732
priv_generate_props.set_decrypt( true );
733
priv_generate_props.set_label( "BOTAN_TEST_RSA_PRIV_KEY" );
735
Botan::PKCS11::PKCS11_RSA_PrivateKey private_key2( session, 2048, priv_generate_props );
737
/************ generate RSA key pair *************/
739
Botan::PKCS11::RSA_PublicKeyGenerationProperties pub_generate_props( 2048UL );
740
pub_generate_props.set_pub_exponent();
741
pub_generate_props.set_label( "BOTAN_TEST_RSA_PUB_KEY" );
742
pub_generate_props.set_token( true );
743
pub_generate_props.set_encrypt( true );
744
pub_generate_props.set_verify( true );
745
pub_generate_props.set_private( false );
747
Botan::PKCS11::PKCS11_RSA_KeyPair rsa_keypair =
748
Botan::PKCS11::generate_rsa_keypair( session, pub_generate_props, priv_generate_props );
750
/************ RSA encrypt *************/
752
Botan::secure_vector<uint8_t> plaintext = { 0x00, 0x01, 0x02, 0x03 };
753
Botan::PK_Encryptor_EME encryptor( rsa_keypair.first, rng, "Raw" );
754
auto ciphertext = encryptor.encrypt( plaintext, rng );
756
/************ RSA decrypt *************/
758
Botan::PK_Decryptor_EME decryptor( rsa_keypair.second, rng, "Raw" );
759
plaintext = decryptor.decrypt( ciphertext );
761
/************ RSA sign *************/
763
Botan::PK_Signer signer( rsa_keypair.second, rng, "EMSA4(SHA-256)", Botan::IEEE_1363 );
764
auto signature = signer.sign_message( plaintext, rng );
766
/************ RSA verify *************/
768
Botan::PK_Verifier verifier( rsa_keypair.first, "EMSA4(SHA-256)", Botan::IEEE_1363 );
769
auto ok = verifier.verify_message( plaintext, signature );
772
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
774
PKCS#11 ECDSA support is implemented in ``<botan/p11_ecdsa.h>``.
776
.. rubric:: ECDSA Public Keys
778
PKCS#11 ECDSA public keys are provided by the class :cpp:class:`PKCS11_ECDSA_PublicKey`. This class
779
inherits from :cpp:class:`PKCS11_EC_PublicKey` and :cpp:class:`ECDSA_PublicKey`. The necessary property classes
780
are defined in ``<botan/p11_ecc_key.h>``. For public keys there are :cpp:class:`EC_PublicKeyGenerationProperties`
781
and :cpp:class:`EC_PublicKeyImportProperties`.
783
.. cpp:class:: PKCS11_ECDSA_PublicKey : public PKCS11_EC_PublicKey, public virtual ECDSA_PublicKey
785
.. cpp:function:: PKCS11_ECDSA_PublicKey(Session& session, ObjectHandle handle)
787
Existing PKCS#11 ECDSA private keys can be used by providing an :cpp:type:`ObjectHandle` to the
790
.. cpp:function:: PKCS11_ECDSA_PublicKey(Session& session, const EC_PublicKeyImportProperties& props)
792
This constructor can be used to import an existing ECDSA public key with the :cpp:class:`EC_PublicKeyImportProperties`
793
passed in ``props`` to the token.
795
.. cpp:function:: ECDSA_PublicKey PKCS11_ECDSA_PublicKey::export_key() const
797
Returns the exported :cpp:class:`ECDSA_PublicKey`.
799
.. rubric:: ECDSA Private Keys
801
The class :cpp:class:`PKCS11_ECDSA_PrivateKey` inherits from :cpp:class:`PKCS11_EC_PrivateKey` and implements support
802
for PKCS#11 ECDSA private keys. There are two property classes for key generation
803
and import: :cpp:class:`EC_PrivateKeyGenerationProperties` and :cpp:class:`EC_PrivateKeyImportProperties`.
805
.. cpp:class:: PKCS11_ECDSA_PrivateKey : public PKCS11_EC_PrivateKey
807
.. cpp:function:: PKCS11_ECDSA_PrivateKey(Session& session, ObjectHandle handle)
809
Existing PKCS#11 ECDSA private keys can be used by providing an :cpp:type:`ObjectHandle` to the
812
.. cpp:function:: PKCS11_ECDSA_PrivateKey(Session& session, const EC_PrivateKeyImportProperties& props)
814
This constructor can be used to import an existing ECDSA private key with the :cpp:class:`EC_PrivateKeyImportProperties`
815
passed in ``props`` to the token.
817
.. cpp:function:: PKCS11_ECDSA_PrivateKey(Session& session, const std::vector<uint8_t>& ec_params, const EC_PrivateKeyGenerationProperties& props)
819
This constructor can be used to generate a new ECDSA private key with the :cpp:class:`EC_PrivateKeyGenerationProperties`
820
passed in ``props`` on the token. The ``ec_params`` parameter is the DER-encoding of an
821
ANSI X9.62 Parameters value.
823
.. cpp:function:: ECDSA_PrivateKey export_key() const
825
Returns the exported :cpp:class:`ECDSA_PrivateKey`.
827
PKCS#11 ECDSA key pairs can be generated with the following free function:
829
.. cpp:function:: PKCS11_ECDSA_KeyPair PKCS11::generate_ecdsa_keypair(Session& session, const EC_PublicKeyGenerationProperties& pub_props, const EC_PrivateKeyGenerationProperties& priv_props)
837
Botan::PKCS11::secure_string pin = { '1', '2', '3', '4', '5', '6' };
838
session.login( Botan::PKCS11::UserType::User, pin );
840
/************ import ECDSA private key *************/
842
// create private key in software
843
Botan::AutoSeeded_RNG rng;
845
Botan::ECDSA_PrivateKey priv_key_sw( rng, Botan::EC_Group( "secp256r1" ) );
846
priv_key_sw.set_parameter_encoding( Botan::EC_Group_Encoding::EC_DOMPAR_ENC_OID );
848
// set the private key import properties
849
Botan::PKCS11::EC_PrivateKeyImportProperties priv_import_props(
850
priv_key_sw.DER_domain(), priv_key_sw.private_value() );
852
priv_import_props.set_token( true );
853
priv_import_props.set_private( true );
854
priv_import_props.set_sign( true );
855
priv_import_props.set_extractable( true );
858
std::string label = "test ECDSA key";
859
priv_import_props.set_label( label );
862
Botan::PKCS11::PKCS11_ECDSA_PrivateKey priv_key( session, priv_import_props );
864
/************ export PKCS#11 ECDSA private key *************/
865
Botan::ECDSA_PrivateKey priv_exported = priv_key.export_key();
867
/************ import ECDSA public key *************/
870
Botan::PKCS11::EC_PublicKeyImportProperties pub_import_props( priv_key_sw.DER_domain(),
871
Botan::DER_Encoder().encode( EC2OSP( priv_key_sw.public_point(), Botan::PointGFp::UNCOMPRESSED ),
872
Botan::OCTET_STRING ).get_contents_unlocked() );
874
pub_import_props.set_token( true );
875
pub_import_props.set_verify( true );
876
pub_import_props.set_private( false );
879
label = "test ECDSA pub key";
880
pub_import_props.set_label( label );
882
Botan::PKCS11::PKCS11_ECDSA_PublicKey public_key( session, pub_import_props );
884
/************ export PKCS#11 ECDSA public key *************/
885
Botan::ECDSA_PublicKey pub_exported = public_key.export_key();
887
/************ generate PKCS#11 ECDSA private key *************/
888
Botan::PKCS11::EC_PrivateKeyGenerationProperties priv_generate_props;
889
priv_generate_props.set_token( true );
890
priv_generate_props.set_private( true );
891
priv_generate_props.set_sign( true );
893
Botan::PKCS11::PKCS11_ECDSA_PrivateKey pk( session,
894
Botan::EC_Group( "secp256r1" ).DER_encode( Botan::EC_Group_Encoding::EC_DOMPAR_ENC_OID ),
895
priv_generate_props );
897
/************ generate PKCS#11 ECDSA key pair *************/
899
Botan::PKCS11::EC_PublicKeyGenerationProperties pub_generate_props(
900
Botan::EC_Group( "secp256r1" ).DER_encode(Botan::EC_Group_Encoding::EC_DOMPAR_ENC_OID ) );
902
pub_generate_props.set_label( "BOTAN_TEST_ECDSA_PUB_KEY" );
903
pub_generate_props.set_token( true );
904
pub_generate_props.set_verify( true );
905
pub_generate_props.set_private( false );
906
pub_generate_props.set_modifiable( true );
908
Botan::PKCS11::PKCS11_ECDSA_KeyPair key_pair = Botan::PKCS11::generate_ecdsa_keypair( session,
909
pub_generate_props, priv_generate_props );
911
/************ PKCS#11 ECDSA sign and verify *************/
913
std::vector<uint8_t> plaintext( 20, 0x01 );
915
Botan::PK_Signer signer( key_pair.second, rng, "Raw", Botan::IEEE_1363, "pkcs11" );
916
auto signature = signer.sign_message( plaintext, rng );
918
Botan::PK_Verifier token_verifier( key_pair.first, "Raw", Botan::IEEE_1363, "pkcs11" );
919
bool ecdsa_ok = token_verifier.verify_message( plaintext, signature );
922
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
924
PKCS#11 ECDH support is implemented in ``<botan/p11_ecdh.h>``.
926
.. rubric:: ECDH Public Keys
928
PKCS#11 ECDH public keys are provided by the class :cpp:class:`PKCS11_ECDH_PublicKey`. This class
929
inherits from :cpp:class:`PKCS11_EC_PublicKey`. The necessary property classes
930
are defined in ``<botan/p11_ecc_key.h>``. For public keys there are :cpp:class:`EC_PublicKeyGenerationProperties`
931
and :cpp:class:`EC_PublicKeyImportProperties`.
933
.. cpp:class:: PKCS11_ECDH_PublicKey : public PKCS11_EC_PublicKey
935
.. cpp:function:: PKCS11_ECDH_PublicKey(Session& session, ObjectHandle handle)
937
Existing PKCS#11 ECDH private keys can be used by providing an :cpp:type:`ObjectHandle` to the
940
.. cpp:function:: PKCS11_ECDH_PublicKey(Session& session, const EC_PublicKeyImportProperties& props)
942
This constructor can be used to import an existing ECDH public key with the :cpp:class:`EC_PublicKeyImportProperties`
943
passed in ``props`` to the token.
945
.. cpp:function:: ECDH_PublicKey export_key() const
947
Returns the exported :cpp:class:`ECDH_PublicKey`.
949
.. rubric:: ECDH Private Keys
951
The class :cpp:class:`PKCS11_ECDH_PrivateKey` inherits from :cpp:class:`PKCS11_EC_PrivateKey` and :cpp:class:`PK_Key_Agreement_Key`
952
and implements support for PKCS#11 ECDH private keys. There are two
953
property classes. One for key generation and one for import: :cpp:class:`EC_PrivateKeyGenerationProperties` and
954
:cpp:class:`EC_PrivateKeyImportProperties`.
956
.. cpp:class:: PKCS11_ECDH_PrivateKey : public virtual PKCS11_EC_PrivateKey, public virtual PK_Key_Agreement_Key
958
.. cpp:function:: PKCS11_ECDH_PrivateKey(Session& session, ObjectHandle handle)
960
Existing PKCS#11 ECDH private keys can be used by providing an :cpp:type:`ObjectHandle` to the
963
.. cpp:function:: PKCS11_ECDH_PrivateKey(Session& session, const EC_PrivateKeyImportProperties& props)
965
This constructor can be used to import an existing ECDH private key with the :cpp:class:`EC_PrivateKeyImportProperties`
966
passed in ``props`` to the token.
968
.. cpp:function:: PKCS11_ECDH_PrivateKey(Session& session, const std::vector<uint8_t>& ec_params, const EC_PrivateKeyGenerationProperties& props)
970
This constructor can be used to generate a new ECDH private key with the :cpp:class:`EC_PrivateKeyGenerationProperties`
971
passed in ``props`` on the token. The ``ec_params`` parameter is the DER-encoding of an
972
ANSI X9.62 Parameters value.
974
.. cpp:function:: ECDH_PrivateKey export_key() const
976
Returns the exported :cpp:class:`ECDH_PrivateKey`.
978
PKCS#11 ECDH key pairs can be generated with the following free function:
980
.. cpp:function:: PKCS11_ECDH_KeyPair PKCS11::generate_ecdh_keypair(Session& session, const EC_PublicKeyGenerationProperties& pub_props, const EC_PrivateKeyGenerationProperties& priv_props)
988
Botan::PKCS11::secure_string pin = { '1', '2', '3', '4', '5', '6' };
989
session.login( Botan::PKCS11::UserType::User, pin );
991
/************ import ECDH private key *************/
993
Botan::AutoSeeded_RNG rng;
995
// create private key in software
996
Botan::ECDH_PrivateKey priv_key_sw( rng, Botan::EC_Group( "secp256r1" ) );
997
priv_key_sw.set_parameter_encoding( Botan::EC_Group_Encoding::EC_DOMPAR_ENC_OID );
999
// set import properties
1000
Botan::PKCS11::EC_PrivateKeyImportProperties priv_import_props(
1001
priv_key_sw.DER_domain(), priv_key_sw.private_value() );
1003
priv_import_props.set_token( true );
1004
priv_import_props.set_private( true );
1005
priv_import_props.set_derive( true );
1006
priv_import_props.set_extractable( true );
1009
std::string label = "test ECDH key";
1010
priv_import_props.set_label( label );
1013
Botan::PKCS11::PKCS11_ECDH_PrivateKey priv_key( session, priv_import_props );
1015
/************ export ECDH private key *************/
1016
Botan::ECDH_PrivateKey exported = priv_key.export_key();
1018
/************ import ECDH public key *************/
1020
// set import properties
1021
Botan::PKCS11::EC_PublicKeyImportProperties pub_import_props( priv_key_sw.DER_domain(),
1022
Botan::DER_Encoder().encode( EC2OSP( priv_key_sw.public_point(), Botan::PointGFp::UNCOMPRESSED ),
1023
Botan::OCTET_STRING ).get_contents_unlocked() );
1025
pub_import_props.set_token( true );
1026
pub_import_props.set_private( false );
1027
pub_import_props.set_derive( true );
1030
label = "test ECDH pub key";
1031
pub_import_props.set_label( label );
1034
Botan::PKCS11::PKCS11_ECDH_PublicKey pub_key( session, pub_import_props );
1036
/************ export ECDH private key *************/
1037
Botan::ECDH_PublicKey exported_pub = pub_key.export_key();
1039
/************ generate ECDH private key *************/
1041
Botan::PKCS11::EC_PrivateKeyGenerationProperties priv_generate_props;
1042
priv_generate_props.set_token( true );
1043
priv_generate_props.set_private( true );
1044
priv_generate_props.set_derive( true );
1046
Botan::PKCS11::PKCS11_ECDH_PrivateKey priv_key2( session,
1047
Botan::EC_Group( "secp256r1" ).DER_encode( Botan::EC_Group_Encoding::EC_DOMPAR_ENC_OID ),
1048
priv_generate_props );
1050
/************ generate ECDH key pair *************/
1052
Botan::PKCS11::EC_PublicKeyGenerationProperties pub_generate_props(
1053
Botan::EC_Group( "secp256r1" ).DER_encode( Botan::EC_Group_Encoding::EC_DOMPAR_ENC_OID ) );
1055
pub_generate_props.set_label( label + "_PUB_KEY" );
1056
pub_generate_props.set_token( true );
1057
pub_generate_props.set_derive( true );
1058
pub_generate_props.set_private( false );
1059
pub_generate_props.set_modifiable( true );
1061
Botan::PKCS11::PKCS11_ECDH_KeyPair key_pair = Botan::PKCS11::generate_ecdh_keypair(
1062
session, pub_generate_props, priv_generate_props );
1064
/************ ECDH derive *************/
1066
Botan::PKCS11::PKCS11_ECDH_KeyPair key_pair_other = Botan::PKCS11::generate_ecdh_keypair(
1067
session, pub_generate_props, priv_generate_props );
1069
Botan::PK_Key_Agreement ka( key_pair.second, rng, "Raw", "pkcs11" );
1070
Botan::PK_Key_Agreement kb( key_pair_other.second, rng, "Raw", "pkcs11" );
1072
Botan::SymmetricKey alice_key = ka.derive_key( 32,
1073
Botan::unlock( Botan::EC2OSP( key_pair_other.first.public_point(),
1074
Botan::PointGFp::UNCOMPRESSED ) ) );
1076
Botan::SymmetricKey bob_key = kb.derive_key( 32,
1077
Botan::unlock( Botan::EC2OSP( key_pair.first.public_point(),
1078
Botan::PointGFp::UNCOMPRESSED ) ) );
1080
bool eq = alice_key == bob_key;
1083
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1085
The PKCS#11 RNG is defined in ``<botan/p11_randomgenerator.h>``. The class :cpp:class:`PKCS11_RNG`
1086
implements the :cpp:class:`Hardware_RNG` interface.
1088
.. cpp:class:: PKCS11_RNG : public Hardware_RNG
1090
.. cpp:function:: PKCS11_RNG(Session& session)
1092
A PKCS#11 :cpp:class:`Session` must be passed to instantiate a ``PKCS11_RNG``.
1094
.. cpp:function:: void randomize(uint8_t output[], std::size_t length) override
1096
Calls :cpp:func:`C_GenerateRandom` to generate random data.
1098
.. cpp:function:: void add_entropy(const uint8_t in[], std::size_t length) override
1100
Calls :cpp:func:`C_SeedRandom` to add entropy to the random generation function of the token/middleware.
1108
Botan::PKCS11::PKCS11_RNG p11_rng( session );
1110
/************ generate random data *************/
1111
std::vector<uint8_t> random( 20 );
1112
p11_rng.randomize( random.data(), random.size() );
1114
/************ add entropy *************/
1115
Botan::AutoSeeded_RNG auto_rng;
1116
auto auto_rng_random = auto_rng.random_vec( 20 );
1117
p11_rng.add_entropy( auto_rng_random.data(), auto_rng_random.size() );
1119
/************ use PKCS#11 RNG to seed HMAC_DRBG *************/
1120
Botan::HMAC_DRBG drbg( Botan::MessageAuthenticationCode::create( "HMAC(SHA-512)" ), p11_rng );
1121
drbg.randomize( random.data(), random.size() );
1123
Token Management Functions
1124
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1126
The header file ``<botan/p11.h>`` also defines some free functions for token management:
1128
.. cpp:function:: void initialize_token(Slot& slot, const std::string& label, const secure_string& so_pin, const secure_string& pin)
1130
Initializes a token by passing a :cpp:class:`Slot`, a ``label`` and the ``so_pin`` of the security officer.
1132
.. cpp:function:: void change_pin(Slot& slot, const secure_string& old_pin, const secure_string& new_pin)
1134
Change PIN with ``old_pin`` to ``new_pin``.
1136
.. cpp:function:: void change_so_pin(Slot& slot, const secure_string& old_so_pin, const secure_string& new_so_pin)
1138
Change SO_PIN with ``old_so_pin`` to new ``new_so_pin``.
1140
.. cpp:function:: void set_pin(Slot& slot, const secure_string& so_pin, const secure_string& pin)
1142
Sets user ``pin`` with ``so_pin``.
1150
/************ set pin *************/
1152
Botan::PKCS11::Module module( Middleware_path );
1154
// only slots with connected token
1155
std::vector<Botan::PKCS11::SlotId> slots = Botan::PKCS11::Slot::get_available_slots( module, true );
1158
Botan::PKCS11::Slot slot( module, slots.at( 0 ) );
1160
Botan::PKCS11::secure_string so_pin = { '1', '2', '3', '4', '5', '6', '7', '8' };
1161
Botan::PKCS11::secure_string pin = { '1', '2', '3', '4', '5', '6' };
1162
Botan::PKCS11::secure_string test_pin = { '6', '5', '4', '3', '2', '1' };
1165
Botan::PKCS11::set_pin( slot, so_pin, test_pin );
1168
Botan::PKCS11::set_pin( slot, so_pin, pin );
1170
/************ initialize *************/
1171
Botan::PKCS11::initialize_token( slot, "Botan handbook example", so_pin, pin );
1173
/************ change pin *************/
1174
Botan::PKCS11::change_pin( slot, pin, test_pin );
1177
Botan::PKCS11::change_pin( slot, test_pin, pin );
1179
/************ change security officer pin *************/
1180
Botan::PKCS11::change_so_pin( slot, so_pin, test_pin );
1183
Botan::PKCS11::change_so_pin( slot, test_pin, so_pin );
1186
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1188
The header file ``<botan/p11_x509.h>`` defines the property class :cpp:class:`X509_CertificateProperties`
1189
and the class :cpp:class:`PKCS11_X509_Certificate`.
1191
.. cpp:class:: PKCS11_X509_Certificate : public Object, public X509_Certificate
1193
.. cpp:function:: PKCS11_X509_Certificate(Session& session, ObjectHandle handle)
1195
Allows to use existing certificates on the token by passing a valid :cpp:type:`ObjectHandle`.
1197
.. cpp:function:: PKCS11_X509_Certificate(Session& session, const X509_CertificateProperties& props)
1199
Allows to import an existing X.509 certificate to the token with the :cpp:class:`X509_CertificateProperties`
1200
passed in ``props``.
1208
// load existing certificate
1209
Botan::X509_Certificate root( "test.crt" );
1212
Botan::PKCS11::X509_CertificateProperties props(
1213
Botan::DER_Encoder().encode( root.subject_dn() ).get_contents_unlocked(), root.BER_encode() );
1215
props.set_label( "Botan PKCS#11 test certificate" );
1216
props.set_private( false );
1217
props.set_token( true );
1220
Botan::PKCS11::PKCS11_X509_Certificate pkcs11_cert( session, props );
1223
Botan::PKCS11::PKCS11_X509_Certificate pkcs11_cert2( session, pkcs11_cert.handle() );
1226
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1228
The PKCS#11 tests are not executed automatically because the depend on an external
1229
PKCS#11 module/middleware. The test tool has to be executed with ``--pkcs11-lib=``
1230
followed with the path of the PKCS#11 module and a second argument which controls the
1231
PKCS#11 tests that are executed. Passing ``pkcs11`` will execute all PKCS#11 tests but it's
1232
also possible to execute only a subset with the following arguments: