1 /*
2  * Copyright (c) 2014 .SE (The Internet Infrastructure Foundation).
3  * Copyright (c) 2014 OpenDNSSEC AB (svb)
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 
29 #include "config.h"
30 
31 #include "db/hsm_key.h"
32 #include "db/policy.h"
33 #include "db/policy_key.h"
34 #include "db/key_data.h"
35 #include "log.h"
36 #include "scheduler/schedule.h"
37 #include "scheduler/task.h"
38 #include "enforcer/enforce_task.h"
39 #include "daemon/engine.h"
40 #include "duration.h"
41 #include "libhsm.h"
42 
43 #include <math.h>
44 #include <pthread.h>
45 #include <ldns/ldns.h>
46 #include <ldns/util.h>
47 
48 #include "hsmkey/hsm_key_factory.h"
49 
50 
51 struct __hsm_key_factory_task {
52     engine_type* engine;
53     /* YBS: I find it scary that these database objects are carried
54      * around in our scheduler. Is that safe? */
55     policy_key_t* policy_key;
56     policy_t* policy;
57     time_t duration;
58     int reschedule_enforce_task;
59 };
60 
61 static pthread_once_t __hsm_key_factory_once = PTHREAD_ONCE_INIT;
62 static pthread_mutex_t* __hsm_key_factory_lock = NULL;
63 
hsm_key_factory_init(void)64 static void hsm_key_factory_init(void) {
65     pthread_mutexattr_t attr;
66 
67     if (!__hsm_key_factory_lock) {
68         if (!(__hsm_key_factory_lock = calloc(1, sizeof(pthread_mutex_t)))
69             || pthread_mutexattr_init(&attr)
70             || pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)
71             || pthread_mutex_init(__hsm_key_factory_lock, &attr))
72         {
73             /* TODO: This should be fatal */
74             ods_log_error("[hsm_key_factory_init] mutex error");
75             if (__hsm_key_factory_lock) {
76                 pthread_mutex_destroy(__hsm_key_factory_lock);
77                 free(__hsm_key_factory_lock);
78                 __hsm_key_factory_lock = NULL;
79             }
80         }
81     }
82 }
83 
hsm_key_factory_deinit(void)84 void hsm_key_factory_deinit(void)
85 {
86     if (__hsm_key_factory_lock) {
87         (void)pthread_mutex_destroy(__hsm_key_factory_lock);
88         free(__hsm_key_factory_lock);
89         __hsm_key_factory_lock = NULL;
90     }
91 }
92 
93 int
hsm_key_factory_generate(engine_type * engine,const db_connection_t * connection,const policy_t * policy,const policy_key_t * policy_key,time_t duration)94 hsm_key_factory_generate(engine_type* engine, const db_connection_t* connection,
95     const policy_t* policy, const policy_key_t* policy_key, time_t duration)
96 {
97     db_clause_list_t* clause_list;
98     hsm_key_t* hsm_key = NULL;
99     size_t num_keys;
100     zone_db_t* zone = NULL;
101     size_t num_zones;
102     ssize_t generate_keys;
103     libhsm_key_t *key = NULL;
104     hsm_ctx_t *hsm_ctx;
105     char* key_id;
106     hsm_repository_t* hsm;
107     char* hsm_err;
108 
109     if (!engine) {
110         return 1;
111     }
112     if (!policy_key) {
113         return 1;
114     }
115 
116     if (!__hsm_key_factory_lock) {
117         pthread_once(&__hsm_key_factory_once, hsm_key_factory_init);
118         if (!__hsm_key_factory_lock) {
119             ods_log_error("[hsm_key_factory_generate] mutex init error");
120             return 1;
121         }
122     }
123     if (pthread_mutex_lock(__hsm_key_factory_lock)) {
124         ods_log_error("[hsm_key_factory_generate] mutex lock error");
125         return 1;
126     }
127 
128     ods_log_debug("[hsm_key_factory_generate] repository %s role %s", policy_key_repository(policy_key), policy_key_role_text(policy_key));
129 
130     /*
131      * Get a count of unused keys that match our policy key to determine how
132      * many keys we need to make if any
133      */
134     if (!(clause_list = db_clause_list_new())
135         || !(hsm_key = hsm_key_new(connection))
136         || !hsm_key_policy_id_clause(clause_list, policy_key_policy_id(policy_key))
137         || !hsm_key_state_clause(clause_list, HSM_KEY_STATE_UNUSED)
138         || !hsm_key_bits_clause(clause_list, policy_key_bits(policy_key))
139         || !hsm_key_algorithm_clause(clause_list, policy_key_algorithm(policy_key))
140         || !hsm_key_role_clause(clause_list, (hsm_key_role_t)policy_key_role(policy_key))
141         || !hsm_key_is_revoked_clause(clause_list, 0)
142         || !hsm_key_key_type_clause(clause_list, HSM_KEY_KEY_TYPE_RSA)
143         || !hsm_key_repository_clause(clause_list, policy_key_repository(policy_key))
144         || hsm_key_count(hsm_key, clause_list, &num_keys))
145     {
146         ods_log_error("[hsm_key_factory_generate] unable to count unused keys, database or memory allocation error");
147         hsm_key_free(hsm_key);
148         db_clause_list_free(clause_list);
149         pthread_mutex_unlock(__hsm_key_factory_lock);
150         return 1;
151     }
152     db_clause_list_free(clause_list);
153     hsm_key_free(hsm_key);
154 
155     /*
156      * Get the count of zones we have for the policy
157      */
158     if (!(clause_list = db_clause_list_new())
159         || !(zone = zone_db_new(connection))
160         || !zone_db_policy_id_clause(clause_list, policy_key_policy_id(policy_key))
161         || zone_db_count(zone, clause_list, &num_zones))
162     {
163         ods_log_error("[hsm_key_factory_generate] unable to count zones for policy, database or memory allocation error");
164         zone_db_free(zone);
165         db_clause_list_free(clause_list);
166         pthread_mutex_unlock(__hsm_key_factory_lock);
167         return 1;
168     }
169     zone_db_free(zone);
170     db_clause_list_free(clause_list);
171 
172     /*
173      * Calculate the number of keys we need to generate now but exit if we do
174      * not have to generate any keys
175      */
176     if (!policy_key_lifetime(policy_key)) {
177         pthread_mutex_unlock(__hsm_key_factory_lock);
178         return 1;
179     }
180     /* OPENDNSSEC-690: this function is called per-zone, and the policy id differs per zone, thus the
181      * keys generated will never be shared.
182      * Additionally, this used to calculate the number of keys to be generated based upon the
183      * duration, times the number of zones.  Not only is this wrong when using shared keys, but
184      * also for non-shared keys, this function would be called per-zone, with a different id for each
185      * zone.
186      */
187     duration = (duration ? duration : engine->config->automatic_keygen_duration);
188     generate_keys = (ssize_t)ceil(duration / (double)policy_key_lifetime(policy_key));
189     if (num_zones == 0 || (ssize_t)num_keys >= generate_keys) {
190         pthread_mutex_unlock(__hsm_key_factory_lock);
191         return 0;
192     }
193 
194     if (policy != NULL) {
195         ods_log_info("%lu zone(s) found on policy \"%s\"", num_zones, policy_name(policy));
196     } else {
197         ods_log_info("%lu zone(s) found on policy <unknown>", num_zones);
198     }
199     ods_log_info("[hsm_key_factory_generate] %lu keys needed for %lu "
200         "zones covering %lld seconds, generating %lu keys for policy %s",
201         generate_keys, num_zones, (long long)duration,
202         (unsigned long)(generate_keys-num_keys), /* This is safe because we checked num_keys < generate_keys */
203         policy_name(policy));
204     generate_keys -= num_keys;
205     ods_log_info("%ld new %s(s) (%d bits) need to be created.", (long) generate_keys, policy_key_role_text(policy_key), policy_key_bits(policy_key));
206 
207     /*
208      * Create a HSM context and check that the repository exists
209      */
210     if (!(hsm_ctx = hsm_create_context())) {
211         pthread_mutex_unlock(__hsm_key_factory_lock);
212         return 1;
213     }
214     if (!hsm_token_attached(hsm_ctx, policy_key_repository(policy_key))) {
215         if ((hsm_err = hsm_get_error(hsm_ctx))) {
216             ods_log_error("[hsm_key_factory_generate] unable to check for repository %s, HSM error: %s", policy_key_repository(policy_key), hsm_err);
217             free(hsm_err);
218         }
219         else {
220             ods_log_error("[hsm_key_factory_generate] unable to find repository %s in HSM", policy_key_repository(policy_key));
221         }
222         hsm_destroy_context(hsm_ctx);
223         pthread_mutex_unlock(__hsm_key_factory_lock);
224         return 1;
225     }
226 
227     /*
228      * Generate a HSM keys
229      */
230     while (generate_keys--) {
231         /*
232          * Find the HSM repository to get the backup configuration
233          */
234         hsm = engine->config->repositories;
235         while (hsm) {
236             if (!strcmp(hsm->name, policy_key_repository(policy_key))) {
237                 break;
238             }
239             hsm = hsm->next;
240         }
241         if (!hsm) {
242             ods_log_error("[hsm_key_factory_generate] unable to find repository %s needed for key generation", policy_key_repository(policy_key));
243             hsm_destroy_context(hsm_ctx);
244             pthread_mutex_unlock(__hsm_key_factory_lock);
245             return 1;
246         }
247 
248         switch(policy_key_algorithm(policy_key)) {
249             case LDNS_DSA: /* */
250                 key = hsm_generate_dsa_key(hsm_ctx, policy_key_repository(policy_key), policy_key_bits(policy_key));
251                 break;
252             case LDNS_RSASHA1:
253             case LDNS_RSASHA1_NSEC3:
254             case LDNS_RSASHA256:
255             case LDNS_RSASHA512:
256                 key = hsm_generate_rsa_key(hsm_ctx, policy_key_repository(policy_key), policy_key_bits(policy_key));
257                 break;
258             case LDNS_ECC_GOST:
259                 key = hsm_generate_gost_key(hsm_ctx, policy_key_repository(policy_key));
260                 break;
261             case LDNS_ECDSAP256SHA256:
262                 key = hsm_generate_ecdsa_key(hsm_ctx, policy_key_repository(policy_key), "P-256");
263                 break;
264             case LDNS_ECDSAP384SHA384:
265                 key = hsm_generate_ecdsa_key(hsm_ctx, policy_key_repository(policy_key), "P-384");
266                 break;
267 #if (LDNS_REVISION >= ((1<<16)|(7<<8)|(0)))
268             case LDNS_ED25519:
269                 key = hsm_generate_eddsa_key(hsm_ctx, policy_key_repository(policy_key), "edwards25519");
270                 break;
271             case LDNS_ED448:
272                 key = hsm_generate_eddsa_key(hsm_ctx, policy_key_repository(policy_key), "edwards448");
273                 break;
274 #endif
275             default:
276                 key = NULL;
277         }
278 
279         if (key) {
280             /*
281              * The key ID is the locator and we check first that we can get it
282              */
283             if (!(key_id = hsm_get_key_id(hsm_ctx, key))) {
284                 if ((hsm_err = hsm_get_error(hsm_ctx))) {
285                     ods_log_error("[hsm_key_factory_generate] unable to get the ID of the key generated, HSM error: %s", hsm_err);
286                     free(hsm_err);
287                 }
288                 else {
289                     ods_log_error("[hsm_key_factory_generate] unable to get the ID of the key generated");
290                 }
291                 libhsm_key_free(key);
292                 hsm_destroy_context(hsm_ctx);
293                 pthread_mutex_unlock(__hsm_key_factory_lock);
294                 return 1;
295             }
296 
297             /*
298              * Create the HSM key (database object)
299              */
300             if (!(hsm_key = hsm_key_new(connection))
301                 || hsm_key_set_algorithm(hsm_key, policy_key_algorithm(policy_key))
302                 || hsm_key_set_backup(hsm_key, (hsm->require_backup ? HSM_KEY_BACKUP_BACKUP_REQUIRED : HSM_KEY_BACKUP_NO_BACKUP))
303                 || hsm_key_set_bits(hsm_key, policy_key_bits(policy_key))
304                 || hsm_key_set_inception(hsm_key, time_now())
305                 || hsm_key_set_key_type(hsm_key, HSM_KEY_KEY_TYPE_RSA)
306                 || hsm_key_set_locator(hsm_key, key_id)
307                 || hsm_key_set_policy_id(hsm_key, policy_key_policy_id(policy_key))
308                 || hsm_key_set_repository(hsm_key, policy_key_repository(policy_key))
309                 || hsm_key_set_role(hsm_key, (hsm_key_role_t)policy_key_role(policy_key))
310                 || hsm_key_set_state(hsm_key, HSM_KEY_STATE_UNUSED)
311                 || hsm_key_create(hsm_key))
312             {
313                 ods_log_error("[hsm_key_factory_generate] hsm key creation failed, database or memory error");
314                 hsm_key_free(hsm_key);
315                 free(key_id);
316                 free(key);
317                 hsm_destroy_context(hsm_ctx);
318                 pthread_mutex_unlock(__hsm_key_factory_lock);
319                 return 1;
320             }
321 
322             ods_log_debug("[hsm_key_factory_generate] generated key %s successfully", key_id);
323 
324             hsm_key_free(hsm_key);
325             free(key_id);
326             libhsm_key_free(key);
327         }
328         else {
329             if ((hsm_err = hsm_get_error(hsm_ctx))) {
330                 ods_log_error("[hsm_key_factory_generate] key generation failed, HSM error: %s", hsm_err);
331                 free(hsm_err);
332             }
333             else {
334                 ods_log_error("[hsm_key_factory_generate] key generation failed");
335             }
336             hsm_destroy_context(hsm_ctx);
337             pthread_mutex_unlock(__hsm_key_factory_lock);
338             return 1;
339         }
340     }
341     hsm_destroy_context(hsm_ctx);
342     pthread_mutex_unlock(__hsm_key_factory_lock);
343     return 0;
344 }
345 
hsm_key_factory_generate_policy(engine_type * engine,const db_connection_t * connection,const policy_t * policy,time_t duration)346 int hsm_key_factory_generate_policy(engine_type* engine, const db_connection_t* connection, const policy_t* policy, time_t duration) {
347     policy_key_list_t* policy_key_list;
348     const policy_key_t* policy_key;
349     int error = 0;
350 
351     if (!engine || !policy || !connection) {
352         return 1;
353     }
354 
355     if (!__hsm_key_factory_lock) {
356         pthread_once(&__hsm_key_factory_once, hsm_key_factory_init);
357         if (!__hsm_key_factory_lock) {
358             ods_log_error("[hsm_key_factory_generate_policy] mutex init error");
359             return 1;
360         }
361     }
362     if (pthread_mutex_lock(__hsm_key_factory_lock)) {
363         ods_log_error("[hsm_key_factory_generate_policy] mutex lock error");
364         return 1;
365     }
366 
367     ods_log_debug("[hsm_key_factory_generate_policy] policy %s", policy_name(policy));
368 
369     /*
370      * Get all policy keys for the specified policy and generate new keys if
371      * needed
372      */
373     if (!(policy_key_list = policy_key_list_new_get_by_policy_id(connection, policy_id(policy)))) {
374         pthread_mutex_unlock(__hsm_key_factory_lock);
375         return 1;
376     }
377 
378     while ((policy_key = policy_key_list_next(policy_key_list))) {
379         error |= hsm_key_factory_generate(engine, connection, policy, policy_key, duration);
380     }
381     policy_key_list_free(policy_key_list);
382     pthread_mutex_unlock(__hsm_key_factory_lock);
383     return error;
384 }
385 
hsm_key_factory_generate_all(engine_type * engine,const db_connection_t * connection,time_t duration)386 int hsm_key_factory_generate_all(engine_type* engine, const db_connection_t* connection, time_t duration) {
387     policy_list_t* policy_list;
388     const policy_t* policy;
389     policy_key_list_t* policy_key_list;
390     const policy_key_t* policy_key;
391     int error;
392 
393     if (!engine || !connection) {
394         return 1;
395     }
396 
397     if (!__hsm_key_factory_lock) {
398         pthread_once(&__hsm_key_factory_once, hsm_key_factory_init);
399         if (!__hsm_key_factory_lock) {
400             ods_log_error("[hsm_key_factory_generate_all] mutex init error");
401             return 1;
402         }
403     }
404     if (pthread_mutex_lock(__hsm_key_factory_lock)) {
405         ods_log_error("[hsm_key_factory_generate_all] mutex lock error");
406         return 1;
407     }
408 
409     ods_log_debug("[hsm_key_factory_generate_all] generating keys");
410 
411     /*
412      * Get all the policies and for each get all the policy keys and generate
413      * new keys for them if needed
414      */
415     if (!(policy_list = policy_list_new_get(connection))) {
416         pthread_mutex_unlock(__hsm_key_factory_lock);
417         return 1;
418     }
419     error = 0;
420     while ((policy = policy_list_next(policy_list))) {
421         if (!(policy_key_list = policy_key_list_new_get_by_policy_id(connection, policy_id(policy)))) {
422             continue;
423         }
424 
425         while ((policy_key = policy_key_list_next(policy_key_list))) {
426             error |= hsm_key_factory_generate(engine, connection, policy, policy_key, duration);
427         }
428         policy_key_list_free(policy_key_list);
429     }
430     policy_list_free(policy_list);
431     pthread_mutex_unlock(__hsm_key_factory_lock);
432     return error;
433 }
434 
435 static time_t
hsm_key_factory_generate_cb(task_type * task,char const * owner,void * userdata,void * context)436 hsm_key_factory_generate_cb(task_type* task, char const *owner, void* userdata, void* context)
437 {
438     struct __hsm_key_factory_task* task2;
439     policy_t* policy;
440     db_connection_t *dbconn = (db_connection_t*) context;
441     (void)owner;
442     int error;
443 
444     if (!userdata) {
445         return schedule_SUCCESS;
446     }
447     task2 = (struct __hsm_key_factory_task*) userdata;
448 
449     if ((policy = policy_new(dbconn)) != NULL) {
450         if (policy_get_by_id(policy, policy_key_policy_id(task2->policy_key))) {
451             policy_free(policy);
452             policy = NULL;
453         }
454     }
455 
456     ods_log_debug("[hsm_key_factory_generate_cb] generate for policy key [duration: %lu]", (unsigned long)task2->duration);
457     error = hsm_key_factory_generate(task2->engine, dbconn, policy, task2->policy_key, task2->duration);
458     ods_log_debug("[hsm_key_factory_generate_cb] generate for policy key done");
459     policy_key_free(task2->policy_key);
460     task2->policy_key = NULL;
461     if (task2->reschedule_enforce_task && policy && !error)
462         enforce_task_flush_policy(task2->engine, dbconn, policy);
463     policy_free(policy);
464     return schedule_SUCCESS;
465 }
466 
467 static time_t
hsm_key_factory_generate_policy_cb(task_type * task,char const * owner,void * userdata,void * context)468 hsm_key_factory_generate_policy_cb(task_type* task, char const *owner, void *userdata,
469     void *context)
470 {
471     struct __hsm_key_factory_task* task2;
472     db_connection_t* dbconn = (db_connection_t*) context;
473     (void)owner;
474     int error;
475 
476     if (!userdata) {
477         return schedule_SUCCESS;
478     }
479     task2 = (struct __hsm_key_factory_task*)userdata;
480 
481     ods_log_debug("[hsm_key_factory_generate_policy_cb] generate for policy [duration: %lu]", (unsigned long) task2->duration);
482     error = hsm_key_factory_generate_policy(task2->engine, dbconn, task2->policy, task2->duration);
483     ods_log_debug("[hsm_key_factory_generate_policy_cb] generate for policy done");
484     if (task2->reschedule_enforce_task && task2->policy && !error)
485         enforce_task_flush_policy(task2->engine, dbconn, task2->policy);
486     return schedule_SUCCESS;
487 }
488 
489 static time_t
hsm_key_factory_generate_all_cb(task_type * task,char const * owner,void * userdata,void * context)490 hsm_key_factory_generate_all_cb(task_type* task, char const *owner, void *userdata,
491     void* context)
492 {
493     struct __hsm_key_factory_task* task2;
494     db_connection_t *dbconn = (db_connection_t *) context;
495     (void)owner;
496     int error;
497 
498     if (!userdata) {
499         return schedule_SUCCESS;
500     }
501     task2 = (struct __hsm_key_factory_task*)userdata;
502 
503     ods_log_debug("[hsm_key_factory_generate_all_cb] generate for all policies [duration: %lu]", (unsigned long)task2->duration);
504     error = hsm_key_factory_generate_all(task2->engine, dbconn, task2->duration);
505     ods_log_debug("[hsm_key_factory_generate_all_cb] generate for all policies done");
506     if (task2->reschedule_enforce_task && !error)
507         enforce_task_flush_all(task2->engine, dbconn);
508     return schedule_SUCCESS;
509 }
510 
511 /**
512  * Schedule a task to generate keys for a specific policy key.
513  * \param[in] engine an engine_type.
514  * \prama[in] policy_key_orig a policy_key_t pointer to the policy key we will
515  * generate keys for.
516  * \param[in] duration a time_t specifying the duration to generate keys from,
517  * if its zero then the duration from conf.xml is taken.
518  * \return non-zero on error.
519  */
520 static int
hsm_key_factory_schedule_generate(engine_type * engine,const policy_key_t * policy_key_orig,time_t duration,int reschedule_enforce_task)521 hsm_key_factory_schedule_generate(engine_type* engine,
522     const policy_key_t* policy_key_orig, time_t duration,
523     int reschedule_enforce_task)
524 {
525     policy_key_t* policy_key;
526     task_type* task;
527     struct __hsm_key_factory_task* task2 = NULL;
528 
529     if (!(task2 = calloc(1, sizeof(struct __hsm_key_factory_task)))) {
530         return 1;
531     }
532     if (!(policy_key = policy_key_new_copy(policy_key_orig))) {
533         free(task2);
534         return 1;
535     }
536 
537     task2->engine = engine;
538     task2->duration = duration;
539     task2->policy_key = policy_key;
540     task2->policy = NULL;
541     task2->reschedule_enforce_task = reschedule_enforce_task;
542 
543     task = task_create(strdup("hsm_key_factory_schedule_generation"),
544         TASK_CLASS_ENFORCER, TASK_TYPE_HSMKEYGEN,
545         hsm_key_factory_generate_cb, task2,
546         free, time_now());
547 
548     if (schedule_task(engine->taskq, task, 1, 0) != ODS_STATUS_OK) {
549         if (!task) {
550             free(task2);
551             policy_key_free(policy_key);
552         }
553         task_destroy(task);
554         return 1;
555     }
556     return 0;
557 }
558 
559 int
hsm_key_factory_schedule_generate_policy(engine_type * engine,const policy_t * policy_orig,time_t duration)560 hsm_key_factory_schedule_generate_policy(engine_type* engine,
561     const policy_t* policy_orig, time_t duration)
562 {
563     policy_t* policy;
564     task_type* task;
565     struct __hsm_key_factory_task* task2 = NULL;
566 
567     if (!(task2 = calloc(1, sizeof(struct __hsm_key_factory_task)))) {
568         return 1;
569     }
570     if (!(policy = policy_new_copy(policy_orig))) {
571         free(task2);
572         return 1;
573     }
574 
575     task2->engine = engine;
576     task2->duration = duration;
577     task2->policy_key = NULL;
578     task2->policy = policy;
579     task2->reschedule_enforce_task = 1;
580 
581     task = task_create(strdup("hsm_key_factory_schedule_generation_policy"),
582         TASK_CLASS_ENFORCER, TASK_TYPE_HSMKEYGEN,
583         hsm_key_factory_generate_policy_cb, task2,
584         free, time_now());
585 
586     if (schedule_task(engine->taskq, task, 1, 0) != ODS_STATUS_OK) {
587         if (!task) {
588             free(task2);
589             policy_free(policy);
590         }
591         task_destroy(task);
592         return 1;
593     }
594     return 0;
595 }
596 
597 int
hsm_key_factory_schedule_generate_all(engine_type * engine,time_t duration)598 hsm_key_factory_schedule_generate_all(engine_type* engine, time_t duration)
599 {
600     task_type* task;
601     struct __hsm_key_factory_task* task2 = NULL;
602 
603     if (!(task2 = calloc(1, sizeof(struct __hsm_key_factory_task)))) {
604         return 1;
605     }
606 
607     task2->engine = engine;
608     task2->duration = duration;
609     task2->policy_key = NULL;
610     task2->policy = NULL;
611     task2->reschedule_enforce_task = 1;
612 
613     task = task_create(strdup("hsm_key_factory_schedule_generation"),
614         TASK_CLASS_ENFORCER, TASK_TYPE_HSMKEYGEN,
615         hsm_key_factory_generate_all_cb, task2,
616         free, time_now());
617 
618     if (schedule_task(engine->taskq, task, 1, 0) != ODS_STATUS_OK) {
619         if (!task) {
620             free(task2);
621         }
622         task_destroy(task);
623         return 1;
624     }
625     return 0;
626 }
627 
628 
hsm_key_factory_get_key(engine_type * engine,const db_connection_t * connection,const policy_key_t * policy_key,hsm_key_state_t hsm_key_state)629 hsm_key_t* hsm_key_factory_get_key(engine_type* engine,
630     const db_connection_t* connection, const policy_key_t* policy_key,
631     hsm_key_state_t hsm_key_state)
632 {
633     db_clause_list_t* clause_list;
634     hsm_key_list_t* hsm_key_list;
635     hsm_key_t* hsm_key;
636 
637     if (!connection) {
638         return NULL;
639     }
640     if (!policy_key) {
641         return NULL;
642     }
643     if (hsm_key_state != HSM_KEY_STATE_PRIVATE
644         && hsm_key_state != HSM_KEY_STATE_SHARED)
645     {
646         return NULL;
647     }
648 
649     ods_log_debug("[hsm_key_factory_get_key] get %s key", (hsm_key_state == HSM_KEY_STATE_PRIVATE ? "private" : "shared"));
650 
651     /*
652      * Get a list of unused HSM keys matching our requirments
653      */
654     if (!(clause_list = db_clause_list_new())
655         || !hsm_key_policy_id_clause(clause_list, policy_key_policy_id(policy_key))
656         || !hsm_key_state_clause(clause_list, HSM_KEY_STATE_UNUSED)
657         || !hsm_key_bits_clause(clause_list, policy_key_bits(policy_key))
658         || !hsm_key_algorithm_clause(clause_list, policy_key_algorithm(policy_key))
659         || !hsm_key_role_clause(clause_list, (hsm_key_role_t)policy_key_role(policy_key))
660         || !hsm_key_is_revoked_clause(clause_list, 0)
661         || !hsm_key_key_type_clause(clause_list, HSM_KEY_KEY_TYPE_RSA)
662         || !hsm_key_repository_clause(clause_list, policy_key_repository(policy_key))
663         || !(hsm_key_list = hsm_key_list_new_get_by_clauses(connection, clause_list)))
664     {
665         ods_log_error("[hsm_key_factory_get_key] unable to list keys, database or memory allocation error");
666         db_clause_list_free(clause_list);
667         return NULL;
668     }
669     db_clause_list_free(clause_list);
670 
671     /*
672      * If there are no keys returned in the list we schedule generation and
673      * return NULL
674      */
675     if (!(hsm_key = hsm_key_list_get_next(hsm_key_list))) {
676         ods_log_warning("[hsm_key_factory_get_key] no keys available");
677         if (!engine->config->manual_keygen)
678             hsm_key_factory_schedule_generate(engine, policy_key, 0, 1);
679         hsm_key_list_free(hsm_key_list);
680         return NULL;
681     }
682     hsm_key_list_free(hsm_key_list);
683 
684     /*
685      * Update the state of the returned HSM key
686      */
687     if (hsm_key_set_state(hsm_key, hsm_key_state)
688         || hsm_key_update(hsm_key))
689     {
690         ods_log_debug("[hsm_key_factory_get_key] unable to update fetched key");
691         hsm_key_free(hsm_key);
692         return NULL;
693     }
694 
695     /*
696      * Schedule generation because we used up a key and return the HSM key
697      */
698     ods_log_debug("[hsm_key_factory_get_key] key allocated");
699     if (!engine->config->manual_keygen)
700         hsm_key_factory_schedule_generate(engine, policy_key, 0, 0);
701     return hsm_key;
702 }
703 
hsm_key_factory_release_key_id(const db_value_t * hsm_key_id,const db_connection_t * connection)704 int hsm_key_factory_release_key_id(const db_value_t* hsm_key_id, const db_connection_t* connection) {
705     hsm_key_t* hsm_key;
706     db_clause_list_t* clause_list = NULL;
707     key_data_t* key_data = NULL;
708     size_t count;
709 
710     if (!hsm_key_id) {
711         return 1;
712     }
713     if (!connection) {
714         return 1;
715     }
716 
717     if (!(hsm_key = hsm_key_new(connection))
718         || !(clause_list = db_clause_list_new())
719         || !(key_data = key_data_new(connection))
720         || !key_data_hsm_key_id_clause(clause_list, hsm_key_id)
721         || key_data_count(key_data, clause_list, &count))
722     {
723         ods_log_debug("[hsm_key_factory_release_key_id] unable to check usage of hsm_key, database or memory allocation error");
724         key_data_free(key_data);
725         db_clause_list_free(clause_list);
726         hsm_key_free(hsm_key);
727         return 1;
728     }
729     key_data_free(key_data);
730     db_clause_list_free(clause_list);
731 
732     if (count > 0) {
733         ods_log_debug("[hsm_key_factory_release_key_id] unable to release hsm_key, in use");
734         hsm_key_free(hsm_key);
735         return 0;
736     }
737 
738     if (hsm_key_get_by_id(hsm_key, hsm_key_id)) {
739         ods_log_debug("[hsm_key_factory_release_key_id] unable to fetch hsm_key");
740         hsm_key_free(hsm_key);
741         return 1;
742     }
743 
744     if (hsm_key_state(hsm_key) == HSM_KEY_STATE_DELETE) {
745         ods_log_debug("[hsm_key_factory_release_key_id] hsm_key already DELETE (?)");
746         hsm_key_free(hsm_key);
747         return 0;
748     }
749 
750     if (hsm_key_set_state(hsm_key, HSM_KEY_STATE_DELETE)
751         || hsm_key_update(hsm_key))
752     {
753         ods_log_debug("[hsm_key_factory_release_key_id] unable to change hsm_key state to DELETE");
754         hsm_key_free(hsm_key);
755         return 1;
756     }
757     ods_log_debug("[hsm_key_factory_release_key_id] key %s marked DELETE", hsm_key_locator(hsm_key));
758 
759     hsm_key_free(hsm_key);
760     return 0;
761 }
762 
hsm_key_factory_release_key(hsm_key_t * hsm_key,const db_connection_t * connection)763 int hsm_key_factory_release_key(hsm_key_t* hsm_key, const db_connection_t* connection) {
764     db_clause_list_t* clause_list = NULL;
765     key_data_t* key_data = NULL;
766     size_t count;
767 
768     if (!hsm_key) {
769         return 1;
770     }
771     if (!connection) {
772         return 1;
773     }
774 
775     if (!(clause_list = db_clause_list_new())
776         || !(key_data = key_data_new(connection))
777         || !key_data_hsm_key_id_clause(clause_list, hsm_key_id(hsm_key))
778         || key_data_count(key_data, clause_list, &count))
779     {
780         ods_log_debug("[hsm_key_factory_release_key] unable to check usage of hsm_key, database or memory allocation error");
781         key_data_free(key_data);
782         db_clause_list_free(clause_list);
783         return 1;
784     }
785     key_data_free(key_data);
786     db_clause_list_free(clause_list);
787 
788     if (count > 0) {
789         ods_log_debug("[hsm_key_factory_release_key] unable to release hsm_key, in use");
790         return 0;
791     }
792 
793     if (hsm_key_state(hsm_key) == HSM_KEY_STATE_DELETE) {
794         ods_log_debug("[hsm_key_factory_release_key] hsm_key already DELETE (?)");
795         return 0;
796     }
797 
798     if (hsm_key_set_state(hsm_key, HSM_KEY_STATE_DELETE)
799         || hsm_key_update(hsm_key))
800     {
801         ods_log_debug("[hsm_key_factory_release_key] unable to change hsm_key state to DELETE");
802         return 1;
803     }
804     ods_log_debug("[hsm_key_factory_release_key] key %s marked DELETE", hsm_key_locator(hsm_key));
805 
806     return 0;
807 }
808 
809 int
hsm_key_factory_delete_key(const db_connection_t * connection)810 hsm_key_factory_delete_key(const db_connection_t* connection)
811 {
812     db_clause_list_t* clause_list;
813     hsm_key_list_t* hsm_key_list;
814     libhsm_key_t* hsmkey;
815     hsm_key_t* hsm_key;
816     hsm_ctx_t *hsm_ctx;
817     int count = 0;
818 
819     if (!(hsm_ctx = hsm_create_context())) {
820         /* might be a transient error, not important for this action so do not log */
821         return -1;
822     }
823 
824     ods_log_error("[hsm_key_factory_delete_key] looking for keys to purge from HSM");
825     if (!(clause_list = db_clause_list_new())
826         || !hsm_key_state_clause(clause_list, HSM_KEY_STATE_DELETE)
827         //|| !hsm_key_is_revoked_clause(clause_list, 0)
828         || !(hsm_key_list = hsm_key_list_new_get_by_clauses(connection, clause_list)))
829     {
830         ods_log_error("[hsm_key_factory_delete_key] unable to list keys, database or memory allocation error");
831         db_clause_list_free(clause_list);
832         return -2;
833     }
834     db_clause_list_free(clause_list);
835 
836     while((hsm_key = hsm_key_list_get_next(hsm_key_list))) {
837         hsmkey = hsm_find_key_by_id(hsm_ctx, hsm_key_locator(hsm_key));
838         if(hsm_remove_key(hsm_ctx, hsmkey)) {
839             // report on error
840             ods_log_error("[hsm_key_factory_delete_key] unable to remove key %s", hsm_key_locator(hsm_key));
841         } else {
842             clause_list = db_clause_list_new();
843             db_clause_t* clause;
844             clause = db_clause_new();
845             db_clause_set_field(clause, "locator");
846             db_clause_set_type(clause, DB_CLAUSE_EQUAL);
847             db_clause_set_operator(clause, DB_CLAUSE_OPERATOR_AND);
848             db_value_from_text(db_clause_get_value(clause), hsm_key_locator(hsm_key));
849             db_clause_list_add(clause_list, clause);
850             clause = db_clause_new();
851             db_clause_set_field(clause, "rev");
852             db_clause_set_type(clause, DB_CLAUSE_EQUAL);
853             db_clause_set_operator(clause, DB_CLAUSE_OPERATOR_AND);
854             db_value_copy(db_clause_get_value(clause), &(hsm_key->rev));
855             db_clause_list_add(clause_list, clause);
856             db_object_delete(hsm_key->dbo, clause_list);
857             db_clause_list_free(clause_list);
858             ods_log_info("[hsm_key_factory_get_key] removing key %s from HSM", hsm_key_locator(hsm_key));
859             ++count;
860         }
861     }
862     hsm_key_list_free(hsm_key_list);
863     hsm_destroy_context(hsm_ctx);
864     return count;
865 }
866