1 /*
2  * Copyright (c) 2009 .SE (The Internet Infrastructure Foundation).
3  * Copyright (c) 2009 NLNet Labs.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #ifndef HSM_H
29 #define HSM_H 1
30 
31 #include <stdint.h>
32 #include <ldns/rbtree.h>
33 #include <pthread.h>
34 
35 #define HSM_MAX_SESSIONS 100
36 /*
37  * Note that currently the MySQL kasp schema limits the number of HSMs to
38  * 127; so to increase it beyond that requires some database changes similar
39  * to when keypairs(id) was increased, see svn r4465.
40  *
41  * Note that this constant also determines the size of the shared PIN memory.
42  * Increasing this size requires any existing memory to be removed and should
43  * be part of a migration script.
44  */
45 #define HSM_MAX_SESSIONS 100
46 
47 #define HSM_MAX_ALGONAME 16
48 
49 #define HSM_ERROR_MSGSIZE 512
50 
51 /* TODO: depends on type and key, or just leave it at current
52  * maximum? */
53 #define HSM_MAX_SIGNATURE_LENGTH 512
54 
55 /* Note that this constant also determines the size of the shared PIN memory.
56  * Increasing this size requires any existing memory to be removed and should
57  * be part of a migration script.
58  */
59 #define HSM_MAX_PIN_LENGTH 255
60 
61 /*! Return codes for some of the functions */
62 /*! These should be different than the list of CKR_ values defined
63  * by pkcs11 (for easier debugging purposes of calling applications)
64  */
65 #define HSM_OK                    0
66 #define HSM_ERROR                 0x10000001
67 #define HSM_PIN_INCORRECT         0x10000002
68 #define HSM_CONFIG_FILE_ERROR     0x10000003
69 #define HSM_REPOSITORY_NOT_FOUND  0x10000004
70 #define HSM_NO_REPOSITORIES       0x10000005
71 #define HSM_MODULE_NOT_FOUND      0x10000006
72 
73 /*! The mode for the PIN callback functions */
74 #define HSM_PIN_FIRST	0	/* Used when getting the PIN for the first time. */
75 #define HSM_PIN_RETRY	1	/* Used when we failed to login the first time. */
76 #define HSM_PIN_SAVE	2	/* The latest PIN can be saved for future use. Called
77 				   after a successful login. */
78 
79 /*! HSM configuration */
80 typedef struct {
81     unsigned int use_pubkey;     /*!< Maintain public keys in HSM */
82     unsigned int allow_extract;  /*!< Generate CKA_EXTRACTABLE private keys */
83 } hsm_config_t;
84 
85 /*! Data type to describe an HSM */
86 typedef struct {
87     unsigned int id;             /*!< HSM numerical identifier */
88     char         *name;          /*!< name of repository */
89     char         *token_label;   /*!< label of the token */
90     char         *path;          /*!< path to PKCS#11 library */
91     void         *handle;        /*!< handle from dlopen()*/
92     void         *sym;           /*!< Function list from dlsym */
93     hsm_config_t *config;        /*!< optional per HSM configuration */
94 } hsm_module_t;
95 
96 /*! HSM Session */
97 typedef struct {
98     hsm_module_t  *module;
99     unsigned long session;
100 } hsm_session_t;
101 
102 /*! HSM Key Pair */
103 typedef struct {
104     char *modulename;   /*!< name of the module, as in hsm_session_t.module.name */
105     unsigned long      private_key;  /*!< private key within module */
106     unsigned long      public_key;   /*!< public key within module */
107 } libhsm_key_t;
108 
109 /*! HSM Key Pair Information */
110 typedef struct {
111   char          *id;             /*!< key id */
112   unsigned long algorithm;       /*!< key algorithm (cast from CKK_*)*/
113   char          *algorithm_name; /*!< key algorithm name */
114   unsigned long keysize;         /*!< key size */
115 } libhsm_key_info_t;
116 
117 /*! HSM Repositories */
118 typedef struct hsm_repository_struct hsm_repository_t;
119 struct hsm_repository_struct {
120     hsm_repository_t* next; /*!< next repository > */
121     char    *name;          /*!< name */
122     char    *module;        /*!< PKCS#11 module */
123     char    *tokenlabel;    /*!< PKCS#11 token label */
124     char    *pin;           /*!< PKCS#11 login credentials */
125     uint8_t require_backup; /*!< require a backup of keys before using new keys */
126     uint8_t use_pubkey;     /*!< use public keys in repository? */
127     unsigned int allow_extract;  /*!< Generate CKA_EXTRACTABLE private keys */
128 };
129 
130 /*! HSM context to keep track of sessions */
131 typedef struct {
132     hsm_session_t *session[HSM_MAX_SESSIONS];  /*!< HSM sessions */
133     size_t        session_count;               /*!< number of configured HSMs */
134 
135     /*!< non-zero if the last operation failed (only the first error will be set) */
136     int error;
137 
138    /*!< static string describing the action we were trying to do
139         when the first error happened */
140     const char *error_action;
141 
142     /*!< static string describing the first error */
143     char error_message[HSM_ERROR_MSGSIZE];
144 
145     ldns_rbtree_t* keycache;
146     pthread_mutex_t *keycache_lock;
147 } hsm_ctx_t;
148 
149 
150 /*! Set HSM Context Error
151 
152 If the ctx is given, and it's error value is still 0, the value will be
153 set to 'error', and the error_message and error_action will be set to
154 the given strings.
155 
156 \param ctx      HSM context
157 \param error    error code
158 \param action   action for which the error occured
159 \param message  error message format string
160 */
161 extern void
162 hsm_ctx_set_error(hsm_ctx_t *ctx, int error, const char *action,
163                  const char *message, ...)
164 #ifdef HAVE___ATTRIBUTE__
165      __attribute__ ((format (printf, 4, 5)))
166 #endif
167      ;
168 
169 /*! Open HSM library
170 
171 \param rlist Repository list.
172 \param pin_callback This function will be called for tokens that have
173                     no PIN configured. The default hsm_prompt_pin() can
174                     be used. If this value is NULL, these tokens will
175                     be skipped.
176 \return 0 if successful, !0 if failed
177 
178 Attaches all HSMs in the repository list, querying for PINs (using the given
179 callback function) if not known.
180 Also creates initial sessions (not part of any context; every API
181 function that takes a context can be passed NULL, in which case the
182 global context will be used) and log into each HSM.
183 */
184 extern int
185 hsm_open2(hsm_repository_t* rlist,
186          char *(pin_callback)(unsigned int, const char *, unsigned int));
187 
188 
189 /*! Create new repository as specified in conf.xml.
190 
191 \param name           Repository name.
192 \param module         PKCS#11 module.
193 \param tokenlabel     PKCS#11 token label.
194 \param pin            PKCS#11 login credentials.
195 \param use_pubkey     Whether to store the public key in the HSM.
196 \return The created repository.
197 */
198 hsm_repository_t *
199 hsm_repository_new(char* name, char* module, char* tokenlabel, char* pin,
200     uint8_t use_pubkey, uint8_t allowextract, uint8_t require_backup);
201 
202 /*! Free configured repositories.
203 
204 \param r Repository list.
205 */
206 void
207 hsm_repository_free(hsm_repository_t* r);
208 
209 /*! Function that queries for a PIN, can be used as callback
210     for hsm_open(). Stores the PIN in the shared memory.
211 
212 \param id Used for identifying the repository. Will have a value between zero and
213           HSM_MAX_SESSIONS.
214 \param repository The repository name will be included in the prompt
215 \param mode The type of mode the function should run in.
216 \return The string the user enters
217 */
218 extern char *
219 hsm_prompt_pin(unsigned int id, const char *repository, unsigned int mode);
220 
221 
222 /*! Function that will check if there is a PIN in the shared memory and returns it.
223 
224 \param id Used for identifying the repository. Will have a value between zero and
225           HSM_MAX_SESSIONS.
226 \param repository The repository name will be included in the prompt
227 \param mode The type of mode the function should run in.
228 \return The string the user enters
229 */
230 extern char *
231 hsm_check_pin(unsigned int id, const char *repository, unsigned int mode);
232 
233 
234 /*! Logout
235 
236     Function that will logout the user by deleting the shared memory and
237     semaphore. Any authenticated process will still be able to interact
238     with the HSM.
239 */
240 extern int
241 hsm_logout_pin(void);
242 
243 
244 /*! Close HSM library
245 
246     Log out and detach from all configured HSMs
247     This cleans up all data for libhsm, and should be the last function
248     called.
249 */
250 extern void
251 hsm_close(void);
252 
253 
254 /*! Create new HSM context
255 
256 Creates a new session for each attached HSM. The returned hsm_ctx_t *
257 can be freed with hsm_destroy_context()
258 */
259 extern hsm_ctx_t *
260 hsm_create_context(void);
261 
262 
263 /*! Check HSM context
264 
265 Check if the associated sessions are still alive.
266 If they are not alive, then try re-open libhsm.
267 
268 \param context HSM context
269 \return 0 if successful, !0 if failed
270 */
271 extern int
272 hsm_check_context();
273 
274 
275 /*! Destroy HSM context
276 
277 \param context HSM context
278 
279 Also destroys any associated sessions.
280 */
281 extern void
282 hsm_destroy_context(hsm_ctx_t *context);
283 
284 extern void
285 libhsm_key_free(libhsm_key_t *key);
286 
287 /*! List all known keys in all attached HSMs
288 
289 After the function has run, the value at count contains the number
290 of keys found.
291 
292 The resulting key list can be freed with libhsm_key_list_free()
293 Alternatively, each individual key structure in the list could be
294 freed with libhsm_key_free()
295 
296 \param context HSM context
297 \param count location to store the number of keys found
298 */
299 extern libhsm_key_t **
300 hsm_list_keys(hsm_ctx_t *context, size_t *count);
301 
302 
303 /*! List all known keys in a HSM
304 
305 After the function has run, the value at count contains the number
306 of keys found.
307 
308 The resulting key list can be freed with libhsm_key_list_free()
309 Alternatively, each individual key structure in the list could be
310 freed with libhsm_key_free()
311 
312 \param context HSM context
313 \param count location to store the number of keys found
314 \param repository repository to list the keys in
315 */
316 extern libhsm_key_t **
317 hsm_list_keys_repository(hsm_ctx_t *context,
318                          size_t *count,
319                          const char *repository);
320 
321 
322 
323 /*! Find a key pair by CKA_ID (as hex string)
324 
325 The returned key structure can be freed with libhsm_key_free()
326 
327 \param context HSM context
328 \param id CKA_ID of key to find (null-terminated
329           string of hex characters)
330 \return key identifier or NULL if not found (or invalid input)
331 */
332 extern libhsm_key_t *
333 hsm_find_key_by_id(hsm_ctx_t *context,
334                    const char *id);
335 
336 /*! Generate new key pair in HSM
337 
338 Keys generated by libhsm will have a 16-byte identifier set as CKA_ID
339 and the hexadecimal representation of it set as CKA_LABEL.
340 Other stuff, like exponent, may be needed here as well.
341 
342 The returned key structure can be freed with libhsm_key_free()
343 
344 \param context HSM context
345 \param repository repository in where to create the key
346 \param keysize Size of RSA key
347 \return return key identifier or NULL if key generation failed
348 */
349 extern libhsm_key_t *
350 hsm_generate_rsa_key(hsm_ctx_t *context,
351                      const char *repository,
352                      unsigned long keysize);
353 
354 /*! Generate new key pair in HSM
355 
356 Keys generated by libhsm will have a 16-byte identifier set as CKA_ID
357 and the hexadecimal representation of it set as CKA_LABEL.
358 
359 The returned key structure can be freed with libhsm_key_free()
360 
361 \param context HSM context
362 \param repository repository in where to create the key
363 \param keysize Size of DSA key
364 \return return key identifier or NULL if key generation failed
365 */
366 extern libhsm_key_t *
367 hsm_generate_dsa_key(hsm_ctx_t *context,
368                      const char *repository,
369                      unsigned long keysize);
370 
371 /*! Generate new key pair in HSM
372 
373 Keys generated by libhsm will have a 16-byte identifier set as CKA_ID
374 and the hexadecimal representation of it set as CKA_LABEL.
375 
376 The returned key structure can be freed with libhsm_key_free()
377 
378 \param context HSM context
379 \param repository repository in where to create the key
380 \return return key identifier or NULL if key generation failed
381 */
382 extern libhsm_key_t *
383 hsm_generate_gost_key(hsm_ctx_t *context,
384                      const char *repository);
385 
386 /*! Generate new key pair in HSM
387 
388 Keys generated by libhsm will have a 16-byte identifier set as CKA_ID
389 and the hexadecimal representation of it set as CKA_LABEL.
390 
391 The returned key structure can be freed with libhsm_key_free()
392 
393 \param context HSM context
394 \param repository repository in where to create the key
395 \param curve which curve to use
396 \return return key identifier or NULL if key generation failed
397 */
398 extern libhsm_key_t *
399 hsm_generate_ecdsa_key(hsm_ctx_t *context,
400                        const char *repository,
401                        const char *curve);
402 
403 /*! Generate new key pair in HSM
404 
405 Keys generated by libhsm will have a 16-byte identifier set as CKA_ID
406 and the hexadecimal representation of it set as CKA_LABEL.
407 
408 The returned key structure can be freed with libhsm_key_free()
409 
410 \param context HSM context
411 \param repository repository in where to create the key
412 \param curve which curve to use
413 \return return key identifier or NULL if key generation failed
414 */
415 libhsm_key_t *
416 hsm_generate_eddsa_key(hsm_ctx_t *context,
417                        const char *repository,
418                        const char *curve);
419 
420 /*! Remove a key pair from HSM
421 
422 When a key is removed, the module pointer is set to NULL, and
423 the public and private key handles are set to 0. The structure still
424 needs to be freed.
425 
426 \param context HSM context
427 \param key Key pair to be removed
428 \return 0 if successful, !0 if failed
429 */
430 extern int
431 hsm_remove_key(hsm_ctx_t *context, libhsm_key_t *key);
432 
433 
434 /*! Free the memory of an array of key structures, as returned by
435 hsm_list_keys()
436 
437 \param key_list The array of keys to free
438 \param count The number of keys in the array
439 */
440 extern void
441 libhsm_key_list_free(libhsm_key_t **key_list, size_t count);
442 
443 
444 /*! Get id as null-terminated hex string using key identifier
445 
446 The returned id is allocated data, and must be free()d by the caller
447 
448 \param context HSM context
449 \param key Key pair to get the ID from
450 \return id of key pair
451 */
452 extern char *
453 hsm_get_key_id(hsm_ctx_t *context,
454                const libhsm_key_t *key);
455 
456 
457 /*! Get extended key information
458 
459 The returned id is allocated data, and must be freed by the caller
460 With libhsm_key_info_free()
461 
462 \param context HSM context
463 \param key Key pair to get information about
464 \return key information
465 */
466 extern libhsm_key_info_t *
467 hsm_get_key_info(hsm_ctx_t *context,
468                  const libhsm_key_t *key);
469 
470 
471 /*! Frees the libhsm_key_info_t structure
472 
473 \param key_info The structure to free
474 */
475 extern void
476 libhsm_key_info_free(libhsm_key_info_t *key_info);
477 
478 /*! Fill a buffer with random data from any attached HSM
479 
480 \param context HSM context
481 \param buffer Buffer to fill with random data
482 \param length Size of random buffer
483 \return 0 if successful, !0 if failed
484 
485 */
486 extern int
487 hsm_random_buffer(hsm_ctx_t *ctx,
488                   unsigned char *buffer,
489                   unsigned long length);
490 
491 
492 /*! Return unsigned 32-bit random number from any attached HSM
493 \param context HSM context
494 \return 32-bit random number, or 0 if no HSM with a random generator is
495                attached
496 */
497 extern uint32_t
498 hsm_random32(hsm_ctx_t *ctx);
499 
500 
501 /*! Return unsigned 64-bit random number from any attached HSM
502 \param context HSM context
503 \return 64-bit random number, or 0 if no HSM with a random generator is
504                attached
505 */
506 extern uint64_t
507 hsm_random64(hsm_ctx_t *ctx);
508 
509 
510 
511 /*
512  * Additional functions for debugging, and non-general use-cases.
513  */
514 
515 /*! Attached a named HSM using a PKCS#11 shared library and
516    optional credentials (may be NULL, but then undefined)
517    This function changes the global state, and is not threadsafe
518 
519 \param repository the name of the repository
520 \param token_label the name of the token to attach
521 \param path the path of the shared PKCS#11 library
522 \param pin the PIN to log into the token
523 \param config optional configuration
524 \return 0 on success, -1 on error
525 */
526 extern int
527 hsm_attach(const char *repository,
528            const char *token_name,
529            const char *path,
530            const char *pin,
531            const hsm_config_t *config);
532 
533 /*! Check whether a named token has been initialized in this context
534 \param ctx HSM context
535 \param token_name The name of the token
536 \return 1 if the token is attached, 0 if not found
537 */
538 extern int
539 hsm_token_attached(hsm_ctx_t *ctx,
540                    const char *repository);
541 
542 /*! Return the current error message
543 
544 The returned message is allocated data, and must be free()d by the caller
545 
546 \param ctx HSM context
547 \return error message string
548 */
549 
550 extern char *
551 hsm_get_error(hsm_ctx_t *gctx);
552 
553 /* a few debug functions for applications */
554 extern void hsm_print_session(hsm_session_t *session);
555 extern void hsm_print_ctx(hsm_ctx_t *ctx);
556 extern void hsm_print_key(hsm_ctx_t *ctx, libhsm_key_t *key);
557 extern void hsm_print_error(hsm_ctx_t *ctx);
558 extern void hsm_print_tokeninfo(hsm_ctx_t *ctx);
559 
560 /* implementation of a key cache per context, needs changing see
561  * OPENDNSSEC-799.
562  */
563 extern void keycache_create(hsm_ctx_t* ctx);
564 extern void keycache_destroy(hsm_ctx_t* ctx);
565 extern const libhsm_key_t* keycache_lookup(hsm_ctx_t* ctx, const char* locator);
566 
567 #endif /* HSM_H */
568