OpenDNSSEC-signer  1.4.5
hsm.c
Go to the documentation of this file.
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 
32 #include "daemon/engine.h"
33 #include "shared/hsm.h"
34 #include "shared/log.h"
35 
36 static const char* hsm_str = "hsm";
37 
38 
43 int
44 lhsm_open(const char* filename)
45 {
46  int result = hsm_open(filename, hsm_check_pin);
47  if (result != HSM_OK) {
48  char* error = hsm_get_error(NULL);
49  if (error != NULL) {
50  ods_log_error("[%s] %s", hsm_str, error);
51  free(error);
52  } else {
53  ods_log_crit("[%s] error opening libhsm (errno %i)", hsm_str,
54  result);
55  }
56  /* exit? */
57  } else {
58  ods_log_info("[%s] libhsm connection opened succesfully", hsm_str);
59  }
60  return result;
61 }
62 
63 
68 int
69 lhsm_reopen(const char* filename)
70 {
71  if (hsm_check_context(NULL) != HSM_OK) {
72  ods_log_warning("[%s] idle libhsm connection, trying to reopen",
73  hsm_str);
74  hsm_close();
75  return lhsm_open(filename);
76  }
77  return HSM_OK;
78 }
79 
80 
85 static void
86 lhsm_clear_key_cache(key_type* key)
87 {
88  if (!key) {
89  return;
90  }
91  if (key->dnskey) {
92  /* DNSKEY still exists in zone */
93  key->dnskey = NULL;
94  }
95  if (key->hsmkey) {
96  hsm_key_free(key->hsmkey);
97  key->hsmkey = NULL;
98  }
99  if (key->params) {
100  hsm_sign_params_free(key->params);
101  key->params = NULL;
102  }
103  return;
104 }
105 
106 
111 void
113 {
114  engine_type* e = (engine_type*) engine;
115  if (hsm_check_context(NULL) != HSM_OK) {
116  ods_log_warning("[%s] idle libhsm connection, trying to reopen",
117  hsm_str);
119  hsm_close();
120  (void)lhsm_open(e->config->cfg_filename);
122  } else {
123  ods_log_debug("[%s] libhsm connection ok", hsm_str);
124  }
125  return;
126 }
127 
128 
134 lhsm_get_key(hsm_ctx_t* ctx, ldns_rdf* owner, key_type* key_id)
135 {
136  char *error = NULL;
137  int retries = 0;
138 
139  if (!owner || !key_id) {
140  ods_log_error("[%s] unable to get key: missing required elements",
141  hsm_str);
142  return ODS_STATUS_ASSERT_ERR;
143  }
144 
145 lhsm_key_start:
146 
147  /* set parameters */
148  if (!key_id->params) {
149  key_id->params = hsm_sign_params_new();
150  if (key_id->params) {
151  key_id->params->owner = ldns_rdf_clone(owner);
152  key_id->params->algorithm = key_id->algorithm;
153  key_id->params->flags = key_id->flags;
154  } else {
155  /* could not create params */
156  error = hsm_get_error(ctx);
157  if (error) {
158  ods_log_error("[%s] %s", hsm_str, error);
159  free((void*)error);
160  } else if (!retries) {
161  lhsm_clear_key_cache(key_id);
162  retries++;
163  goto lhsm_key_start;
164  }
165  ods_log_error("[%s] unable to get key: create params for key %s "
166  "failed", hsm_str, key_id->locator?key_id->locator:"(null)");
167  return ODS_STATUS_ERR;
168  }
169  }
170  /* lookup key */
171  if (!key_id->hsmkey) {
172  key_id->hsmkey = hsm_find_key_by_id(ctx, key_id->locator);
173  }
174  if (!key_id->hsmkey) {
175  error = hsm_get_error(ctx);
176  if (error) {
177  ods_log_error("[%s] %s", hsm_str, error);
178  free((void*)error);
179  } else if (!retries) {
180  lhsm_clear_key_cache(key_id);
181  retries++;
182  goto lhsm_key_start;
183  }
184  /* could not find key */
185  ods_log_error("[%s] unable to get key: key %s not found", hsm_str,
186  key_id->locator?key_id->locator:"(null)");
187  return ODS_STATUS_ERR;
188  }
189  /* get dnskey */
190  if (!key_id->dnskey) {
191  key_id->dnskey = hsm_get_dnskey(ctx, key_id->hsmkey, key_id->params);
192  }
193  if (!key_id->dnskey) {
194  error = hsm_get_error(ctx);
195  if (error) {
196  ods_log_error("[%s] %s", hsm_str, error);
197  free((void*)error);
198  } else if (!retries) {
199  lhsm_clear_key_cache(key_id);
200  retries++;
201  goto lhsm_key_start;
202  }
203  ods_log_error("[%s] unable to get key: hsm failed to create dnskey",
204  hsm_str);
205  return ODS_STATUS_ERR;
206  }
207  key_id->params->keytag = ldns_calc_keytag(key_id->dnskey);
208  return ODS_STATUS_OK;
209 }
210 
211 
216 ldns_rr*
217 lhsm_sign(hsm_ctx_t* ctx, ldns_rr_list* rrset, key_type* key_id,
218  ldns_rdf* owner, time_t inception, time_t expiration)
219 {
220  ods_status status = ODS_STATUS_OK;
221  char* error = NULL;
222  ldns_rr* result = NULL;
223  hsm_sign_params_t* params = NULL;
224  int retries = 0;
225 
226  if (!owner || !key_id || !rrset || !inception || !expiration) {
227  ods_log_error("[%s] unable to sign: missing required elements",
228  hsm_str);
229  return NULL;
230  }
231  ods_log_assert(key_id->dnskey);
232  ods_log_assert(key_id->hsmkey);
233  ods_log_assert(key_id->params);
234  /* adjust parameters */
235  params = hsm_sign_params_new();
236  params->owner = ldns_rdf_clone(key_id->params->owner);
237  params->algorithm = key_id->algorithm;
238  params->flags = key_id->flags;
239  params->inception = inception;
240  params->expiration = expiration;
241  params->keytag = key_id->params->keytag;
242  ods_log_deeebug("[%s] sign RRset[%i] with key %s tag %u", hsm_str,
243  ldns_rr_get_type(ldns_rr_list_rr(rrset, 0)),
244  key_id->locator?key_id->locator:"(null)", params->keytag);
245  result = hsm_sign_rrset(ctx, rrset, key_id->hsmkey, params);
246  hsm_sign_params_free(params);
247  if (!result) {
248  error = hsm_get_error(ctx);
249  if (error) {
250  ods_log_error("[%s] %s", hsm_str, error);
251  free((void*)error);
252  }
253  ods_log_crit("[%s] error signing rrset with libhsm", hsm_str);
254  }
255  return result;
256 }