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