1 /*
2 * Copyright (c) 2009 NLNet Labs. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
19 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
21 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
23 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 */
26
27 /**
28 * Hardware Security Module support.
29 *
30 */
31
32 #include "daemon/engine.h"
33 #include "hsm.h"
34 #include "log.h"
35 #include "cryptoki_compat/pkcs11.h"
36
37 static const char* hsm_str = "hsm";
38
39 /**
40 * Clear key cache.
41 *
42 */
43 static void
lhsm_clear_key_cache(key_type * key)44 lhsm_clear_key_cache(key_type* key)
45 {
46 if (!key) {
47 return;
48 }
49 if (key->dnskey) {
50 /* DNSKEY still exists in zone */
51 key->dnskey = NULL;
52 }
53 if (key->params) {
54 hsm_sign_params_free(key->params);
55 key->params = NULL;
56 }
57 }
58
59 static const libhsm_key_t*
keylookup(hsm_ctx_t * ctx,const char * locator)60 keylookup(hsm_ctx_t* ctx, const char* locator)
61 {
62 const libhsm_key_t* key;
63 key = keycache_lookup(ctx, locator);
64 if (key == NULL) {
65 char* error = hsm_get_error(ctx);
66 if (error) {
67 ods_log_error("[%s] %s", hsm_str, error);
68 free((void*)error);
69 }
70 /* could not find key */
71 ods_log_error("[%s] unable to get key: key %s not found", hsm_str, locator);
72 }
73 return key;
74 }
75
76 /**
77 * Get key from one of the HSMs.
78 *
79 */
80 ods_status
lhsm_get_key(hsm_ctx_t * ctx,ldns_rdf * owner,key_type * key_id,int skip_hsm_access)81 lhsm_get_key(hsm_ctx_t* ctx, ldns_rdf* owner, key_type* key_id, int skip_hsm_access)
82 {
83 char *error = NULL;
84 int retries = 0;
85
86 if (!owner || !key_id) {
87 ods_log_error("[%s] unable to get key: missing required elements",
88 hsm_str);
89 return ODS_STATUS_ASSERT_ERR;
90 }
91
92 llibhsm_key_start:
93
94 /* set parameters */
95 if (!key_id->params) {
96 key_id->params = hsm_sign_params_new();
97 if (key_id->params) {
98 key_id->params->owner = ldns_rdf_clone(owner);
99 key_id->params->algorithm = key_id->algorithm;
100 key_id->params->flags = key_id->flags;
101 } else {
102 /* could not create params */
103 ods_log_error("[%s] unable to get key: create params for key %s "
104 "failed", hsm_str, key_id->locator?key_id->locator:"(null)");
105 return ODS_STATUS_ERR;
106 }
107 }
108 if (skip_hsm_access) return ODS_STATUS_OK;
109
110 /* get dnskey */
111 if (!key_id->dnskey) {
112 key_id->dnskey = hsm_get_dnskey(ctx, keylookup(ctx, key_id->locator), key_id->params);
113 }
114 if (!key_id->dnskey) {
115 error = hsm_get_error(ctx);
116 if (error) {
117 ods_log_error("[%s] %s", hsm_str, error);
118 free((void*)error);
119 } else if (!retries) {
120 lhsm_clear_key_cache(key_id);
121 retries++;
122 goto llibhsm_key_start;
123 }
124 ods_log_error("[%s] unable to get key: hsm failed to create dnskey",
125 hsm_str);
126 return ODS_STATUS_ERR;
127 }
128 key_id->params->keytag = ldns_calc_keytag(key_id->dnskey);
129 return ODS_STATUS_OK;
130 }
131
132
133 /**
134 * Get RRSIG from one of the HSMs, given a RRset and a key.
135 *
136 */
137 ldns_rr*
lhsm_sign(hsm_ctx_t * ctx,ldns_rr_list * rrset,key_type * key_id,ldns_rdf * owner,time_t inception,time_t expiration)138 lhsm_sign(hsm_ctx_t* ctx, ldns_rr_list* rrset, key_type* key_id,
139 ldns_rdf* owner, time_t inception, time_t expiration)
140 {
141 char* error = NULL;
142 ldns_rr* result = NULL;
143 hsm_sign_params_t* params = NULL;
144
145 if (!owner || !key_id || !rrset || !inception || !expiration) {
146 ods_log_error("[%s] unable to sign: missing required elements",
147 hsm_str);
148 return NULL;
149 }
150 ods_log_assert(key_id->dnskey);
151 ods_log_assert(key_id->params);
152 /* adjust parameters */
153 params = hsm_sign_params_new();
154 params->owner = ldns_rdf_clone(key_id->params->owner);
155 params->algorithm = key_id->algorithm;
156 params->flags = key_id->flags;
157 params->inception = inception;
158 params->expiration = expiration;
159 params->keytag = key_id->params->keytag;
160 ods_log_deeebug("[%s] sign RRset[%i] with key %s tag %u", hsm_str,
161 ldns_rr_get_type(ldns_rr_list_rr(rrset, 0)),
162 key_id->locator?key_id->locator:"(null)", params->keytag);
163 result = hsm_sign_rrset(ctx, rrset, keylookup(ctx, key_id->locator), params);
164 hsm_sign_params_free(params);
165 if (!result) {
166 error = hsm_get_error(ctx);
167 if (error) {
168 ods_log_error("[%s] %s", hsm_str, error);
169 free((void*)error);
170 }
171 ods_log_crit("[%s] error signing rrset with libhsm", hsm_str);
172 }
173 return result;
174 }
175