~ubuntu-branches/debian/sid/botan/sid

« back to all changes in this revision

Viewing changes to doc/manual/pkcs11.rst

  • Committer: Package Import Robot
  • Author(s): Laszlo Boszormenyi (GCS)
  • Date: 2018-03-01 22:23:25 UTC
  • mfrom: (1.2.2)
  • Revision ID: package-import@ubuntu.com-20180301222325-7p7vc45gu3hta34d
Tags: 2.4.0-2
* Don't remove .doctrees from the manual if it doesn't exist.
* Don't specify parallel to debhelper.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
.. _pkcs11:
 
2
 
 
3
PKCS#11
 
4
========================================
 
5
 
 
6
.. versionadded:: 1.11.31
 
7
 
 
8
|
 
9
 
 
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.
 
16
 
 
17
   .. note::
 
18
 
 
19
     The Botan PKCS#11 interface is implemented against version v2.40 of the standard.
 
20
 
 
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.
 
26
 
 
27
To use the PKCS#11 implementation the ``pkcs11`` module has to be enabled.
 
28
 
 
29
   .. note::
 
30
 
 
31
      Both PKCS#11 APIs live in the namespace ``Botan::PKCS11``
 
32
 
 
33
.. _pkcs11_low_level:
 
34
 
 
35
Low Level API
 
36
----------------------------------------
 
37
 
 
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.
 
45
 
 
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``.
 
48
 
 
49
Preface
 
50
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
51
 
 
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:
 
55
 
 
56
.. cpp:enum-class:: UserType : CK_USER_TYPE
 
57
 
 
58
   .. cpp:enumerator:: UserType::SO = CKU_SO
 
59
   .. cpp:enumerator:: UserType::User = CKU_USER
 
60
   .. cpp:enumerator:: UserType::ContextSpecific = CKU_CONTEXT_SPECIFIC
 
61
 
 
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:
 
64
 
 
65
.. cpp:type:: FunctionListPtr = CK_FUNCTION_LIST_PTR
 
66
 
 
67
.. rubric:: C-API Wrapping
 
68
 
 
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:
 
71
 
 
72
.. cpp:class:: LowLevel
 
73
 
 
74
   .. cpp:function:: bool C_GetSlotList(Bbool token_present, SlotId* slot_list_ptr, Ulong* count_ptr, ReturnValue* return_value = ThrowException) const
 
75
 
 
76
The :cpp:class:`LowLevel` class calls the PKCS#11 function from the function list of the PKCS#11 module:
 
77
 
 
78
   .. code-block:: c
 
79
 
 
80
      CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)( CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList,
 
81
                                                CK_ULONG_PTR pulCount )
 
82
 
 
83
Where it makes sense there is also an overload of the :cpp:class:`LowLevel` method to make usage easier and safer:
 
84
 
 
85
   .. cpp:function:: bool C_GetSlotList( bool token_present, std::vector<SlotId>& slot_ids, ReturnValue* return_value = ThrowException ) const
 
86
 
 
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.
 
90
 
 
91
Another example is the :cpp:func:`C_InitPIN` overload:
 
92
 
 
93
   .. cpp:function:: template<typename Talloc> bool C_InitPIN( SessionHandle session, const std::vector<uint8_t, TAlloc>& pin, ReturnValue* return_value = ThrowException ) const
 
94
 
 
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.
 
97
 
 
98
Error Handling
 
99
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
100
 
 
101
All possible PKCS#11 return values are represented by the enum class:
 
102
 
 
103
.. cpp:enum-class:: ReturnValue : CK_RV
 
104
 
 
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.
 
112
 
 
113
Getting started
 
114
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
115
 
 
116
An object of this class can be instantiated by providing a :cpp:type:`FunctionListPtr` to the :cpp:class:`LowLevel` constructor:
 
117
 
 
118
   .. cpp:function:: explicit LowLevel(FunctionListPtr ptr)
 
119
 
 
120
The :cpp:class:`LowLevel` class provides a static method to retrieve a :cpp:type:`FunctionListPtr`
 
121
from a PKCS#11 module file:
 
122
 
 
123
   .. cpp:function:: static bool C_GetFunctionList(Dynamically_Loaded_Library& pkcs11_module, FunctionListPtr* function_list_ptr_ptr, ReturnValue* return_value = ThrowException)
 
124
 
 
125
----------
 
126
 
 
127
Code Example: Object Instantiation
 
128
 
 
129
   .. code-block:: cpp
 
130
 
 
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 );
 
135
 
 
136
----------
 
137
 
 
138
Code Example: PKCS#11 Module Initialization
 
139
 
 
140
   .. code-block:: cpp
 
141
 
 
142
      Botan::PKCS11::LowLevel p11_low_level(func_list);
 
143
 
 
144
      Botan::PKCS11::C_InitializeArgs init_args = { nullptr, nullptr, nullptr, nullptr,
 
145
              static_cast<CK_FLAGS>(Botan::PKCS11::Flag::OsLockingOk), nullptr };
 
146
 
 
147
      p11_low_level.C_Initialize(&init_args);
 
148
 
 
149
      // work with the token
 
150
 
 
151
      p11_low_level.C_Finalize(nullptr);
 
152
 
 
153
More code examples can be found in the test suite in the ``test_pkcs11_low_level.cpp`` file.
 
154
 
 
155
.. _pkcs11_high_level:
 
156
 
 
157
High Level API
 
158
----------------------------------------
 
159
 
 
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:
 
162
 
 
163
* Loading/unloading of PKCS#11 modules
 
164
* Initialization of tokens
 
165
* Change of PIN/SO-PIN
 
166
* Session management
 
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
 
175
 
 
176
Module
 
177
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
178
 
 
179
The :cpp:class:`Module` class represents a PKCS#11 shared library (module) and is defined in
 
180
``botan/p11_module.h``.
 
181
 
 
182
It is constructed from a a file path to a PKCS#11 module and optional :cpp:type:`C_InitializeArgs`:
 
183
 
 
184
.. cpp:class:: Module
 
185
 
 
186
   .. code-block:: cpp
 
187
 
 
188
      Module(const std::string& file_path, C_InitializeArgs init_args =
 
189
         { nullptr, nullptr, nullptr, nullptr, static_cast<CK_FLAGS>(Flag::OsLockingOk), nullptr })
 
190
 
 
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.
 
193
 
 
194
There are two more methods in this class. One is for reloading the shared library
 
195
and reinitializing the PKCS#11 module:
 
196
 
 
197
   .. code-block:: cpp
 
198
 
 
199
      void reload(C_InitializeArgs init_args =
 
200
         { nullptr, nullptr, nullptr, nullptr, static_cast< CK_FLAGS >(Flag::OsLockingOk), nullptr });
 
201
 
 
202
The other one is for getting general information about the PKCS#11 module:
 
203
 
 
204
   .. cpp:function:: Info get_info() const
 
205
 
 
206
      This function calls :cpp:func:`C_GetInfo` internally.
 
207
 
 
208
----------
 
209
 
 
210
Code example:
 
211
 
 
212
   .. code-block:: cpp
 
213
 
 
214
      Botan::PKCS11::Module module( "C:\\pkcs11-middleware\\library.dll" );
 
215
 
 
216
      // Sometimes useful if a newly connected token is not detected by the PKCS#11 module
 
217
      module.reload();
 
218
 
 
219
      Botan::PKCS11::Info info = module.get_info();
 
220
 
 
221
      // print library version
 
222
      std::cout << std::to_string( info.libraryVersion.major ) << "."
 
223
         << std::to_string( info.libraryVersion.minor ) << std::endl;
 
224
 
 
225
Slot
 
226
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
227
 
 
228
The :cpp:class:`Slot` class represents a PKCS#11 slot and is defined in
 
229
``botan/p11_slot.h``.
 
230
 
 
231
A PKCS#11 slot is usually a smart card reader that potentially contains a token.
 
232
 
 
233
.. cpp:class:: Slot
 
234
 
 
235
   .. cpp:function:: Slot(Module& module, SlotId slot_id)
 
236
 
 
237
      To instantiate this class a reference to a :cpp:class:`Module` object and a ``slot_id`` have to be passed
 
238
      to the constructor.
 
239
 
 
240
To retrieve available slot ids this class has the following static method:
 
241
 
 
242
   .. cpp:function:: static std::vector<SlotId> get_available_slots(Module& module, bool token_present)
 
243
 
 
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()`.
 
246
 
 
247
Further methods:
 
248
 
 
249
   .. cpp:function:: SlotInfo get_slot_info() const
 
250
 
 
251
      Returns information about the slot. Calls :cpp:func:`C_GetSlotInfo`.
 
252
 
 
253
   .. cpp:function:: TokenInfo get_token_info() const
 
254
 
 
255
      Obtains information about a particular token in the system. Calls :cpp:func:`C_GetTokenInfo`.
 
256
 
 
257
   .. cpp:function:: std::vector<MechanismType> get_mechanism_list() const
 
258
 
 
259
      Obtains a list of mechanism types supported by the slot. Calls :cpp:func:`C_GetMechanismList`.
 
260
 
 
261
   .. cpp:function:: MechanismInfo get_mechanism_info(MechanismType mechanism_type) const
 
262
 
 
263
      Obtains information about a particular mechanism possibly supported by a slot.
 
264
      Calls :cpp:func:`C_GetMechanismInfo`.
 
265
 
 
266
   .. cpp:function:: void initialize(const std::string& label, const secure_string& so_pin) const
 
267
 
 
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.
 
271
 
 
272
----------
 
273
 
 
274
Code example:
 
275
 
 
276
   .. code-block:: cpp
 
277
 
 
278
      // only slots with connected token
 
279
      std::vector<Botan::PKCS11::SlotId> slots = Botan::PKCS11::Slot::get_available_slots( module, true );
 
280
 
 
281
      // use first slot
 
282
      Botan::PKCS11::Slot slot( module, slots.at( 0 ) );
 
283
 
 
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;
 
288
 
 
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;
 
293
 
 
294
      // retrieve all mechanisms supported by the token
 
295
      std::vector<Botan::PKCS11::MechanismType> mechanisms = slot.get_mechanism_list();
 
296
 
 
297
      // retrieve information about a particular mechanism
 
298
      Botan::PKCS11::MechanismInfo mech_info =
 
299
         slot.get_mechanism_info( Botan::PKCS11::MechanismType::RsaPkcsOaep );
 
300
 
 
301
      // maximum RSA key length supported:
 
302
      std::cout << mech_info.ulMaxKeySize << std::endl;
 
303
 
 
304
      // initialize the token
 
305
      Botan::PKCS11::secure_string so_pin( 8, '0' );
 
306
      slot.initialize( "Botan PKCS11 documentation test label", so_pin );
 
307
 
 
308
Session
 
309
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
310
 
 
311
The :cpp:class:`Session` class represents a PKCS#11 session and is defined in ``botan/p11_session.h``.
 
312
 
 
313
A session is a logical connection between an application and a token.
 
314
 
 
315
.. cpp:class:: Session
 
316
 
 
317
There are two constructors to create a new session and one constructor to take ownership
 
318
of an existing session.
 
319
 
 
320
   .. cpp:function:: Session(Slot& slot, bool read_only)
 
321
 
 
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`.
 
325
 
 
326
   .. cpp:function:: Session(Slot& slot, Flags flags, VoidPtr callback_data, Notify notify_callback)
 
327
 
 
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`.
 
330
 
 
331
   .. cpp:function:: Session(Slot& slot, SessionHandle handle)
 
332
 
 
333
      Takes ownership of an existing session by passing :cpp:class:`Slot` and a session ``handle``.
 
334
 
 
335
The destructor calls :cpp:func:`C_Logout` if a user is logged in to this session and always :cpp:func:`C_CloseSession`.
 
336
 
 
337
   .. cpp:function:: SessionHandle release()
 
338
 
 
339
      Returns the released :cpp:type:`SessionHandle`
 
340
 
 
341
   .. cpp:function:: void login(UserType userType, const secure_string& pin)
 
342
 
 
343
      Login to this session by passing :cpp:enum:`UserType` and ``pin``. Calls :cpp:func:`C_Login`.
 
344
 
 
345
   .. cpp:function:: void logoff()
 
346
 
 
347
      Logout from this session. Not mandatory because on destruction of the :cpp:class:`Session` object
 
348
      this is done automatically.
 
349
 
 
350
   .. cpp:function:: SessionInfo get_info() const
 
351
 
 
352
      Returns information about this session. Calls :cpp:func:`C_GetSessionInfo`.
 
353
 
 
354
   .. cpp:function:: void set_pin(const secure_string& old_pin, const secure_string& new_pin) const
 
355
 
 
356
      Calls :cpp:func:`C_SetPIN` to change the PIN of the logged in user using the ``old_pin``.
 
357
 
 
358
   .. cpp:function:: void init_pin(const secure_string& new_pin)
 
359
 
 
360
      Calls :cpp:func:`C_InitPIN` to change or initialize the PIN using the SO_PIN (requires a logged in session).
 
361
 
 
362
----------
 
363
 
 
364
Code example:
 
365
 
 
366
   .. code-block:: cpp
 
367
 
 
368
      // open read only session
 
369
      {
 
370
      Botan::PKCS11::Session read_only_session( slot, true );
 
371
      }
 
372
 
 
373
      // open read write session
 
374
      {
 
375
      Botan::PKCS11::Session read_write_session( slot, false );
 
376
      }
 
377
 
 
378
      // open read write session by passing flags
 
379
      {
 
380
      Botan::PKCS11::Flags flags =
 
381
         Botan::PKCS11::flags( Botan::PKCS11::Flag::SerialSession | Botan::PKCS11::Flag::RwSession );
 
382
 
 
383
      Botan::PKCS11::Session read_write_session( slot, flags, nullptr, nullptr );
 
384
      }
 
385
 
 
386
      // move ownership of a session
 
387
      {
 
388
      Botan::PKCS11::Session session( slot, false );
 
389
      Botan::PKCS11::SessionHandle handle = session.release();
 
390
 
 
391
      Botan::PKCS11::Session session2( slot, handle );
 
392
      }
 
393
 
 
394
      Botan::PKCS11::Session session( slot, false );
 
395
 
 
396
      // get session info
 
397
      Botan::PKCS11::SessionInfo info = session.get_info();
 
398
      std::cout << info.slotID << std::endl;
 
399
 
 
400
      // login
 
401
      Botan::PKCS11::secure_string pin = { '1', '2', '3', '4', '5', '6' };
 
402
      session.login( Botan::PKCS11::UserType::User, pin );
 
403
 
 
404
      // set pin
 
405
      Botan::PKCS11::secure_string new_pin = { '6', '5', '4', '3', '2', '1' };
 
406
      session.set_pin( pin, new_pin );
 
407
 
 
408
      // logoff
 
409
      session.logoff();
 
410
 
 
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 );
 
414
 
 
415
      // change pin to old pin
 
416
      session.init_pin( pin );
 
417
 
 
418
Objects
 
419
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
420
 
 
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``.
 
424
 
 
425
.. cpp:class:: AttributeContainer
 
426
 
 
427
Attributes can be set in an :cpp:class:`AttributeContainer` by various ``add_`` methods:
 
428
 
 
429
   .. cpp:function:: void add_class(ObjectClass object_class)
 
430
 
 
431
      Add a class attribute (:c:macro:`CKA_CLASS` / :cpp:enumerator:`AttributeType::Class`)
 
432
 
 
433
   .. cpp:function:: void add_string(AttributeType attribute, const std::string& value)
 
434
 
 
435
      Add a string attribute (e.g. :c:macro:`CKA_LABEL` / :cpp:enumerator:`AttributeType::Label`).
 
436
 
 
437
   .. cpp:function:: void AttributeContainer::add_binary(AttributeType attribute, const uint8_t* value, size_t length)
 
438
 
 
439
      Add a binary attribute (e.g. :c:macro:`CKA_ID` / :cpp:enumerator:`AttributeType::Id`).
 
440
 
 
441
   .. cpp:function:: template<typename TAlloc> void AttributeContainer::add_binary(AttributeType attribute, const std::vector<uint8_t, TAlloc>& binary)
 
442
 
 
443
      Add a binary attribute by passing a ``vector``/``secure_vector`` (e.g. :c:macro:`CKA_ID` / :cpp:enumerator:`AttributeType::Id`).
 
444
 
 
445
   .. cpp:function:: void AttributeContainer::add_bool(AttributeType attribute, bool value)
 
446
 
 
447
      Add a bool attribute (e.g. :c:macro:`CKA_SENSITIVE` / :cpp:enumerator:`AttributeType::Sensitive`).
 
448
 
 
449
    .. cpp:function:: template<typename T> void AttributeContainer::add_numeric(AttributeType attribute, T value)
 
450
 
 
451
       Add a numeric attribute (e.g. :c:macro:`CKA_MODULUS_BITS` / :cpp:enumerator:`AttributeType::ModulusBits`).
 
452
 
 
453
.. rubric:: Object Properties
 
454
 
 
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.
 
458
 
 
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.
 
461
 
 
462
.. cpp:class:: ObjectProperties : public AttributeContainer
 
463
 
 
464
The constructor is defined as follows:
 
465
 
 
466
   .. cpp:function:: ObjectProperties(ObjectClass object_class)
 
467
 
 
468
      Every PKCS#11 object needs an object class attribute.
 
469
 
 
470
The next level defines the :cpp:class:`StorageObjectProperties` class which inherits from
 
471
:cpp:class:`ObjectProperties`.
 
472
 
 
473
.. cpp:class:: StorageObjectProperties : public ObjectProperties
 
474
 
 
475
The only mandatory attribute is the object class, so the constructor is
 
476
defined as follows:
 
477
 
 
478
   .. cpp:function:: StorageObjectProperties(ObjectClass object_class)
 
479
 
 
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`:
 
482
 
 
483
   .. cpp:function:: void set_label(const std::string& label)
 
484
 
 
485
      Sets the label description of the object (RFC2279 string).
 
486
 
 
487
The remaining hierarchy is defined as follows:
 
488
 
 
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`
 
496
 
 
497
PKCS#11 objects themself are represented by the :cpp:class:`Object` class.
 
498
 
 
499
.. cpp:class:: Object
 
500
 
 
501
Following constructors are defined:
 
502
 
 
503
   .. cpp:function:: Object(Session& session, ObjectHandle handle)
 
504
 
 
505
      Takes ownership over an existing object.
 
506
 
 
507
   .. cpp:function:: Object(Session& session, const ObjectProperties& obj_props)
 
508
 
 
509
      Creates a new object with the :cpp:class:`ObjectProperties` provided in ``obj_props``.
 
510
 
 
511
The other methods are:
 
512
 
 
513
   .. cpp:function:: secure_vector<uint8_t> get_attribute_value(AttributeType attribute) const
 
514
 
 
515
      Returns the value of the given attribute (using :cpp:func:`C_GetAttributeValue`)
 
516
 
 
517
   .. cpp:function:: void set_attribute_value(AttributeType attribute, const secure_vector<uint8_t>& value) const
 
518
 
 
519
      Sets the given value for the attribute (using :cpp:func:`C_SetAttributeValue`)
 
520
 
 
521
   .. cpp:function:: void destroy() const
 
522
 
 
523
      Destroys the object.
 
524
 
 
525
   .. cpp:function:: ObjectHandle copy(const AttributeContainer& modified_attributes) const
 
526
 
 
527
      Allows to copy the object with modified attributes.
 
528
 
 
529
And static methods to search for objects:
 
530
 
 
531
   .. cpp:function:: template<typename T> static std::vector<T> search(Session& session, const std::vector<Attribute>& search_template)
 
532
 
 
533
      Searches for all objects of the given type that match ``search_template``.
 
534
 
 
535
   .. cpp:function:: template<typename T> static std::vector<T> search(Session& session, const std::string& label)
 
536
 
 
537
      Searches for all objects of the given type using the label (:c:macro:`CKA_LABEL`).
 
538
 
 
539
   .. cpp:function:: template<typename T> static std::vector<T> search(Session& session, const std::vector<uint8_t>& id)
 
540
 
 
541
      Searches for all objects of the given type using the id (:c:macro:`CKA_ID`).
 
542
 
 
543
   .. cpp:function:: template<typename T> static std::vector<T> search(Session& session, const std::string& label, const std::vector<uint8_t>& id)
 
544
 
 
545
      Searches for all objects of the given type using the label (:c:macro:`CKA_LABEL`) and id (:c:macro:`CKA_ID`).
 
546
 
 
547
   .. cpp:function:: template<typename T> static std::vector<T> search(Session& session)
 
548
 
 
549
      Searches for all objects of the given type.
 
550
 
 
551
.. rubric:: The ObjectFinder
 
552
 
 
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`.
 
556
 
 
557
.. cpp:class:: ObjectFinder
 
558
 
 
559
The constructor has the following signature:
 
560
 
 
561
   .. cpp:function:: ObjectFinder(Session& session, const std::vector<Attribute>& search_template)
 
562
 
 
563
      A search can be prepared with an :cpp:class:`ObjectSearcher` by passing a :cpp:class:`Session` and a ``search_template``.
 
564
 
 
565
The actual search operation is started by calling the :cpp:func:`find` method:
 
566
 
 
567
   .. cpp:function:: std::vector<ObjectHandle> find(std::uint32_t max_count = 100) const
 
568
 
 
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.
 
571
 
 
572
   .. cpp:function:: void finish()
 
573
 
 
574
      Finishes the search operation manually to allow a new :cpp:class:`ObjectFinder` to exist.
 
575
      Otherwise the search is finished by the destructor.
 
576
 
 
577
----------
 
578
 
 
579
Code example:
 
580
 
 
581
   .. code-block:: cpp
 
582
 
 
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";
 
587
 
 
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() );
 
595
 
 
596
      // create the object
 
597
      Botan::PKCS11::Object data_obj( session, data_obj_props );
 
598
 
 
599
      // get label of this object
 
600
      Botan::PKCS11::secure_string retrieved_label =
 
601
         data_obj.get_attribute_value( Botan::PKCS11::AttributeType::Label );
 
602
 
 
603
      // set a new 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 );
 
606
 
 
607
      // copy the object
 
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 );
 
611
 
 
612
      // search for an object
 
613
      Botan::PKCS11::AttributeContainer search_template;
 
614
      search_template.add_string( Botan::PKCS11::AttributeType::Label, "Botan" );
 
615
      auto found_objs =
 
616
         Botan::PKCS11::Object::search<Botan::PKCS11::Object>( session, search_template.attributes() );
 
617
 
 
618
      // destroy the object
 
619
      data_obj.destroy();
 
620
 
 
621
RSA
 
622
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
623
 
 
624
PKCS#11 RSA support is implemented in ``<botan/p11_rsa.h>``.
 
625
 
 
626
.. rubric:: RSA Public Keys
 
627
 
 
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`.
 
632
 
 
633
.. cpp:class:: PKCS11_RSA_PublicKey : public RSA_PublicKey, public Object
 
634
 
 
635
   .. cpp:function:: PKCS11_RSA_PublicKey(Session& session, ObjectHandle handle)
 
636
 
 
637
      Existing PKCS#11 RSA public keys can be used by providing an :cpp:type:`ObjectHandle` to the
 
638
      constructor.
 
639
 
 
640
   .. cpp:function:: PKCS11_RSA_PublicKey(Session& session, const RSA_PublicKeyImportProperties& pubkey_props)
 
641
 
 
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.
 
644
 
 
645
.. rubric:: RSA Private Keys
 
646
 
 
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.
 
652
 
 
653
.. cpp:class:: PKCS11_RSA_PrivateKey : public Private_Key, public RSA_PublicKey, public Object
 
654
 
 
655
   .. cpp:function:: PKCS11_RSA_PrivateKey(Session& session, ObjectHandle handle)
 
656
 
 
657
      Existing PKCS#11 RSA private keys can be used by providing an :cpp:type:`ObjectHandle` to the
 
658
      constructor.
 
659
 
 
660
   .. cpp:function:: PKCS11_RSA_PrivateKey(Session& session, const RSA_PrivateKeyImportProperties& priv_key_props)
 
661
 
 
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.
 
664
 
 
665
   .. cpp:function:: PKCS11_RSA_PrivateKey(Session& session, uint32_t bits, const RSA_PrivateKeyGenerationProperties& priv_key_props)
 
666
 
 
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``.
 
669
 
 
670
   .. cpp:function:: RSA_PrivateKey export_key() const
 
671
 
 
672
      Returns the exported :cpp:class:`RSA_PrivateKey`.
 
673
 
 
674
PKCS#11 RSA key pairs can be generated with the following free function:
 
675
 
 
676
   .. cpp:function:: PKCS11_RSA_KeyPair PKCS11::generate_rsa_keypair(Session& session, const RSA_PublicKeyGenerationProperties& pub_props, const RSA_PrivateKeyGenerationProperties& priv_props)
 
677
 
 
678
----------
 
679
 
 
680
Code example:
 
681
 
 
682
   .. code-block:: cpp
 
683
 
 
684
      Botan::PKCS11::secure_string pin = { '1', '2', '3', '4', '5', '6' };
 
685
      session.login( Botan::PKCS11::UserType::User, pin );
 
686
 
 
687
      /************ import RSA private key *************/
 
688
 
 
689
      // create private key in software
 
690
      Botan::AutoSeeded_RNG rng;
 
691
      Botan::RSA_PrivateKey priv_key_sw( rng, 2048 );
 
692
 
 
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() );
 
696
 
 
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() );
 
703
 
 
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 );
 
708
 
 
709
      // import
 
710
      Botan::PKCS11::PKCS11_RSA_PrivateKey priv_key( session, priv_import_props );
 
711
 
 
712
      /************ export PKCS#11 RSA private key *************/
 
713
      Botan::RSA_PrivateKey exported = priv_key.export_key();
 
714
 
 
715
      /************ import RSA public key *************/
 
716
 
 
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 );
 
722
 
 
723
      // import
 
724
      Botan::PKCS11::PKCS11_RSA_PublicKey public_key( session, pub_import_props );
 
725
 
 
726
      /************ generate RSA private key *************/
 
727
 
 
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" );
 
734
 
 
735
      Botan::PKCS11::PKCS11_RSA_PrivateKey private_key2( session, 2048, priv_generate_props );
 
736
 
 
737
      /************ generate RSA key pair *************/
 
738
 
 
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 );
 
746
 
 
747
      Botan::PKCS11::PKCS11_RSA_KeyPair rsa_keypair =
 
748
         Botan::PKCS11::generate_rsa_keypair( session, pub_generate_props, priv_generate_props );
 
749
 
 
750
      /************ RSA encrypt *************/
 
751
 
 
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 );
 
755
 
 
756
      /************ RSA decrypt *************/
 
757
 
 
758
      Botan::PK_Decryptor_EME decryptor( rsa_keypair.second, rng, "Raw" );
 
759
      plaintext = decryptor.decrypt( ciphertext );
 
760
 
 
761
      /************ RSA sign *************/
 
762
 
 
763
      Botan::PK_Signer signer( rsa_keypair.second, rng, "EMSA4(SHA-256)", Botan::IEEE_1363 );
 
764
      auto signature = signer.sign_message( plaintext, rng );
 
765
 
 
766
      /************ RSA verify *************/
 
767
 
 
768
      Botan::PK_Verifier verifier( rsa_keypair.first, "EMSA4(SHA-256)", Botan::IEEE_1363 );
 
769
      auto ok = verifier.verify_message( plaintext, signature );
 
770
 
 
771
ECDSA
 
772
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
773
 
 
774
PKCS#11 ECDSA support is implemented in ``<botan/p11_ecdsa.h>``.
 
775
 
 
776
.. rubric:: ECDSA Public Keys
 
777
 
 
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`.
 
782
 
 
783
.. cpp:class:: PKCS11_ECDSA_PublicKey : public PKCS11_EC_PublicKey, public virtual ECDSA_PublicKey
 
784
 
 
785
   .. cpp:function:: PKCS11_ECDSA_PublicKey(Session& session, ObjectHandle handle)
 
786
 
 
787
      Existing PKCS#11 ECDSA private keys can be used by providing an :cpp:type:`ObjectHandle` to the
 
788
      constructor.
 
789
 
 
790
   .. cpp:function:: PKCS11_ECDSA_PublicKey(Session& session, const EC_PublicKeyImportProperties& props)
 
791
 
 
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.
 
794
 
 
795
   .. cpp:function:: ECDSA_PublicKey PKCS11_ECDSA_PublicKey::export_key() const
 
796
 
 
797
      Returns the exported :cpp:class:`ECDSA_PublicKey`.
 
798
 
 
799
.. rubric:: ECDSA Private Keys
 
800
 
 
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`.
 
804
 
 
805
.. cpp:class:: PKCS11_ECDSA_PrivateKey : public PKCS11_EC_PrivateKey
 
806
 
 
807
   .. cpp:function:: PKCS11_ECDSA_PrivateKey(Session& session, ObjectHandle handle)
 
808
 
 
809
      Existing PKCS#11 ECDSA private keys can be used by providing an :cpp:type:`ObjectHandle` to the
 
810
      constructor.
 
811
 
 
812
   .. cpp:function:: PKCS11_ECDSA_PrivateKey(Session& session, const EC_PrivateKeyImportProperties& props)
 
813
 
 
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.
 
816
 
 
817
   .. cpp:function:: PKCS11_ECDSA_PrivateKey(Session& session, const std::vector<uint8_t>& ec_params, const EC_PrivateKeyGenerationProperties& props)
 
818
 
 
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.
 
822
 
 
823
   .. cpp:function:: ECDSA_PrivateKey export_key() const
 
824
 
 
825
      Returns the exported :cpp:class:`ECDSA_PrivateKey`.
 
826
 
 
827
PKCS#11 ECDSA key pairs can be generated with the following free function:
 
828
 
 
829
   .. cpp:function:: PKCS11_ECDSA_KeyPair PKCS11::generate_ecdsa_keypair(Session& session, const EC_PublicKeyGenerationProperties& pub_props, const EC_PrivateKeyGenerationProperties& priv_props)
 
830
 
 
831
----------
 
832
 
 
833
Code example:
 
834
 
 
835
   .. code-block:: cpp
 
836
 
 
837
      Botan::PKCS11::secure_string pin = { '1', '2', '3', '4', '5', '6' };
 
838
      session.login( Botan::PKCS11::UserType::User, pin );
 
839
 
 
840
      /************ import ECDSA private key *************/
 
841
 
 
842
      // create private key in software
 
843
      Botan::AutoSeeded_RNG rng;
 
844
 
 
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 );
 
847
 
 
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() );
 
851
 
 
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 );
 
856
 
 
857
      // label
 
858
      std::string label = "test ECDSA key";
 
859
      priv_import_props.set_label( label );
 
860
 
 
861
      // import to card
 
862
      Botan::PKCS11::PKCS11_ECDSA_PrivateKey priv_key( session, priv_import_props );
 
863
 
 
864
      /************ export PKCS#11 ECDSA private key *************/
 
865
      Botan::ECDSA_PrivateKey priv_exported = priv_key.export_key();
 
866
 
 
867
      /************ import ECDSA public key *************/
 
868
 
 
869
      // import to card
 
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() );
 
873
 
 
874
      pub_import_props.set_token( true );
 
875
      pub_import_props.set_verify( true );
 
876
      pub_import_props.set_private( false );
 
877
 
 
878
      // label
 
879
      label = "test ECDSA pub key";
 
880
      pub_import_props.set_label( label );
 
881
 
 
882
      Botan::PKCS11::PKCS11_ECDSA_PublicKey public_key( session, pub_import_props );
 
883
 
 
884
      /************ export PKCS#11 ECDSA public key *************/
 
885
      Botan::ECDSA_PublicKey pub_exported = public_key.export_key();
 
886
 
 
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 );
 
892
 
 
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 );
 
896
 
 
897
      /************ generate PKCS#11 ECDSA key pair *************/
 
898
 
 
899
      Botan::PKCS11::EC_PublicKeyGenerationProperties pub_generate_props(
 
900
         Botan::EC_Group( "secp256r1" ).DER_encode(Botan::EC_Group_Encoding::EC_DOMPAR_ENC_OID ) );
 
901
 
 
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 );
 
907
 
 
908
      Botan::PKCS11::PKCS11_ECDSA_KeyPair key_pair = Botan::PKCS11::generate_ecdsa_keypair( session,
 
909
         pub_generate_props, priv_generate_props );
 
910
 
 
911
      /************ PKCS#11 ECDSA sign and verify *************/
 
912
 
 
913
      std::vector<uint8_t> plaintext( 20, 0x01 );
 
914
 
 
915
      Botan::PK_Signer signer( key_pair.second, rng, "Raw", Botan::IEEE_1363, "pkcs11" );
 
916
      auto signature = signer.sign_message( plaintext, rng );
 
917
 
 
918
      Botan::PK_Verifier token_verifier( key_pair.first, "Raw", Botan::IEEE_1363, "pkcs11" );
 
919
      bool ecdsa_ok = token_verifier.verify_message( plaintext, signature );
 
920
 
 
921
ECDH
 
922
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
923
 
 
924
PKCS#11 ECDH support is implemented in ``<botan/p11_ecdh.h>``.
 
925
 
 
926
.. rubric:: ECDH Public Keys
 
927
 
 
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`.
 
932
 
 
933
.. cpp:class:: PKCS11_ECDH_PublicKey : public PKCS11_EC_PublicKey
 
934
 
 
935
   .. cpp:function:: PKCS11_ECDH_PublicKey(Session& session, ObjectHandle handle)
 
936
 
 
937
      Existing PKCS#11 ECDH private keys can be used by providing an :cpp:type:`ObjectHandle` to the
 
938
      constructor.
 
939
 
 
940
   .. cpp:function:: PKCS11_ECDH_PublicKey(Session& session, const EC_PublicKeyImportProperties& props)
 
941
 
 
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.
 
944
 
 
945
   .. cpp:function:: ECDH_PublicKey export_key() const
 
946
 
 
947
      Returns the exported :cpp:class:`ECDH_PublicKey`.
 
948
 
 
949
.. rubric:: ECDH Private Keys
 
950
 
 
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`.
 
955
 
 
956
.. cpp:class:: PKCS11_ECDH_PrivateKey : public virtual PKCS11_EC_PrivateKey, public virtual PK_Key_Agreement_Key
 
957
 
 
958
   .. cpp:function:: PKCS11_ECDH_PrivateKey(Session& session, ObjectHandle handle)
 
959
 
 
960
      Existing PKCS#11 ECDH private keys can be used by providing an :cpp:type:`ObjectHandle` to the
 
961
      constructor.
 
962
 
 
963
   .. cpp:function:: PKCS11_ECDH_PrivateKey(Session& session, const EC_PrivateKeyImportProperties& props)
 
964
 
 
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.
 
967
 
 
968
   .. cpp:function:: PKCS11_ECDH_PrivateKey(Session& session, const std::vector<uint8_t>& ec_params, const EC_PrivateKeyGenerationProperties& props)
 
969
 
 
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.
 
973
 
 
974
   .. cpp:function:: ECDH_PrivateKey export_key() const
 
975
 
 
976
      Returns the exported :cpp:class:`ECDH_PrivateKey`.
 
977
 
 
978
PKCS#11 ECDH key pairs can be generated with the following free function:
 
979
 
 
980
.. cpp:function:: PKCS11_ECDH_KeyPair PKCS11::generate_ecdh_keypair(Session& session, const EC_PublicKeyGenerationProperties& pub_props, const EC_PrivateKeyGenerationProperties& priv_props)
 
981
 
 
982
----------
 
983
 
 
984
Code example:
 
985
 
 
986
   .. code-block:: cpp
 
987
 
 
988
      Botan::PKCS11::secure_string pin = { '1', '2', '3', '4', '5', '6' };
 
989
      session.login( Botan::PKCS11::UserType::User, pin );
 
990
 
 
991
      /************ import ECDH private key *************/
 
992
 
 
993
      Botan::AutoSeeded_RNG rng;
 
994
 
 
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 );
 
998
 
 
999
      // set import properties
 
1000
      Botan::PKCS11::EC_PrivateKeyImportProperties priv_import_props(
 
1001
         priv_key_sw.DER_domain(), priv_key_sw.private_value() );
 
1002
 
 
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 );
 
1007
 
 
1008
      // label
 
1009
      std::string label = "test ECDH key";
 
1010
      priv_import_props.set_label( label );
 
1011
 
 
1012
      // import to card
 
1013
      Botan::PKCS11::PKCS11_ECDH_PrivateKey priv_key( session, priv_import_props );
 
1014
 
 
1015
      /************ export ECDH private key *************/
 
1016
      Botan::ECDH_PrivateKey exported = priv_key.export_key();
 
1017
 
 
1018
      /************ import ECDH public key *************/
 
1019
 
 
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() );
 
1024
 
 
1025
      pub_import_props.set_token( true );
 
1026
      pub_import_props.set_private( false );
 
1027
      pub_import_props.set_derive( true );
 
1028
 
 
1029
      // label
 
1030
      label = "test ECDH pub key";
 
1031
      pub_import_props.set_label( label );
 
1032
 
 
1033
      // import
 
1034
      Botan::PKCS11::PKCS11_ECDH_PublicKey pub_key( session, pub_import_props );
 
1035
 
 
1036
      /************ export ECDH private key *************/
 
1037
      Botan::ECDH_PublicKey exported_pub = pub_key.export_key();
 
1038
 
 
1039
      /************ generate ECDH private key *************/
 
1040
 
 
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 );
 
1045
 
 
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 );
 
1049
 
 
1050
      /************ generate ECDH key pair *************/
 
1051
 
 
1052
      Botan::PKCS11::EC_PublicKeyGenerationProperties pub_generate_props(
 
1053
         Botan::EC_Group( "secp256r1" ).DER_encode( Botan::EC_Group_Encoding::EC_DOMPAR_ENC_OID ) );
 
1054
 
 
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 );
 
1060
 
 
1061
      Botan::PKCS11::PKCS11_ECDH_KeyPair key_pair = Botan::PKCS11::generate_ecdh_keypair(
 
1062
         session, pub_generate_props, priv_generate_props );
 
1063
 
 
1064
      /************ ECDH derive *************/
 
1065
 
 
1066
      Botan::PKCS11::PKCS11_ECDH_KeyPair key_pair_other = Botan::PKCS11::generate_ecdh_keypair(
 
1067
         session, pub_generate_props, priv_generate_props );
 
1068
 
 
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" );
 
1071
 
 
1072
      Botan::SymmetricKey alice_key = ka.derive_key( 32,
 
1073
         Botan::unlock( Botan::EC2OSP( key_pair_other.first.public_point(),
 
1074
         Botan::PointGFp::UNCOMPRESSED ) ) );
 
1075
 
 
1076
      Botan::SymmetricKey bob_key = kb.derive_key( 32,
 
1077
         Botan::unlock( Botan::EC2OSP( key_pair.first.public_point(),
 
1078
         Botan::PointGFp::UNCOMPRESSED ) ) );
 
1079
 
 
1080
      bool eq = alice_key == bob_key;
 
1081
 
 
1082
RNG
 
1083
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
1084
 
 
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.
 
1087
 
 
1088
.. cpp:class:: PKCS11_RNG : public Hardware_RNG
 
1089
 
 
1090
   .. cpp:function:: PKCS11_RNG(Session& session)
 
1091
 
 
1092
      A PKCS#11 :cpp:class:`Session` must be passed to instantiate a ``PKCS11_RNG``.
 
1093
 
 
1094
   .. cpp:function:: void randomize(uint8_t output[], std::size_t length) override
 
1095
 
 
1096
      Calls :cpp:func:`C_GenerateRandom` to generate random data.
 
1097
 
 
1098
   .. cpp:function:: void add_entropy(const uint8_t in[], std::size_t length) override
 
1099
 
 
1100
      Calls :cpp:func:`C_SeedRandom` to add entropy to the random generation function of the token/middleware.
 
1101
 
 
1102
----------
 
1103
 
 
1104
Code example:
 
1105
 
 
1106
   .. code-block:: cpp
 
1107
 
 
1108
      Botan::PKCS11::PKCS11_RNG p11_rng( session );
 
1109
 
 
1110
      /************ generate random data *************/
 
1111
      std::vector<uint8_t> random( 20 );
 
1112
      p11_rng.randomize( random.data(), random.size() );
 
1113
 
 
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() );
 
1118
 
 
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() );
 
1122
 
 
1123
Token Management Functions
 
1124
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
1125
 
 
1126
The header file ``<botan/p11.h>`` also defines some free functions for token management:
 
1127
 
 
1128
   .. cpp:function:: void initialize_token(Slot& slot, const std::string& label, const secure_string& so_pin, const secure_string& pin)
 
1129
 
 
1130
      Initializes a token by passing a :cpp:class:`Slot`, a ``label`` and the ``so_pin`` of the security officer.
 
1131
 
 
1132
   .. cpp:function:: void change_pin(Slot& slot, const secure_string& old_pin, const secure_string& new_pin)
 
1133
 
 
1134
      Change PIN with ``old_pin`` to ``new_pin``.
 
1135
 
 
1136
   .. cpp:function:: void change_so_pin(Slot& slot, const secure_string& old_so_pin, const secure_string& new_so_pin)
 
1137
 
 
1138
      Change SO_PIN with ``old_so_pin`` to new ``new_so_pin``.
 
1139
 
 
1140
   .. cpp:function:: void set_pin(Slot& slot, const secure_string& so_pin, const secure_string& pin)
 
1141
 
 
1142
      Sets user ``pin`` with ``so_pin``.
 
1143
 
 
1144
----------
 
1145
 
 
1146
Code example:
 
1147
 
 
1148
   .. code-block:: cpp
 
1149
 
 
1150
      /************ set pin *************/
 
1151
 
 
1152
      Botan::PKCS11::Module module( Middleware_path );
 
1153
 
 
1154
      // only slots with connected token
 
1155
      std::vector<Botan::PKCS11::SlotId> slots = Botan::PKCS11::Slot::get_available_slots( module, true );
 
1156
 
 
1157
      // use first slot
 
1158
      Botan::PKCS11::Slot slot( module, slots.at( 0 ) );
 
1159
 
 
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' };
 
1163
 
 
1164
      // set pin
 
1165
      Botan::PKCS11::set_pin( slot, so_pin, test_pin );
 
1166
 
 
1167
      // change back
 
1168
      Botan::PKCS11::set_pin( slot, so_pin, pin );
 
1169
 
 
1170
      /************ initialize *************/
 
1171
      Botan::PKCS11::initialize_token( slot, "Botan handbook example", so_pin, pin );
 
1172
 
 
1173
      /************ change pin *************/
 
1174
      Botan::PKCS11::change_pin( slot, pin, test_pin );
 
1175
 
 
1176
      // change back
 
1177
      Botan::PKCS11::change_pin( slot, test_pin, pin );
 
1178
 
 
1179
      /************ change security officer pin *************/
 
1180
      Botan::PKCS11::change_so_pin( slot, so_pin, test_pin );
 
1181
 
 
1182
      // change back
 
1183
      Botan::PKCS11::change_so_pin( slot, test_pin, so_pin );
 
1184
 
 
1185
X.509
 
1186
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
1187
 
 
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`.
 
1190
 
 
1191
.. cpp:class:: PKCS11_X509_Certificate : public Object, public X509_Certificate
 
1192
 
 
1193
   .. cpp:function:: PKCS11_X509_Certificate(Session& session, ObjectHandle handle)
 
1194
 
 
1195
      Allows to use existing certificates on the token by passing a valid :cpp:type:`ObjectHandle`.
 
1196
 
 
1197
   .. cpp:function:: PKCS11_X509_Certificate(Session& session, const X509_CertificateProperties& props)
 
1198
 
 
1199
      Allows to import an existing X.509 certificate to the token with the :cpp:class:`X509_CertificateProperties`
 
1200
      passed in ``props``.
 
1201
 
 
1202
----------
 
1203
 
 
1204
Code example:
 
1205
 
 
1206
   .. code-block:: cpp
 
1207
 
 
1208
      // load existing certificate
 
1209
      Botan::X509_Certificate root( "test.crt" );
 
1210
 
 
1211
      // set props
 
1212
      Botan::PKCS11::X509_CertificateProperties props(
 
1213
         Botan::DER_Encoder().encode( root.subject_dn() ).get_contents_unlocked(), root.BER_encode() );
 
1214
 
 
1215
      props.set_label( "Botan PKCS#11 test certificate" );
 
1216
      props.set_private( false );
 
1217
      props.set_token( true );
 
1218
 
 
1219
      // import
 
1220
      Botan::PKCS11::PKCS11_X509_Certificate pkcs11_cert( session, props );
 
1221
 
 
1222
      // load by handle
 
1223
      Botan::PKCS11::PKCS11_X509_Certificate pkcs11_cert2( session, pkcs11_cert.handle() );
 
1224
 
 
1225
Tests
 
1226
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
1227
 
 
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:
 
1233
 
 
1234
- pkcs11-ecdh
 
1235
- pkcs11-ecdsa
 
1236
- pkcs11-lowlevel
 
1237
- pkcs11-manage
 
1238
- pkcs11-module
 
1239
- pkcs11-object
 
1240
- pkcs11-rng
 
1241
- pkcs11-rsa
 
1242
- pkcs11-session
 
1243
- pkcs11-slot
 
1244
- pkcs11-x509