OpenDNSSEC-signer  1.3.9
hsm.c
Go to the documentation of this file.
1 /*
2  * $Id: hsm.c 6192 2012-02-29 14:29:03Z matthijs $
3  *
4  * Copyright (c) 2009 NLNet Labs. 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 
34 #include "daemon/engine.h"
35 #include "shared/hsm.h"
36 #include "shared/log.h"
37 
38 static const char* hsm_str = "hsm";
39 
40 
45 int
46 lhsm_open(const char* filename)
47 {
48  int result = hsm_open(filename, hsm_prompt_pin, NULL);
49  if (result != HSM_OK) {
50  char* error = hsm_get_error(NULL);
51  if (error != NULL) {
52  ods_log_error("[%s] %s", hsm_str, error);
53  free(error);
54  } else {
55  ods_log_crit("[%s] error opening libhsm (errno %i)", hsm_str,
56  result);
57  }
58  /* exit? */
59  } else {
60  ods_log_info("[%s] libhsm connection opened succesfully", hsm_str);
61  }
62  return result;
63 }
64 
65 
70 int
71 lhsm_reopen(const char* filename)
72 {
73  if (hsm_check_context(NULL) != HSM_OK) {
74  ods_log_warning("[%s] idle libhsm connection, trying to reopen",
75  hsm_str);
76  hsm_close();
77  return lhsm_open(filename);
78  }
79  return HSM_OK;
80 }
81 
82 
87 static void
88 lhsm_clear_key_cache(key_type* key)
89 {
90  if (!key) {
91  return;
92  }
93  if (key->dnskey) {
94  ldns_rr_free(key->dnskey);
95  key->dnskey = NULL;
96  }
97  if (key->hsmkey) {
98  hsm_key_free(key->hsmkey);
99  key->hsmkey = NULL;
100  }
101  if (key->params) {
102  hsm_sign_params_free(key->params);
103  key->params = NULL;
104  }
105  return;
106 }
107 
108 
113 void
115 {
116  engine_type* e = (engine_type*) engine;
117  if (hsm_check_context(NULL) != HSM_OK) {
118  ods_log_warning("[%s] idle libhsm connection, trying to reopen",
119  hsm_str);
121  hsm_close();
122  (void)lhsm_open(e->config->cfg_filename);
124  } else {
125  ods_log_debug("[%s] libhsm connection ok", hsm_str);
126  }
127  return;
128 }
129 
130 
136 lhsm_get_key(hsm_ctx_t* ctx, ldns_rdf* owner, key_type* key_id)
137 {
138  char *error = NULL;
139  int retries = 0;
140 
141  if (!owner || !key_id) {
142  ods_log_error("[%s] unable to get key: missing required elements",
143  hsm_str);
144  return ODS_STATUS_ASSERT_ERR;
145  }
146  ods_log_assert(owner);
147  ods_log_assert(key_id);
148 
149 lhsm_key_start:
150 
151  /* set parameters */
152  if (!key_id->params) {
153  key_id->params = hsm_sign_params_new();
154  if (key_id->params) {
155  key_id->params->owner = ldns_rdf_clone(owner);
156  key_id->params->algorithm = key_id->algorithm;
157  key_id->params->flags = key_id->flags;
158  } else {
159  /* could not create params */
160  error = hsm_get_error(ctx);
161  if (error) {
162  ods_log_error("[%s] %s", hsm_str, error);
163  free((void*)error);
164  } else if (!retries) {
165  lhsm_clear_key_cache(key_id);
166  retries++;
167  goto lhsm_key_start;
168  }
169  ods_log_error("[%s] unable to get key: create params for key %s "
170  "failed", hsm_str, key_id->locator?key_id->locator:"(null)");
171  return ODS_STATUS_ERR;
172  }
173  }
174 
175  /* lookup key */
176  if (!key_id->hsmkey) {
177  key_id->hsmkey = hsm_find_key_by_id(ctx, key_id->locator);
178  }
179  if (!key_id->hsmkey) {
180  error = hsm_get_error(ctx);
181  if (error) {
182  ods_log_error("[%s] %s", hsm_str, error);
183  free((void*)error);
184  } else if (!retries) {
185  lhsm_clear_key_cache(key_id);
186  retries++;
187  goto lhsm_key_start;
188  }
189  /* could not find key */
190  ods_log_error("[%s] unable to get key: key %s not found", hsm_str,
191  key_id->locator?key_id->locator:"(null)");
192  return ODS_STATUS_ERR;
193  }
194 
195  /* get dnskey */
196  if (!key_id->dnskey) {
197  key_id->dnskey = hsm_get_dnskey(ctx, key_id->hsmkey, key_id->params);
198  }
199  if (!key_id->dnskey) {
200  error = hsm_get_error(ctx);
201  if (error) {
202  ods_log_error("[%s] %s", hsm_str, error);
203  free((void*)error);
204  } else if (!retries) {
205  lhsm_clear_key_cache(key_id);
206  retries++;
207  goto lhsm_key_start;
208  }
209  ods_log_error("[%s] unable to get key: hsm failed to create dnskey",
210  hsm_str);
211  return ODS_STATUS_ERR;
212  }
213  key_id->params->keytag = ldns_calc_keytag(key_id->dnskey);
214  return ODS_STATUS_OK;
215 }
216 
217 
222 ldns_rr*
223 lhsm_sign(hsm_ctx_t* ctx, ldns_rr_list* rrset, key_type* key_id,
224  ldns_rdf* owner, time_t inception, time_t expiration)
225 {
226  ods_status status = ODS_STATUS_OK;
227  char* error = NULL;
228  ldns_rr* result = NULL;
229  hsm_sign_params_t* params = NULL;
230  int retries = 0;
231 
232  if (!owner || !key_id || !rrset || !inception || !expiration) {
233  ods_log_error("[%s] unable to sign: missing required elements",
234  hsm_str);
235  return NULL;
236  }
237  ods_log_assert(owner);
238  ods_log_assert(key_id);
239  ods_log_assert(rrset);
240  ods_log_assert(inception);
241  ods_log_assert(expiration);
242 
243 lhsm_sign_start:
244 
245  if (!key_id->dnskey) {
246  status = lhsm_get_key(ctx, owner, key_id);
247  if (status != ODS_STATUS_OK) {
248  error = hsm_get_error(ctx);
249  if (error) {
250  ods_log_error("[%s] %s", hsm_str, error);
251  free((void*)error);
252  } else if (!retries) {
253  lhsm_clear_key_cache(key_id);
254  retries++;
255  goto lhsm_sign_start;
256  }
257  ods_log_error("[%s] unable to sign: get key failed", hsm_str);
258  return NULL;
259  }
260  }
261  ods_log_assert(key_id->dnskey);
262  ods_log_assert(key_id->hsmkey);
263  ods_log_assert(key_id->params);
264 
265  params = hsm_sign_params_new();
266  params->owner = ldns_rdf_clone(key_id->params->owner);
267  params->algorithm = key_id->algorithm;
268  params->flags = key_id->flags;
269  params->inception = inception;
270  params->expiration = expiration;
271  params->keytag = ldns_calc_keytag(key_id->dnskey);
272  ods_log_debug("[%s] sign RRset[%i] with key %s tag %u", hsm_str,
273  ldns_rr_get_type(ldns_rr_list_rr(rrset, 0)),
274  key_id->locator?key_id->locator:"(null)", params->keytag);
275  result = hsm_sign_rrset(ctx, rrset, key_id->hsmkey, params);
276  hsm_sign_params_free(params);
277 
278  if (!result) {
279  error = hsm_get_error(ctx);
280  if (error) {
281  ods_log_error("[%s] %s", hsm_str, error);
282  free((void*)error);
283  } else if (!retries) {
284  lhsm_clear_key_cache(key_id);
285  retries++;
286  goto lhsm_sign_start;
287  }
288  ods_log_crit("[%s] error signing rrset with libhsm", hsm_str);
289  }
290  return result;
291 }