OpenDNSSEC-signer
1.3.8
|
00001 /* 00002 * $Id: hsm.c 6192 2012-02-29 14:29:03Z matthijs $ 00003 * 00004 * Copyright (c) 2009 NLNet Labs. All rights reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 1. Redistributions of source code must retain the above copyright 00010 * notice, this list of conditions and the following disclaimer. 00011 * 2. Redistributions in binary form must reproduce the above copyright 00012 * notice, this list of conditions and the following disclaimer in the 00013 * documentation and/or other materials provided with the distribution. 00014 * 00015 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 00016 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00017 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00018 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 00019 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00020 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00021 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00022 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 00023 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 00024 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 00025 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 * 00027 */ 00028 00034 #include "daemon/engine.h" 00035 #include "shared/hsm.h" 00036 #include "shared/log.h" 00037 00038 static const char* hsm_str = "hsm"; 00039 00040 00045 int 00046 lhsm_open(const char* filename) 00047 { 00048 int result = hsm_open(filename, hsm_prompt_pin, NULL); 00049 if (result != HSM_OK) { 00050 char* error = hsm_get_error(NULL); 00051 if (error != NULL) { 00052 ods_log_error("[%s] %s", hsm_str, error); 00053 free(error); 00054 } else { 00055 ods_log_crit("[%s] error opening libhsm (errno %i)", hsm_str, 00056 result); 00057 } 00058 /* exit? */ 00059 } else { 00060 ods_log_info("[%s] libhsm connection opened succesfully", hsm_str); 00061 } 00062 return result; 00063 } 00064 00065 00070 int 00071 lhsm_reopen(const char* filename) 00072 { 00073 if (hsm_check_context(NULL) != HSM_OK) { 00074 ods_log_warning("[%s] idle libhsm connection, trying to reopen", 00075 hsm_str); 00076 hsm_close(); 00077 return lhsm_open(filename); 00078 } 00079 return HSM_OK; 00080 } 00081 00082 00087 static void 00088 lhsm_clear_key_cache(key_type* key) 00089 { 00090 if (!key) { 00091 return; 00092 } 00093 if (key->dnskey) { 00094 ldns_rr_free(key->dnskey); 00095 key->dnskey = NULL; 00096 } 00097 if (key->hsmkey) { 00098 hsm_key_free(key->hsmkey); 00099 key->hsmkey = NULL; 00100 } 00101 if (key->params) { 00102 hsm_sign_params_free(key->params); 00103 key->params = NULL; 00104 } 00105 return; 00106 } 00107 00108 00113 void 00114 lhsm_check_connection(void* engine) 00115 { 00116 engine_type* e = (engine_type*) engine; 00117 if (hsm_check_context(NULL) != HSM_OK) { 00118 ods_log_warning("[%s] idle libhsm connection, trying to reopen", 00119 hsm_str); 00120 engine_stop_drudgers(e); 00121 hsm_close(); 00122 (void)lhsm_open(e->config->cfg_filename); 00123 engine_start_drudgers((engine_type*) engine); 00124 } else { 00125 ods_log_debug("[%s] libhsm connection ok", hsm_str); 00126 } 00127 return; 00128 } 00129 00130 00135 ods_status 00136 lhsm_get_key(hsm_ctx_t* ctx, ldns_rdf* owner, key_type* key_id) 00137 { 00138 char *error = NULL; 00139 int retries = 0; 00140 00141 if (!owner || !key_id) { 00142 ods_log_error("[%s] unable to get key: missing required elements", 00143 hsm_str); 00144 return ODS_STATUS_ASSERT_ERR; 00145 } 00146 ods_log_assert(owner); 00147 ods_log_assert(key_id); 00148 00149 lhsm_key_start: 00150 00151 /* set parameters */ 00152 if (!key_id->params) { 00153 key_id->params = hsm_sign_params_new(); 00154 if (key_id->params) { 00155 key_id->params->owner = ldns_rdf_clone(owner); 00156 key_id->params->algorithm = key_id->algorithm; 00157 key_id->params->flags = key_id->flags; 00158 } else { 00159 /* could not create params */ 00160 error = hsm_get_error(ctx); 00161 if (error) { 00162 ods_log_error("[%s] %s", hsm_str, error); 00163 free((void*)error); 00164 } else if (!retries) { 00165 lhsm_clear_key_cache(key_id); 00166 retries++; 00167 goto lhsm_key_start; 00168 } 00169 ods_log_error("[%s] unable to get key: create params for key %s " 00170 "failed", hsm_str, key_id->locator?key_id->locator:"(null)"); 00171 return ODS_STATUS_ERR; 00172 } 00173 } 00174 00175 /* lookup key */ 00176 if (!key_id->hsmkey) { 00177 key_id->hsmkey = hsm_find_key_by_id(ctx, key_id->locator); 00178 } 00179 if (!key_id->hsmkey) { 00180 error = hsm_get_error(ctx); 00181 if (error) { 00182 ods_log_error("[%s] %s", hsm_str, error); 00183 free((void*)error); 00184 } else if (!retries) { 00185 lhsm_clear_key_cache(key_id); 00186 retries++; 00187 goto lhsm_key_start; 00188 } 00189 /* could not find key */ 00190 ods_log_error("[%s] unable to get key: key %s not found", hsm_str, 00191 key_id->locator?key_id->locator:"(null)"); 00192 return ODS_STATUS_ERR; 00193 } 00194 00195 /* get dnskey */ 00196 if (!key_id->dnskey) { 00197 key_id->dnskey = hsm_get_dnskey(ctx, key_id->hsmkey, key_id->params); 00198 } 00199 if (!key_id->dnskey) { 00200 error = hsm_get_error(ctx); 00201 if (error) { 00202 ods_log_error("[%s] %s", hsm_str, error); 00203 free((void*)error); 00204 } else if (!retries) { 00205 lhsm_clear_key_cache(key_id); 00206 retries++; 00207 goto lhsm_key_start; 00208 } 00209 ods_log_error("[%s] unable to get key: hsm failed to create dnskey", 00210 hsm_str); 00211 return ODS_STATUS_ERR; 00212 } 00213 key_id->params->keytag = ldns_calc_keytag(key_id->dnskey); 00214 return ODS_STATUS_OK; 00215 } 00216 00217 00222 ldns_rr* 00223 lhsm_sign(hsm_ctx_t* ctx, ldns_rr_list* rrset, key_type* key_id, 00224 ldns_rdf* owner, time_t inception, time_t expiration) 00225 { 00226 ods_status status = ODS_STATUS_OK; 00227 char* error = NULL; 00228 ldns_rr* result = NULL; 00229 hsm_sign_params_t* params = NULL; 00230 int retries = 0; 00231 00232 if (!owner || !key_id || !rrset || !inception || !expiration) { 00233 ods_log_error("[%s] unable to sign: missing required elements", 00234 hsm_str); 00235 return NULL; 00236 } 00237 ods_log_assert(owner); 00238 ods_log_assert(key_id); 00239 ods_log_assert(rrset); 00240 ods_log_assert(inception); 00241 ods_log_assert(expiration); 00242 00243 lhsm_sign_start: 00244 00245 if (!key_id->dnskey) { 00246 status = lhsm_get_key(ctx, owner, key_id); 00247 if (status != ODS_STATUS_OK) { 00248 error = hsm_get_error(ctx); 00249 if (error) { 00250 ods_log_error("[%s] %s", hsm_str, error); 00251 free((void*)error); 00252 } else if (!retries) { 00253 lhsm_clear_key_cache(key_id); 00254 retries++; 00255 goto lhsm_sign_start; 00256 } 00257 ods_log_error("[%s] unable to sign: get key failed", hsm_str); 00258 return NULL; 00259 } 00260 } 00261 ods_log_assert(key_id->dnskey); 00262 ods_log_assert(key_id->hsmkey); 00263 ods_log_assert(key_id->params); 00264 00265 params = hsm_sign_params_new(); 00266 params->owner = ldns_rdf_clone(key_id->params->owner); 00267 params->algorithm = key_id->algorithm; 00268 params->flags = key_id->flags; 00269 params->inception = inception; 00270 params->expiration = expiration; 00271 params->keytag = ldns_calc_keytag(key_id->dnskey); 00272 ods_log_debug("[%s] sign RRset[%i] with key %s tag %u", hsm_str, 00273 ldns_rr_get_type(ldns_rr_list_rr(rrset, 0)), 00274 key_id->locator?key_id->locator:"(null)", params->keytag); 00275 result = hsm_sign_rrset(ctx, rrset, key_id->hsmkey, params); 00276 hsm_sign_params_free(params); 00277 00278 if (!result) { 00279 error = hsm_get_error(ctx); 00280 if (error) { 00281 ods_log_error("[%s] %s", hsm_str, error); 00282 free((void*)error); 00283 } else if (!retries) { 00284 lhsm_clear_key_cache(key_id); 00285 retries++; 00286 goto lhsm_sign_start; 00287 } 00288 ods_log_crit("[%s] error signing rrset with libhsm", hsm_str); 00289 } 00290 return result; 00291 }