OpenDNSSEC-signer  1.3.8
/build/buildd/opendnssec-1.3.8/signer/src/shared/hsm.c
Go to the documentation of this file.
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 }