• Main Page
  • Data Structures
  • Files
  • File List
  • Globals

/build/buildd-opendnssec_1.3.2-1~bpo60+1-armel-4stS1W/opendnssec-1.3.2/libhsm/src/libhsm.c

Go to the documentation of this file.
00001 /* $Id: libhsm.c 4513 2011-02-23 10:03:08Z matthijs $ */
00002 
00003 /*
00004  * Copyright (c) 2009 .SE (The Internet Infrastructure Foundation).
00005  * Copyright (c) 2009 NLNet Labs.
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions
00010  * are met:
00011  * 1. Redistributions of source code must retain the above copyright
00012  *    notice, this list of conditions and the following disclaimer.
00013  * 2. Redistributions in binary form must reproduce the above copyright
00014  *    notice, this list of conditions and the following disclaimer in the
00015  *    documentation and/or other materials provided with the distribution.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00019  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00021  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00023  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
00025  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00026  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
00027  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 #include "config.h"
00031 
00032 #include <stdio.h>
00033 #include <string.h>
00034 #include <strings.h>
00035 #include <stdlib.h>
00036 #include <unistd.h>
00037 #include <dlfcn.h>
00038 
00039 #include <libxml/tree.h>
00040 #include <libxml/parser.h>
00041 #include <libxml/xpath.h>
00042 #include <libxml/xpathInternals.h>
00043 #include <libxml/relaxng.h>
00044 
00045 #include "libhsm.h"
00046 #include "libhsmdns.h"
00047 #include "compat.h"
00048 
00049 #include <pkcs11.h>
00050 
00052 #define HSM_TOKEN_LABEL_LENGTH 32
00053 
00055 static hsm_ctx_t *_hsm_ctx;
00056 
00058 static char *
00059 ldns_pkcs11_rv_str(CK_RV rv)
00060 {
00061     switch (rv)
00062         {
00063         case CKR_OK:
00064             return "CKR_OK";
00065         case CKR_CANCEL:
00066             return "CKR_CANCEL";
00067         case CKR_HOST_MEMORY:
00068             return "CKR_HOST_MEMORY";
00069         case CKR_GENERAL_ERROR:
00070             return "CKR_GENERAL_ERROR";
00071         case CKR_FUNCTION_FAILED:
00072             return "CKR_FUNCTION_FAILED";
00073         case CKR_SLOT_ID_INVALID:
00074             return "CKR_SLOT_ID_INVALID";
00075         case CKR_ATTRIBUTE_READ_ONLY:
00076             return "CKR_ATTRIBUTE_READ_ONLY";
00077         case CKR_ATTRIBUTE_SENSITIVE:
00078             return "CKR_ATTRIBUTE_SENSITIVE";
00079         case CKR_ATTRIBUTE_TYPE_INVALID:
00080             return "CKR_ATTRIBUTE_TYPE_INVALID";
00081         case CKR_ATTRIBUTE_VALUE_INVALID:
00082             return "CKR_ATTRIBUTE_VALUE_INVALID";
00083         case CKR_DATA_INVALID:
00084             return "CKR_DATA_INVALID";
00085         case CKR_DATA_LEN_RANGE:
00086             return "CKR_DATA_LEN_RANGE";
00087         case CKR_DEVICE_ERROR:
00088             return "CKR_DEVICE_ERROR";
00089         case CKR_DEVICE_MEMORY:
00090             return "CKR_DEVICE_MEMORY";
00091         case CKR_DEVICE_REMOVED:
00092             return "CKR_DEVICE_REMOVED";
00093         case CKR_ENCRYPTED_DATA_INVALID:
00094             return "CKR_ENCRYPTED_DATA_INVALID";
00095         case CKR_ENCRYPTED_DATA_LEN_RANGE:
00096             return "CKR_ENCRYPTED_DATA_LEN_RANGE";
00097         case CKR_FUNCTION_CANCELED:
00098             return "CKR_FUNCTION_CANCELED";
00099         case CKR_FUNCTION_NOT_PARALLEL:
00100             return "CKR_FUNCTION_NOT_PARALLEL";
00101         case CKR_KEY_HANDLE_INVALID:
00102             return "CKR_KEY_HANDLE_INVALID";
00103         case CKR_KEY_SIZE_RANGE:
00104             return "CKR_KEY_SIZE_RANGE";
00105         case CKR_KEY_TYPE_INCONSISTENT:
00106             return "CKR_KEY_TYPE_INCONSISTENT";
00107         case CKR_MECHANISM_INVALID:
00108             return "CKR_MECHANISM_INVALID";
00109         case CKR_MECHANISM_PARAM_INVALID:
00110             return "CKR_MECHANISM_PARAM_INVALID";
00111         case CKR_OBJECT_HANDLE_INVALID:
00112             return "CKR_OBJECT_HANDLE_INVALID";
00113         case CKR_OPERATION_ACTIVE:
00114             return "CKR_OPERATION_ACTIVE";
00115         case CKR_OPERATION_NOT_INITIALIZED:
00116             return "CKR_OPERATION_NOT_INITIALIZED";
00117         case CKR_PIN_INCORRECT:
00118             return "CKR_PIN_INCORRECT";
00119         case CKR_PIN_INVALID:
00120             return "CKR_PIN_INVALID";
00121         case CKR_PIN_LEN_RANGE:
00122             return "CKR_PIN_LEN_RANGE";
00123         case CKR_SESSION_CLOSED:
00124             return "CKR_SESSION_CLOSED";
00125         case CKR_SESSION_COUNT:
00126             return "CKR_SESSION_COUNT";
00127         case CKR_SESSION_HANDLE_INVALID:
00128             return "CKR_SESSION_HANDLE_INVALID";
00129         case CKR_SESSION_PARALLEL_NOT_SUPPORTED:
00130             return "CKR_SESSION_PARALLEL_NOT_SUPPORTED";
00131         case CKR_SESSION_READ_ONLY:
00132             return "CKR_SESSION_READ_ONLY";
00133         case CKR_SESSION_EXISTS:
00134             return "CKR_SESSION_EXISTS";
00135         case CKR_SIGNATURE_INVALID:
00136             return "CKR_SIGNATURE_INVALID";
00137         case CKR_SIGNATURE_LEN_RANGE:
00138             return "CKR_SIGNATURE_LEN_RANGE";
00139         case CKR_TEMPLATE_INCOMPLETE:
00140             return "CKR_TEMPLATE_INCOMPLETE";
00141         case CKR_TEMPLATE_INCONSISTENT:
00142             return "CKR_TEMPLATE_INCONSISTENT";
00143         case CKR_TOKEN_NOT_PRESENT:
00144             return "CKR_TOKEN_NOT_PRESENT";
00145         case CKR_TOKEN_NOT_RECOGNIZED:
00146             return "CKR_TOKEN_NOT_RECOGNIZED";
00147         case CKR_TOKEN_WRITE_PROTECTED:
00148             return "CKR_TOKEN_WRITE_PROTECTED";
00149         case CKR_UNWRAPPING_KEY_HANDLE_INVALID:
00150             return "CKR_UNWRAPPING_KEY_HANDLE_INVALID";
00151         case CKR_UNWRAPPING_KEY_SIZE_RANGE:
00152             return "CKR_UNWRAPPING_KEY_SIZE_RANGE";
00153         case CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT:
00154             return "CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT";
00155         case CKR_USER_ALREADY_LOGGED_IN:
00156             return "CKR_USER_ALREADY_LOGGED_IN";
00157         case CKR_USER_NOT_LOGGED_IN:
00158             return "CKR_USER_NOT_LOGGED_IN";
00159         case CKR_USER_PIN_NOT_INITIALIZED:
00160             return "CKR_USER_PIN_NOT_INITIALIZED";
00161         case CKR_USER_TYPE_INVALID:
00162             return "CKR_USER_TYPE_INVALID";
00163         case CKR_WRAPPED_KEY_INVALID:
00164             return "CKR_WRAPPED_KEY_INVALID";
00165         case CKR_WRAPPED_KEY_LEN_RANGE:
00166             return "CKR_WRAPPED_KEY_LEN_RANGE";
00167         case CKR_WRAPPING_KEY_HANDLE_INVALID:
00168             return "CKR_WRAPPING_KEY_HANDLE_INVALID";
00169         case CKR_WRAPPING_KEY_SIZE_RANGE:
00170             return "CKR_WRAPPING_KEY_SIZE_RANGE";
00171         case CKR_WRAPPING_KEY_TYPE_INCONSISTENT:
00172             return "CKR_WRAPPING_KEY_TYPE_INCONSISTENT";
00173         case CKR_RANDOM_SEED_NOT_SUPPORTED:
00174             return "CKR_RANDOM_SEED_NOT_SUPPORTED";
00175         case CKR_VENDOR_DEFINED:
00176             return "CKR_VENDOR_DEFINED";
00177         case CKR_BUFFER_TOO_SMALL:
00178             return "CKR_BUFFER_TOO_SMALL";
00179         case CKR_SAVED_STATE_INVALID:
00180             return "CKR_SAVED_STATE_INVALID";
00181         case CKR_INFORMATION_SENSITIVE:
00182             return "CKR_INFORMATION_SENSITIVE";
00183         case CKR_STATE_UNSAVEABLE:
00184             return "CKR_STATE_UNSAVEABLE";
00185         case CKR_CRYPTOKI_NOT_INITIALIZED:
00186             return "CKR_CRYPTOKI_NOT_INITIALIZED";
00187         case CKR_CRYPTOKI_ALREADY_INITIALIZED:
00188             return "CKR_CRYPTOKI_ALREADY_INITIALIZED";
00189         case CKR_MUTEX_BAD:
00190             return "CKR_MUTEX_BAD";
00191         case CKR_MUTEX_NOT_LOCKED:
00192             return "CKR_MUTEX_NOT_LOCKED";
00193         default:
00194             return "Unknown error";
00195         }
00196 }
00197 
00209 static void
00210 hsm_ctx_set_error(hsm_ctx_t *ctx, int error, const char *action,
00211                  const char *message, ...)
00212 {
00213     va_list args;
00214 
00215     if (ctx && ctx->error == 0) {
00216         ctx->error = error;
00217         ctx->error_action = action;
00218 
00219         va_start(args, message);
00220         vsnprintf(ctx->error_message, sizeof(ctx->error_message),
00221             message, args);
00222         va_end(args);
00223     }
00224 }
00225 
00237 static int
00238 hsm_pkcs11_check_error(hsm_ctx_t *ctx, CK_RV rv, const char *action)
00239 {
00240     if (rv != CKR_OK) {
00241         if (ctx && ctx->error == 0) {
00242             ctx->error = (int) rv;
00243             ctx->error_action = action;
00244             strlcpy(ctx->error_message, ldns_pkcs11_rv_str(rv), sizeof(ctx->error_message));
00245         }
00246         return 1;
00247     }
00248     return 0;
00249 }
00250 
00252 static void
00253 hsm_pkcs11_unload_functions(void *handle)
00254 {
00255     int result;
00256     if (handle) {
00257 #if defined(HAVE_LOADLIBRARY)
00258         /* no idea */
00259 #elif defined(HAVE_DLOPEN)
00260         result = dlclose(handle);
00261 #endif
00262     }
00263 }
00264 
00266 static CK_RV
00267 hsm_pkcs11_load_functions(hsm_module_t *module)
00268 {
00269     CK_C_GetFunctionList pGetFunctionList = NULL;
00270 
00271     if (module && module->path) {
00272         /* library provided by application or user */
00273 
00274 #if defined(HAVE_LOADLIBRARY)
00275         /* Load PKCS #11 library */
00276         HINSTANCE hDLL = LoadLibrary(_T(module->path));
00277 
00278         if (hDLL == NULL) {
00279             /* Failed to load the PKCS #11 library */
00280             return CKR_FUNCTION_FAILED;
00281         }
00282 
00283         /* Retrieve the entry point for C_GetFunctionList */
00284         pGetFunctionList = (CK_C_GetFunctionList)
00285             GetProcAddress(hDLL, _T("C_GetFunctionList"));
00286 
00287 #elif defined(HAVE_DLOPEN)
00288         /* Load PKCS #11 library */
00289         void* pDynLib = dlopen(module->path, RTLD_NOW | RTLD_LOCAL);
00290 
00291         if (pDynLib == NULL) {
00292             /* Failed to load the PKCS #11 library */
00293             return CKR_FUNCTION_FAILED;
00294         }
00295 
00296         /* Retrieve the entry point for C_GetFunctionList */
00297         pGetFunctionList = (CK_C_GetFunctionList) dlsym(pDynLib, "C_GetFunctionList");
00298         /* Store the handle so we can dlclose it later */
00299         module->handle = pDynLib;
00300 
00301 #else
00302         return CKR_FUNCTION_FAILED;
00303 #endif
00304     } else {
00305         /* No library provided, use the statically compiled softHSM */
00306 #ifdef HAVE_PKCS11_MODULE
00307         return C_GetFunctionList(pkcs11_functions);
00308 #else
00309         return CKR_FUNCTION_FAILED;
00310 #endif
00311     }
00312 
00313     if (pGetFunctionList == NULL) {
00314         /* Failed to load the PKCS #11 library */
00315         return CKR_FUNCTION_FAILED;
00316     }
00317 
00318     /* Retrieve the function list */
00319     (pGetFunctionList)((CK_FUNCTION_LIST_PTR)(&module->sym));
00320     return CKR_OK;
00321 }
00322 
00323 static int
00324 hsm_pkcs11_check_token_name(hsm_ctx_t *ctx,
00325                             CK_FUNCTION_LIST_PTR pkcs11_functions,
00326                             CK_SLOT_ID slotId,
00327                             const char *token_name)
00328 {
00329     /* token label is always 32 bytes */
00330     char token_name_bytes[HSM_TOKEN_LABEL_LENGTH];
00331     int result = 0;
00332     CK_RV rv;
00333     CK_TOKEN_INFO token_info;
00334 
00335     rv = pkcs11_functions->C_GetTokenInfo(slotId, &token_info);
00336     if (hsm_pkcs11_check_error(ctx, rv, "C_GetTokenInfo")) {
00337         return 0;
00338     }
00339 
00340     memset(token_name_bytes, ' ', HSM_TOKEN_LABEL_LENGTH);
00341     if (strlen(token_name) < HSM_TOKEN_LABEL_LENGTH) {
00342         memcpy(token_name_bytes, token_name, strlen(token_name));
00343     } else {
00344         memcpy(token_name_bytes, token_name, HSM_TOKEN_LABEL_LENGTH);
00345     }
00346 
00347     result = memcmp(token_info.label,
00348                     token_name_bytes,
00349                     HSM_TOKEN_LABEL_LENGTH) == 0;
00350 
00351     return result;
00352 }
00353 
00354 
00355 int
00356 hsm_get_slot_id(hsm_ctx_t *ctx,
00357                 CK_FUNCTION_LIST_PTR pkcs11_functions,
00358                 const char *token_name, CK_SLOT_ID *slotId)
00359 {
00360     CK_RV rv;
00361     CK_ULONG slotCount;
00362     CK_SLOT_ID cur_slot;
00363     CK_SLOT_ID *slotIds;
00364     int found = 0;
00365 
00366     if (token_name == NULL || slotId == NULL) return HSM_ERROR;
00367 
00368     rv = pkcs11_functions->C_GetSlotList(CK_TRUE, NULL_PTR, &slotCount);
00369     if (hsm_pkcs11_check_error(ctx, rv, "get slot list")) {
00370         return HSM_ERROR;
00371     }
00372 
00373     if (slotCount < 1) {
00374         hsm_ctx_set_error(ctx, HSM_ERROR, "hsm_get_slot_id()",
00375                           "No slots found in HSM");
00376         return HSM_ERROR;
00377     }
00378 
00379     slotIds = malloc(sizeof(CK_SLOT_ID) * slotCount);
00380     rv = pkcs11_functions->C_GetSlotList(CK_TRUE, slotIds, &slotCount);
00381     if (hsm_pkcs11_check_error(ctx, rv, "get slot list")) {
00382         return HSM_ERROR;
00383     }
00384 
00385     for (cur_slot = 0; cur_slot < slotCount; cur_slot++) {
00386         if (hsm_pkcs11_check_token_name(ctx,
00387                                         pkcs11_functions,
00388                                         slotIds[cur_slot],
00389                                         token_name)) {
00390             *slotId = slotIds[cur_slot];
00391             found = 1;
00392             break;
00393         }
00394     }
00395     free(slotIds);
00396     if (!found) {
00397         hsm_ctx_set_error(ctx, -1, "hsm_get_slot_id()",
00398             "could not find token with the name %s", token_name);
00399         return HSM_ERROR;
00400     }
00401 
00402     return HSM_OK;
00403 }
00404 
00405 /* internal functions */
00406 static hsm_module_t *
00407 hsm_module_new(const char *repository,
00408                const char *token_label,
00409                const char *path,
00410                const hsm_config_t *config)
00411 {
00412     hsm_module_t *module;
00413 
00414     if (!repository || !path) return NULL;
00415 
00416     
00417     module = malloc(sizeof(hsm_module_t));
00418     if (!module) return NULL;
00419 
00420     if (config) {
00421         module->config = malloc(sizeof(hsm_config_t));
00422         if (!module->config) {
00423             free(module);
00424             return NULL;
00425         }
00426         memcpy(module->config, config, sizeof(hsm_config_t));
00427     } else {
00428         module->config = NULL;
00429     }
00430 
00431     module->id = 0; /*TODO i think we can remove this*/
00432     module->name = strdup(repository);
00433     module->token_label = strdup(token_label);
00434     module->path = strdup(path);
00435     module->handle = NULL;
00436     module->sym = NULL;
00437     
00438     return module;
00439 }
00440 
00441 static void
00442 hsm_module_free(hsm_module_t *module)
00443 {
00444     if (module) {
00445         if (module->name) free(module->name);
00446         if (module->token_label) free(module->token_label);
00447         if (module->path) free(module->path);
00448         if (module->config) free(module->config);
00449 
00450         free(module);
00451     }
00452 }
00453 
00454 static hsm_session_t *
00455 hsm_session_new(hsm_module_t *module, CK_SESSION_HANDLE session_handle)
00456 {
00457     hsm_session_t *session;
00458     session = malloc(sizeof(hsm_session_t));
00459     session->module = module;
00460     session->session = session_handle;
00461     return session;
00462 }
00463 
00464 static void
00465 hsm_session_free(hsm_session_t *session) {
00466     if (session) {
00467         free(session);
00468     }
00469 }
00470 
00472 static void
00473 hsm_config_default(hsm_config_t *config)
00474 {
00475     config->use_pubkey = 1;
00476 }
00477 
00478 /* creates a session_t structure, and automatically adds and initializes
00479  * a module_t struct for it
00480  */
00481 static int
00482 hsm_session_init(hsm_ctx_t *ctx, hsm_session_t **session,
00483                  const char *repository, const char *token_label,
00484                  const char *module_path, const char *pin,
00485                  const hsm_config_t *config)
00486 {
00487     CK_RV rv;
00488     CK_RV rv_login;
00489     hsm_module_t *module;
00490     CK_SLOT_ID slot_id;
00491     CK_SESSION_HANDLE session_handle;
00492     int first = 1, result;
00493 
00494     CK_C_INITIALIZE_ARGS InitArgs = {NULL, NULL, NULL, NULL,
00495                                      CKF_OS_LOCKING_OK, NULL };
00496 
00497     module = hsm_module_new(repository, token_label, module_path, config);
00498     if (!module) return HSM_ERROR;
00499     rv = hsm_pkcs11_load_functions(module);
00500     if (rv != CKR_OK) {
00501         hsm_ctx_set_error(ctx, HSM_MODULE_NOT_FOUND,
00502             "hsm_session_init()",
00503             "PKCS#11 module load failed: %s", module_path);
00504         hsm_module_free(module);
00505         return HSM_MODULE_NOT_FOUND;
00506     }
00507     rv = ((CK_FUNCTION_LIST_PTR) module->sym)->C_Initialize((CK_VOID_PTR) &InitArgs);
00508     /* ALREADY_INITIALIZED is ok, apparently we are using a second
00509      * device with the same library */
00510     if (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
00511         if (hsm_pkcs11_check_error(ctx, rv, "Initialization")) {
00512             hsm_module_free(module);
00513             return HSM_ERROR;
00514         }
00515     } else {
00516         first = 0;
00517     }
00518     result = hsm_get_slot_id(ctx, module->sym, token_label, &slot_id);
00519     if (result != HSM_OK) {
00520         hsm_module_free(module);
00521         return HSM_ERROR;
00522     }
00523     rv = ((CK_FUNCTION_LIST_PTR) module->sym)->C_OpenSession(slot_id,
00524                                CKF_SERIAL_SESSION | CKF_RW_SESSION,
00525                                NULL,
00526                                NULL,
00527                                &session_handle);
00528     if (hsm_pkcs11_check_error(ctx, rv, "Open first session")) {
00529         hsm_module_free(module);
00530         return HSM_ERROR;
00531     }
00532     rv_login = ((CK_FUNCTION_LIST_PTR) module->sym)->C_Login(session_handle,
00533                                    CKU_USER,
00534                                    (unsigned char *) pin,
00535                                    strlen((char *)pin));
00536 
00537     if (rv_login == CKR_OK) {
00538         *session = hsm_session_new(module, session_handle);
00539         return HSM_OK;
00540     } else {
00541         /* uninitialize the session again */
00542         if (session_handle) {
00543             rv = ((CK_FUNCTION_LIST_PTR) module->sym)->
00544                    C_CloseSession(session_handle);
00545             if (hsm_pkcs11_check_error(ctx, rv,
00546                 "finalize after failed login")) {
00547                 hsm_module_free(module);
00548                 return HSM_ERROR;
00549             }
00550         }
00551         /* if this was not the first, don't close the library for
00552          * the rest of us */
00553         if (first) {
00554             rv = ((CK_FUNCTION_LIST_PTR) module->sym)->C_Finalize(NULL);
00555             if (hsm_pkcs11_check_error(ctx, rv, "finalize after failed login")) {
00556                 hsm_module_free(module);
00557                 return HSM_ERROR;
00558             }
00559         }
00560         hsm_module_free(module);
00561         *session = NULL;
00562         switch(rv_login) {
00563         case CKR_PIN_INCORRECT:
00564             hsm_ctx_set_error(ctx, HSM_PIN_INCORRECT,
00565                     "hsm_session_init()",
00566                     "Incorrect PIN for repository %s", repository);
00567             return HSM_PIN_INCORRECT;
00568         default:
00569             return HSM_ERROR;
00570         }
00571     }
00572 }
00573 
00574 /* open a second session from the given one */
00575 static hsm_session_t *
00576 hsm_session_clone(hsm_ctx_t *ctx, hsm_session_t *session)
00577 {
00578     CK_RV rv;
00579     CK_SLOT_ID slot_id;
00580     CK_SESSION_HANDLE session_handle;
00581     hsm_session_t *new_session;
00582     int result;
00583 
00584     result = hsm_get_slot_id(ctx,
00585                               session->module->sym,
00586                               session->module->token_label,
00587                               &slot_id);
00588     if (result != HSM_OK) return NULL;
00589     rv = ((CK_FUNCTION_LIST_PTR) session->module->sym)->C_OpenSession(slot_id,
00590                                     CKF_SERIAL_SESSION | CKF_RW_SESSION,
00591                                     NULL,
00592                                     NULL,
00593                                     &session_handle);
00594 
00595     if (hsm_pkcs11_check_error(ctx, rv, "Clone session")) {
00596         return NULL;
00597     }
00598     new_session = hsm_session_new(session->module, session_handle);
00599 
00600     return new_session;
00601 }
00602 
00603 static hsm_ctx_t *
00604 hsm_ctx_new()
00605 {
00606     hsm_ctx_t *ctx;
00607     ctx = malloc(sizeof(hsm_ctx_t));
00608     memset(ctx->session, 0, HSM_MAX_SESSIONS);
00609     ctx->session_count = 0;
00610     ctx->error = 0;
00611     return ctx;
00612 }
00613 
00614 /* ctx_free frees the structure */
00615 static void
00616 hsm_ctx_free(hsm_ctx_t *ctx)
00617 {
00618     unsigned int i;
00619     if (ctx) {
00620         for (i = 0; i < ctx->session_count; i++) {
00621             hsm_session_free(ctx->session[i]);
00622         }
00623         free(ctx);
00624     }
00625 }
00626 
00627 /* close the session, and free the allocated data
00628  *
00629  * if unload is non-zero, C_Logout() is called,
00630  * the dlopen()d module is closed and unloaded
00631  * (only call this on the last session for each
00632  * module, ie. the one in the global ctx)
00633  */
00634 static void
00635 hsm_session_close(hsm_ctx_t *ctx, hsm_session_t *session, int unload)
00636 {
00637     /* If we loaded this library more than once, we may have
00638      * already finalized it before, so we can safely ignore
00639      * NOT_INITIALIZED */
00640     CK_RV rv;
00641     if (unload) {
00642         rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_Logout(session->session);
00643         if (rv != CKR_CRYPTOKI_NOT_INITIALIZED) {
00644             (void) hsm_pkcs11_check_error(ctx, rv, "Logout");
00645         }
00646     }
00647     rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_CloseSession(session->session);
00648     if (rv != CKR_CRYPTOKI_NOT_INITIALIZED) {
00649         (void) hsm_pkcs11_check_error(ctx, rv, "Close session");
00650     }
00651     if (unload) {
00652         rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_Finalize(NULL);
00653         if (rv != CKR_CRYPTOKI_NOT_INITIALIZED) {
00654             (void) hsm_pkcs11_check_error(ctx, rv, "Finalize");
00655             hsm_pkcs11_unload_functions(session->module->handle);
00656         }
00657         hsm_module_free(session->module);
00658         session->module = NULL;
00659     }
00660     hsm_session_free(session);
00661 }
00662 
00663 /* ctx_close closes all session, and free
00664  * the structures.
00665  *
00666  * if unload is non-zero, the associated dynamic libraries are unloaded
00667  * (hence only use that on the last, global, ctx)
00668  */
00669 static void
00670 hsm_ctx_close(hsm_ctx_t *ctx, int unload)
00671 {
00672     unsigned int i;
00673 
00674     if (ctx) {
00675         for (i = 0; i < ctx->session_count; i++) {
00676             /* todo syslog? */
00677             /*printf("close session %u (unload: %d)\n", i, unload);*/
00678             /*hsm_print_ctx(ctx);*/
00679             hsm_session_close(ctx, ctx->session[i], unload);
00680             ctx->session[i] = NULL;
00681             /* if this was the last session in the array, decrease
00682              * the session counter of the context */
00683             if (i == _hsm_ctx->session_count) {
00684                 while(ctx->session_count > 0 && !ctx->session[i]) {
00685                     ctx->session_count--;
00686                 }
00687             }
00688         }
00689         free(ctx);
00690     }
00691 }
00692 
00693 
00694 /* adds a session to the context.
00695  * returns  0 on success
00696  *          1 if the maximum number of sessions (HSM_MAX_SESSIONS) was
00697  *            reached
00698  *          -1 if one of the arguments is NULL
00699  */
00700 static int
00701 hsm_ctx_add_session(hsm_ctx_t *ctx, hsm_session_t *session)
00702 {
00703     if (!ctx || !session) return -1;
00704     if (ctx->session_count >= HSM_MAX_SESSIONS) return 1;
00705     ctx->session[ctx->session_count] = session;
00706     ctx->session_count++;
00707     return 0;
00708 }
00709 
00710 static hsm_ctx_t *
00711 hsm_ctx_clone(hsm_ctx_t *ctx)
00712 {
00713     unsigned int i;
00714     hsm_ctx_t *new_ctx;
00715     hsm_session_t *new_session;
00716 
00717     new_ctx = NULL;
00718     if (ctx) {
00719         new_ctx = hsm_ctx_new();
00720         for (i = 0; i < ctx->session_count; i++) {
00721             new_session = hsm_session_clone(ctx, ctx->session[i]);
00722             if (!new_session) {
00723                 /* one of the sessions failed to clone. Clear the
00724                  * new ctx and return NULL */
00725                 hsm_ctx_close(new_ctx, 0);
00726                 return NULL;
00727             }
00728             hsm_ctx_add_session(new_ctx, new_session);
00729         }
00730     }
00731     return new_ctx;
00732 }
00733 
00734 static hsm_key_t *
00735 hsm_key_new()
00736 {
00737     hsm_key_t *key;
00738     key = malloc(sizeof(hsm_key_t));
00739     key->module = NULL;
00740     key->private_key = 0;
00741     key->public_key = 0;
00742     return key;
00743 }
00744 
00745 /* find the session belonging to a key, by iterating over the modules
00746  * in the context */
00747 static hsm_session_t *
00748 hsm_find_key_session(hsm_ctx_t *ctx, const hsm_key_t *key)
00749 {
00750     unsigned int i;
00751     if (!key || !key->module) return NULL;
00752     if (!ctx) ctx = _hsm_ctx;
00753     for (i = 0; i < ctx->session_count; i++) {
00754         if (ctx->session[i] && ctx->session[i]->module == key->module) {
00755             return ctx->session[i];
00756         }
00757     }
00758     return NULL;
00759 }
00760 
00761 /* Returns the key type (algorithm) of the given key */
00762 static CK_KEY_TYPE
00763 hsm_get_key_algorithm(hsm_ctx_t *ctx, const hsm_session_t *session,
00764                       const hsm_key_t *key)
00765 {
00766     CK_RV rv;
00767     CK_KEY_TYPE key_type;
00768 
00769     CK_ATTRIBUTE template[] = {
00770         {CKA_KEY_TYPE, &key_type, sizeof(CK_KEY_TYPE)}
00771     };
00772 
00773     rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
00774                                       session->session,
00775                                       key->private_key,
00776                                       template,
00777                                       1);
00778     if (hsm_pkcs11_check_error(ctx, rv,
00779                                "Get attr value algorithm type")) {
00780         /* this is actually not a good return value;
00781          * CKK_RSA is also 0. But we can't return a negative
00782          * value. Should we #define a specific 'key type' that
00783          * indicates an error? (TODO) */
00784         return 0;
00785     }
00786 
00787     if ((CK_LONG)template[0].ulValueLen < 1) {
00788         /* this is actually not a good return value;
00789          * CKK_RSA is also 0. But we can't return a negative
00790          * value. Should we #define a specific 'key type' that
00791          * indicates an error? (TODO) */
00792         return 0;
00793     }
00794 
00795     return key_type;
00796 }
00797 
00798 /* returns a CK_ULONG with the key size of the given RSA key. The
00799  * key is not checked for type. For RSA, the number of bits in the
00800  * modulus is the key size (CKA_MODULUS_BITS)
00801  */
00802 static CK_ULONG
00803 hsm_get_key_size_rsa(hsm_ctx_t *ctx, const hsm_session_t *session,
00804                      const hsm_key_t *key)
00805 {
00806     CK_RV rv;
00807     CK_ULONG modulus_bits;
00808 
00809     /* Template for public keys */
00810     CK_ATTRIBUTE template[] = {
00811         {CKA_MODULUS_BITS, &modulus_bits, sizeof(CK_KEY_TYPE)}
00812     };
00813 
00814     /* Template for private keys */
00815     CK_BYTE_PTR modulus = NULL;
00816     int mask;
00817     CK_ATTRIBUTE template2[] = {
00818         {CKA_MODULUS, NULL, 0}
00819     };
00820 
00821     if (session->module->config->use_pubkey) {
00822         rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
00823                                           session->session,
00824                                           key->public_key,
00825                                           template,
00826                                           1);
00827         if (hsm_pkcs11_check_error(ctx, rv,
00828                                    "Get attr value algorithm type")) {
00829             return 0;
00830         }
00831     
00832         if ((CK_ULONG)template[0].ulValueLen < 1) {
00833             return 0;
00834         }
00835     } else {
00836         // Get buffer size
00837         rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
00838                                           session->session,
00839                                           key->private_key,
00840                                           template2,
00841                                           1);
00842         if (hsm_pkcs11_check_error(ctx, rv, "Could not get the size of the modulus of the private key")) {
00843             return 0;
00844         }
00845 
00846         // Allocate memory
00847         modulus = (CK_BYTE_PTR)malloc(template2[0].ulValueLen);
00848         template2[0].pValue = modulus;
00849         if (modulus == NULL) {
00850             hsm_ctx_set_error(ctx, -1, "hsm_get_key_size_rsa()",
00851                 "Error allocating memory for modulus");
00852             return 0;
00853         }
00854 
00855         // Get attribute
00856         rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
00857                                           session->session,
00858                                           key->private_key,
00859                                           template2,
00860                                           1);
00861         if (hsm_pkcs11_check_error(ctx, rv, "Could not get the modulus of the private key")) {
00862             free(modulus);
00863             return 0;
00864         }
00865 
00866         // Calculate size
00867         modulus_bits = template2[0].ulValueLen * 8;
00868         mask = 0x80;
00869         for (int i = 0; modulus_bits && (modulus[i] & mask) == 0; modulus_bits--) {
00870             mask >>= 1;
00871             if (mask == 0) {
00872                 i++;
00873                 mask = 0x80;
00874             }
00875         }
00876         free(modulus);
00877     }
00878 
00879     return modulus_bits;
00880 }
00881 
00882 /* Wrapper for specific key size functions, currently only supports
00883  * CKK_RSA (the value 0) as algorithm identifier */
00884 static CK_ULONG
00885 hsm_get_key_size(hsm_ctx_t *ctx, const hsm_session_t *session,
00886                  const hsm_key_t *key, const unsigned long algorithm)
00887 {
00888     switch (algorithm) {
00889         case CKK_RSA:
00890             return hsm_get_key_size_rsa(ctx, session, key);
00891             break;
00892         default:
00893             return 0;
00894     }
00895 }
00896 
00897 static CK_OBJECT_HANDLE
00898 hsm_find_object_handle_for_id(hsm_ctx_t *ctx,
00899                               const hsm_session_t *session,
00900                               CK_OBJECT_CLASS key_class,
00901                               CK_BYTE *id,
00902                               CK_ULONG id_len)
00903 {
00904     CK_ULONG objectCount;
00905     CK_OBJECT_HANDLE object;
00906     CK_RV rv;
00907 
00908     CK_ATTRIBUTE template[] = {
00909         { CKA_CLASS, &key_class, sizeof(key_class) },
00910         { CKA_ID, id, id_len },
00911     };
00912 
00913     rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_FindObjectsInit(session->session,
00914                                                  template, 2);
00915     if (hsm_pkcs11_check_error(ctx, rv, "Find objects init")) {
00916         return 0;
00917     }
00918 
00919     rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_FindObjects(session->session,
00920                                          &object,
00921                                          1,
00922                                          &objectCount);
00923     if (hsm_pkcs11_check_error(ctx, rv, "Find object")) {
00924         return 0;
00925     }
00926 
00927     rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_FindObjectsFinal(session->session);
00928     if (hsm_pkcs11_check_error(ctx, rv, "Find object final")) {
00929         return 0;
00930     }
00931 
00932     if (objectCount > 0) {
00933         return object;
00934     } else {
00935         return 0;
00936     }
00937 }
00938 
00939 /*
00940  * Parses the null-terminated string hex as hex values,
00941  * Returns allocated data that needs to be freed (or NULL on error)
00942  * len will contain the number of bytes allocated, or 0 on error
00943  */
00944 static unsigned char *
00945 hsm_hex_parse(const char *hex, size_t *len)
00946 {
00947     unsigned char *bytes;
00948     /* length of the hex input */
00949     size_t hex_len;
00950     size_t i;
00951 
00952     if (!len) return NULL;
00953     *len = 0;
00954 
00955     if (!hex) return NULL;
00956     hex_len = strlen(hex);
00957     if (hex_len % 2 != 0) {
00958         return NULL;
00959     }
00960 
00961     *len = hex_len / 2;
00962     bytes = malloc(*len);
00963     for (i = 0; i < *len; i++) {
00964         bytes[i] = ldns_hexdigit_to_int(hex[2*i]) * 16 +
00965                    ldns_hexdigit_to_int(hex[2*i+1]);
00966     }
00967     return bytes;
00968 }
00969 
00970 /* put a hexadecimal representation of the data from src into dst
00971  * len is the number of bytes to read from src
00972  * dst must have allocated enough space (len*2 + 1)
00973  */
00974 static void
00975 hsm_hex_unparse(char *dst, const unsigned char *src, size_t len)
00976 {
00977     size_t dst_len = len*2 + 1;
00978     size_t i;
00979 
00980     for (i = 0; i < len; i++) {
00981         snprintf(dst + (2*i), dst_len, "%02x", src[i]);
00982     }
00983     dst[len*2] = '\0';
00984 }
00985 
00986 /* returns an allocated byte array with the CKA_ID for the given object
00987  * len will contain the result size
00988  * returns NULL and size zero if not found in this session
00989  */
00990 static CK_BYTE *
00991 hsm_get_id_for_object(hsm_ctx_t *ctx,
00992                       const hsm_session_t *session,
00993                       CK_OBJECT_HANDLE object,
00994                       size_t *len)
00995 {
00996     CK_RV rv;
00997     CK_BYTE *id = NULL;
00998 
00999     CK_ATTRIBUTE template[] = {
01000         {CKA_ID, id, 0}
01001     };
01002 
01003     /* find out the size of the id first */
01004     rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
01005                                       session->session,
01006                                       object,
01007                                       template,
01008                                       1);
01009     if (hsm_pkcs11_check_error(ctx, rv, "Get attr value")) {
01010         *len = 0;
01011         return NULL;
01012     }
01013 
01014     if ((CK_LONG)template[0].ulValueLen < 1) {
01015         /* No CKA_ID found, return NULL */
01016         *len = 0;
01017         return NULL;
01018     }
01019 
01020     template[0].pValue = malloc(template[0].ulValueLen);
01021     rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
01022                                       session->session,
01023                                       object,
01024                                       template,
01025                                       1);
01026     if (hsm_pkcs11_check_error(ctx, rv, "Get attr value 2")) {
01027         *len = 0;
01028         free(template[0].pValue);
01029         return NULL;
01030     }
01031 
01032     *len = template[0].ulValueLen;
01033     return template[0].pValue;
01034 }
01035 
01036 /* returns an hsm_key_t object for the given *private key* object handle
01037  * the module, private key, and public key handle are set
01038  * The session needs to be free to perform a search for the public key
01039  */
01040 static hsm_key_t *
01041 hsm_key_new_privkey_object_handle(hsm_ctx_t *ctx,
01042                                   const hsm_session_t *session,
01043                                   CK_OBJECT_HANDLE object)
01044 {
01045     hsm_key_t *key;
01046     CK_BYTE *id;
01047     size_t len;
01048 
01049     id = hsm_get_id_for_object(ctx, session, object, &len);
01050 
01051     if (!id) return NULL;
01052 
01053     key = hsm_key_new();
01054     key->module = session->module;
01055     key->private_key = object;
01056     
01057     if (session->module->config->use_pubkey) {
01058         key->public_key = hsm_find_object_handle_for_id(
01059                               ctx,
01060                               session,
01061                               CKO_PUBLIC_KEY,
01062                               id,
01063                               len);
01064     } else {
01065         key->public_key = 0;
01066     }
01067 
01068     free(id);
01069     return key;
01070 }
01071 
01072 /* helper function to find both key counts or the keys themselves
01073  * if the argument store is 0, results are not returned; the
01074  * function will only set the count and return NULL
01075  * Otherwise, a newly allocated key array will be returned
01076  * (on error, the count will also be zero and NULL returned)
01077  */
01078 static hsm_key_t **
01079 hsm_list_keys_session_internal(hsm_ctx_t *ctx,
01080                                const hsm_session_t *session,
01081                                size_t *count,
01082                                int store)
01083 {
01084     hsm_key_t **keys = NULL;
01085     hsm_key_t *key;
01086     CK_RV rv;
01087     CK_OBJECT_CLASS key_class = CKO_PRIVATE_KEY;
01088     CK_ATTRIBUTE template[] = {
01089         { CKA_CLASS, &key_class, sizeof(key_class) },
01090     };
01091     CK_ULONG total_count = 0;
01092     CK_ULONG objectCount = 1;
01093     /* find 100 keys at a time (and loop until there are none left) */
01094     CK_ULONG max_object_count = 100;
01095     CK_ULONG i, j;
01096     CK_OBJECT_HANDLE object[max_object_count];
01097     CK_OBJECT_HANDLE *key_handles = NULL;
01098 
01099     rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_FindObjectsInit(session->session,
01100                                                  template, 1);
01101     if (hsm_pkcs11_check_error(ctx, rv, "Find objects init")) {
01102         *count = 0;
01103         return NULL;
01104     }
01105     j = 0;
01106     while (objectCount > 0) {
01107         rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_FindObjects(session->session,
01108                                                  object,
01109                                                  max_object_count,
01110                                                  &objectCount);
01111         if (hsm_pkcs11_check_error(ctx, rv, "Find first object")) {
01112             free(key_handles);
01113             *count = 0;
01114             return NULL;
01115         }
01116 
01117         total_count += objectCount;
01118         if (objectCount > 0 && store) {
01119             key_handles = realloc(key_handles, total_count * sizeof(CK_OBJECT_HANDLE));
01120             for (i = 0; i < objectCount; i++) {
01121                 key_handles[j] = object[i];
01122                 j++;
01123             }
01124         }
01125     }
01126 
01127     rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_FindObjectsFinal(session->session);
01128     if (hsm_pkcs11_check_error(ctx, rv, "Find objects final")) {
01129         free(key_handles);
01130         *count = 0;
01131         return NULL;
01132     }
01133 
01134     if (store) {
01135         keys = realloc(keys, total_count * sizeof(hsm_key_t *));
01136         for (i = 0; i < total_count; i++) {
01137             key = hsm_key_new_privkey_object_handle(ctx, session,
01138                                                     key_handles[i]);
01139             /* todo, if we get NULL, free all and return error? */
01140             keys[i] = key;
01141         }
01142     }
01143     free(key_handles);
01144 
01145     *count = total_count;
01146     return keys;
01147 }
01148 
01149 
01150 /* returns an array of all keys available to the given session
01151  *
01152  * \param session the session to find the keys in
01153  * \param count this value will contain the number of keys found
01154  *
01155  * \return the list of keys
01156  */
01157 hsm_key_t **
01158 hsm_list_keys_session(hsm_ctx_t *ctx, const hsm_session_t *session,
01159                       size_t *count)
01160 {
01161     return hsm_list_keys_session_internal(ctx, session, count, 1);
01162 }
01163 
01164 /* returns a count all keys available to the given session
01165  *
01166  * \param session the session to find the keys in
01167  *
01168  * \return the number of keys
01169  */
01170 size_t
01171 hsm_count_keys_session(hsm_ctx_t *ctx, const hsm_session_t *session)
01172 {
01173     size_t count = 0;
01174     (void) hsm_list_keys_session_internal(ctx, session, &count, 0);
01175     return count;
01176 }
01177 
01178 /* returns a newly allocated key structure containing the key data
01179  * for the given CKA_ID available in the session. Returns NULL if not
01180  * found
01181  */
01182 static hsm_key_t *
01183 hsm_find_key_by_id_session(hsm_ctx_t *ctx, const hsm_session_t *session,
01184                            const unsigned char *id, size_t len)
01185 {
01186     hsm_key_t *key;
01187     CK_OBJECT_HANDLE private_key_handle;
01188 
01189     private_key_handle = hsm_find_object_handle_for_id(
01190                              ctx,
01191                              session,
01192                              CKO_PRIVATE_KEY,
01193                              (CK_BYTE *) id,
01194                              (CK_ULONG) len);
01195     if (private_key_handle != 0) {
01196         key = hsm_key_new_privkey_object_handle(ctx, session,
01197                                                 private_key_handle);
01198         return key;
01199     } else {
01200         return NULL;
01201     }
01202 }
01203 
01204 /* Find a key pair by CKA_ID (as byte array)
01205 
01206 The returned key structure can be freed with hsm_key_free()
01207 
01208 \param context HSM context
01209 \param id CKA_ID of key to find (array of bytes)
01210 \param len number of bytes in the id
01211 \return key identifier or NULL if not found
01212 */
01213 static hsm_key_t *
01214 hsm_find_key_by_id_bin(hsm_ctx_t *ctx,
01215                        const unsigned char *id,
01216                        size_t len)
01217 {
01218     hsm_key_t *key;
01219     unsigned int i;
01220 
01221     if (!ctx) ctx = _hsm_ctx;
01222     if (!id) return NULL;
01223 
01224     for (i = 0; i < ctx->session_count; i++) {
01225         key = hsm_find_key_by_id_session(ctx, ctx->session[i], id, len);
01226         if (key) return key;
01227     }
01228     return NULL;
01229 }
01230 
01231 
01237 static hsm_session_t *
01238 hsm_find_repository_session(hsm_ctx_t *ctx, const char *repository)
01239 {
01240     unsigned int i;
01241     if (!repository) {
01242         for (i = 0; i < ctx->session_count; i++) {
01243             if (ctx->session[i]) {
01244                 return ctx->session[i];
01245             }
01246         }
01247     } else {
01248         for (i = 0; i < ctx->session_count; i++) {
01249             if (ctx->session[i] &&
01250                 strcmp(repository, ctx->session[i]->module->name) == 0)
01251             {
01252                 return ctx->session[i];
01253             }
01254         }
01255     }
01256 
01257     hsm_ctx_set_error(ctx, HSM_REPOSITORY_NOT_FOUND,
01258                     "hsm_find_repository_session()",
01259                     "Can't find repository: %s", repository);
01260 
01261     return NULL;
01262 }
01263 
01264 static ldns_rdf *
01265 hsm_get_key_rdata(hsm_ctx_t *ctx, hsm_session_t *session,
01266                   const hsm_key_t *key)
01267 {
01268     CK_RV rv;
01269     CK_BYTE_PTR public_exponent = NULL;
01270     CK_ULONG public_exponent_len = 0;
01271     CK_BYTE_PTR modulus = NULL;
01272     CK_ULONG modulus_len = 0;
01273     unsigned long hKey = 0;
01274     unsigned char *data = NULL;
01275     size_t data_size = 0;
01276 
01277     CK_ATTRIBUTE template[] = {
01278         {CKA_PUBLIC_EXPONENT, NULL, 0},
01279         {CKA_MODULUS, NULL, 0},
01280     };
01281     ldns_rdf *rdf;
01282 
01283     if (!session || !session->module) {
01284         return NULL;
01285     }
01286 
01287     if (session->module->config->use_pubkey) {
01288         hKey = key->public_key;
01289     } else {
01290         hKey = key->private_key;
01291     }
01292 
01293     rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
01294                                       session->session,
01295                                       hKey,
01296                                       template,
01297                                       2);
01298     if (hsm_pkcs11_check_error(ctx, rv, "C_GetAttributeValue")) {
01299         return NULL;
01300     }
01301     public_exponent_len = template[0].ulValueLen;
01302     modulus_len = template[1].ulValueLen;
01303 
01304     public_exponent = template[0].pValue = malloc(public_exponent_len);
01305     if (!public_exponent) {
01306         hsm_ctx_set_error(ctx, -1, "hsm_get_key_rdata()",
01307             "Error allocating memory for public exponent");
01308         return NULL;
01309     }
01310 
01311     modulus = template[1].pValue = malloc(modulus_len);
01312     if (!modulus) {
01313         hsm_ctx_set_error(ctx, -1, "hsm_get_key_rdata()",
01314             "Error allocating memory for modulus");
01315         free(public_exponent);
01316         return NULL;
01317     }
01318 
01319     rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GetAttributeValue(
01320                                       session->session,
01321                                       hKey,
01322                                       template,
01323                                       2);
01324     if (hsm_pkcs11_check_error(ctx, rv, "get attribute value")) {
01325         free(template[0].pValue);
01326         free(template[1].pValue);
01327         return NULL;
01328     }
01329 
01330     data_size = public_exponent_len + modulus_len + 1;
01331     if (public_exponent_len <= 256) {
01332         data = malloc(data_size);
01333         if (!data) {
01334             hsm_ctx_set_error(ctx, -1, "hsm_get_key_rdata()",
01335                 "Error allocating memory for pub key rr data");
01336             free(public_exponent);
01337             free(modulus);
01338             return NULL;
01339         }
01340         data[0] = public_exponent_len;
01341         memcpy(&data[1], public_exponent, public_exponent_len);
01342         memcpy(&data[1 + public_exponent_len], modulus, modulus_len);
01343     } else if (public_exponent_len <= 65535) {
01344         data_size += 2;
01345         data = malloc(data_size);
01346         if (!data) {
01347             hsm_ctx_set_error(ctx, -1, "hsm_get_key_rdata()",
01348                 "Error allocating memory for pub key rr data");
01349             free(public_exponent);
01350             free(modulus);
01351             return NULL;
01352         }
01353         data[0] = 0;
01354         ldns_write_uint16(&data[1], (uint16_t) public_exponent_len);
01355         memcpy(&data[3], public_exponent, public_exponent_len);
01356         memcpy(&data[3 + public_exponent_len], modulus, modulus_len);
01357     } else {
01358         hsm_ctx_set_error(ctx, -1, "hsm_get_key_rdata()",
01359             "Public exponent too big");
01360         free(public_exponent);
01361         free(modulus);
01362         return NULL;
01363     }
01364     rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, data_size, data);
01365     free(public_exponent);
01366     free(modulus);
01367 
01368     return rdf;
01369 }
01370 
01371 /* this function allocates memory for the mechanism ID and enough room
01372  * to leave the upcoming digest data. It fills in the mechanism id
01373  * use with care. The returned data must be free'd by the caller */
01374 static CK_BYTE *
01375 hsm_create_prefix(CK_ULONG digest_len,
01376                   ldns_algorithm algorithm,
01377                   CK_ULONG *data_size)
01378 {
01379     CK_BYTE *data;
01380     const CK_BYTE RSA_MD5_ID[] = { 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 };
01381     const CK_BYTE RSA_SHA1_ID[] = { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14 };
01382     const CK_BYTE RSA_SHA256_ID[] = { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 };
01383     const CK_BYTE RSA_SHA512_ID[] = { 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40 };
01384 
01385     switch(algorithm) {
01386         case LDNS_SIGN_RSAMD5:
01387             *data_size = sizeof(RSA_MD5_ID) + digest_len;
01388             data = malloc(*data_size);
01389             memcpy(data, RSA_MD5_ID, sizeof(RSA_MD5_ID));
01390             break;
01391         case LDNS_SIGN_RSASHA1:
01392         case LDNS_SIGN_RSASHA1_NSEC3:
01393             *data_size = sizeof(RSA_SHA1_ID) + digest_len;
01394             data = malloc(*data_size);
01395             memcpy(data, RSA_SHA1_ID, sizeof(RSA_SHA1_ID));
01396             break;
01397         case LDNS_SIGN_RSASHA256:
01398             *data_size = sizeof(RSA_SHA256_ID) + digest_len;
01399             data = malloc(*data_size);
01400             memcpy(data, RSA_SHA256_ID, sizeof(RSA_SHA256_ID));
01401             break;
01402         case LDNS_SIGN_RSASHA512:
01403             *data_size = sizeof(RSA_SHA512_ID) + digest_len;
01404             data = malloc(*data_size);
01405             memcpy(data, RSA_SHA512_ID, sizeof(RSA_SHA512_ID));
01406             break;
01407         default:
01408             return NULL;
01409     }
01410     return data;
01411 }
01412 
01413 static CK_BYTE *
01414 hsm_digest_through_hsm(hsm_ctx_t *ctx,
01415                        hsm_session_t *session,
01416                        CK_MECHANISM_TYPE mechanism_type,
01417                        CK_ULONG digest_len,
01418                        ldns_buffer *sign_buf)
01419 {
01420     CK_MECHANISM digest_mechanism;
01421     CK_BYTE *digest;
01422     CK_RV rv;
01423 
01424     digest_mechanism.pParameter = NULL;
01425     digest_mechanism.ulParameterLen = 0;
01426     digest_mechanism.mechanism = mechanism_type;
01427     digest = malloc(digest_len);
01428     rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_DigestInit(session->session,
01429                                                  &digest_mechanism);
01430     if (hsm_pkcs11_check_error(ctx, rv, "HSM digest init")) {
01431         free(digest);
01432         return NULL;
01433     }
01434 
01435     rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_Digest(session->session,
01436                                         ldns_buffer_begin(sign_buf),
01437                                         ldns_buffer_position(sign_buf),
01438                                         digest,
01439                                         &digest_len);
01440     if (hsm_pkcs11_check_error(ctx, rv, "HSM digest")) {
01441         free(digest);
01442         return NULL;
01443     }
01444     return digest;
01445 }
01446 
01447 static ldns_rdf *
01448 hsm_sign_buffer(hsm_ctx_t *ctx,
01449                 ldns_buffer *sign_buf,
01450                 const hsm_key_t *key,
01451                 ldns_algorithm algorithm)
01452 {
01453     CK_RV rv;
01454     /* TODO: depends on type and key, or just leave it at current
01455      * maximum? */
01456     CK_ULONG signatureLen = 512;
01457     CK_BYTE *signature = NULL;
01458     CK_MECHANISM sign_mechanism;
01459 
01460     ldns_rdf *sig_rdf;
01461     CK_BYTE *digest = NULL;
01462     CK_ULONG digest_len;
01463 
01464     CK_BYTE *data = NULL;
01465     CK_ULONG data_len = 0;
01466 
01467     hsm_session_t *session;
01468 
01469     session = hsm_find_key_session(ctx, key);
01470     if (!session) return NULL;
01471 
01472     signature = malloc(signatureLen);
01473     if (signature == NULL) {
01474         return NULL;
01475     }
01476 
01477     /* some HSMs don't really handle CKM_SHA1_RSA_PKCS well, so
01478      * we'll do the hashing manually */
01479     /* When adding algorithms, remember there is another switch below */
01480     switch (algorithm) {
01481         case LDNS_SIGN_RSAMD5:
01482             digest_len = 16;
01483             digest = hsm_digest_through_hsm(ctx, session,
01484                                             CKM_MD5, digest_len,
01485                                             sign_buf);
01486             break;
01487 
01488         case LDNS_SIGN_RSASHA1:
01489         case LDNS_SIGN_RSASHA1_NSEC3:
01490             digest_len = LDNS_SHA1_DIGEST_LENGTH;
01491             digest = malloc(digest_len);
01492             digest = ldns_sha1(ldns_buffer_begin(sign_buf),
01493                                ldns_buffer_position(sign_buf),
01494                                digest);
01495             break;
01496 
01497         case LDNS_SIGN_RSASHA256:
01498             digest_len = LDNS_SHA256_DIGEST_LENGTH;
01499             digest = malloc(digest_len);
01500             digest = ldns_sha256(ldns_buffer_begin(sign_buf),
01501                                  ldns_buffer_position(sign_buf),
01502                                  digest);
01503             break;
01504 
01505         case LDNS_SIGN_RSASHA512:
01506             digest_len = LDNS_SHA512_DIGEST_LENGTH;
01507             digest = malloc(digest_len);
01508             digest = ldns_sha512(ldns_buffer_begin(sign_buf),
01509                                  ldns_buffer_position(sign_buf),
01510                                  digest);
01511             break;
01512 
01513         default:
01514             /* log error? or should we not even get here for
01515              * unsupported algorithms? */
01516             free(signature);
01517             return NULL;
01518     }
01519 
01520     if (!digest) {
01521         free(signature);
01522         return NULL;
01523     }
01524 
01525     /* CKM_RSA_PKCS does the padding, but cannot know the identifier
01526      * prefix, so we need to add that ourselves */
01527     data = hsm_create_prefix(digest_len, algorithm, &data_len);
01528     memcpy(data + data_len - digest_len, digest, digest_len);
01529 
01530     sign_mechanism.pParameter = NULL;
01531     sign_mechanism.ulParameterLen = 0;
01532     switch(algorithm) {
01533         case LDNS_SIGN_RSAMD5:
01534         case LDNS_SIGN_RSASHA1:
01535         case LDNS_SIGN_RSASHA1_NSEC3:
01536         case LDNS_SIGN_RSASHA256:
01537         case LDNS_SIGN_RSASHA512:
01538             sign_mechanism.mechanism = CKM_RSA_PKCS;
01539             break;
01540         default:
01541             /* log error? or should we not even get here for
01542              * unsupported algorithms? */
01543             free(data);
01544             free(digest);
01545             free(signature);
01546             return NULL;
01547     }
01548 
01549     rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_SignInit(
01550                                       session->session,
01551                                       &sign_mechanism,
01552                                       key->private_key);
01553     if (hsm_pkcs11_check_error(ctx, rv, "sign init")) {
01554         free(data);
01555         free(digest);
01556         free(signature);
01557         return NULL;
01558     }
01559 
01560     rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_Sign(session->session, data, data_len,
01561                                       signature,
01562                                       &signatureLen);
01563     if (hsm_pkcs11_check_error(ctx, rv, "sign final")) {
01564         free(data);
01565         free(digest);
01566         free(signature);
01567         return NULL;
01568     }
01569 
01570     sig_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64,
01571                                     signatureLen,
01572                                     signature);
01573 
01574     free(data);
01575     free(digest);
01576     free(signature);
01577 
01578     return sig_rdf;
01579 
01580 }
01581 
01582 static int
01583 hsm_dname_is_wildcard(const ldns_rdf* dname)
01584 {
01585     return ( ldns_dname_label_count(dname) > 0 &&
01586              ldns_rdf_data(dname)[0] == 1 &&
01587              ldns_rdf_data(dname)[1] == '*');
01588 }
01589 
01590 static ldns_rr *
01591 hsm_create_empty_rrsig(const ldns_rr_list *rrset,
01592                        const hsm_sign_params_t *sign_params)
01593 {
01594     ldns_rr *rrsig;
01595     uint32_t orig_ttl;
01596     uint32_t orig_class;
01597     time_t now;
01598     uint8_t label_count;
01599 
01600     label_count = ldns_dname_label_count(
01601                        ldns_rr_owner(ldns_rr_list_rr(rrset, 0)));
01602     /* RFC 4035 section 2.2: dnssec label length and wildcards */
01603     if (hsm_dname_is_wildcard(ldns_rr_owner(ldns_rr_list_rr(rrset, 0)))) {
01604         label_count--;
01605     }
01606 
01607     rrsig = ldns_rr_new_frm_type(LDNS_RR_TYPE_RRSIG);
01608 
01609     /* set the type on the new signature */
01610     orig_ttl = ldns_rr_ttl(ldns_rr_list_rr(rrset, 0));
01611     orig_class = ldns_rr_get_class(ldns_rr_list_rr(rrset, 0));
01612 
01613     ldns_rr_set_class(rrsig, orig_class);
01614     ldns_rr_set_ttl(rrsig, orig_ttl);
01615     ldns_rr_set_owner(rrsig,
01616               ldns_rdf_clone(
01617                    ldns_rr_owner(
01618                     ldns_rr_list_rr(rrset,
01619                             0))));
01620 
01621     /* fill in what we know of the signature */
01622 
01623     /* set the orig_ttl */
01624     (void)ldns_rr_rrsig_set_origttl(
01625            rrsig,
01626            ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32,
01627                      orig_ttl));
01628     /* the signers name */
01629     (void)ldns_rr_rrsig_set_signame(
01630                rrsig,
01631                ldns_rdf_clone(sign_params->owner));
01632     /* label count - get it from the first rr in the rr_list */
01633     (void)ldns_rr_rrsig_set_labels(
01634             rrsig,
01635             ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8,
01636                                  label_count));
01637     /* inception, expiration */
01638     now = time(NULL);
01639     if (sign_params->inception != 0) {
01640         (void)ldns_rr_rrsig_set_inception(
01641                 rrsig,
01642                 ldns_native2rdf_int32(
01643                     LDNS_RDF_TYPE_TIME,
01644                     sign_params->inception));
01645     } else {
01646         (void)ldns_rr_rrsig_set_inception(
01647                 rrsig,
01648                 ldns_native2rdf_int32(LDNS_RDF_TYPE_TIME, now));
01649     }
01650     if (sign_params->expiration != 0) {
01651         (void)ldns_rr_rrsig_set_expiration(
01652                 rrsig,
01653                 ldns_native2rdf_int32(
01654                     LDNS_RDF_TYPE_TIME,
01655                     sign_params->expiration));
01656     } else {
01657         (void)ldns_rr_rrsig_set_expiration(
01658                  rrsig,
01659                 ldns_native2rdf_int32(
01660                     LDNS_RDF_TYPE_TIME,
01661                     now + LDNS_DEFAULT_EXP_TIME));
01662     }
01663 
01664     (void)ldns_rr_rrsig_set_keytag(
01665            rrsig,
01666            ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16,
01667                                  sign_params->keytag));
01668 
01669     (void)ldns_rr_rrsig_set_algorithm(
01670             rrsig,
01671             ldns_native2rdf_int8(
01672                 LDNS_RDF_TYPE_ALG,
01673                 sign_params->algorithm));
01674 
01675     (void)ldns_rr_rrsig_set_typecovered(
01676             rrsig,
01677             ldns_native2rdf_int16(
01678                 LDNS_RDF_TYPE_TYPE,
01679                 ldns_rr_get_type(ldns_rr_list_rr(rrset,
01680                                                  0))));
01681 
01682     return rrsig;
01683 }
01684 
01685 
01686 /*
01687  *  API functions
01688  */
01689 
01690 int
01691 hsm_open(const char *config,
01692          char *(pin_callback)(const char *repository, void *),
01693          void *data)
01694 {
01695     xmlDocPtr doc;
01696     xmlXPathContextPtr xpath_ctx;
01697     xmlXPathObjectPtr xpath_obj;
01698     xmlNode *curNode;
01699     xmlChar *xexpr;
01700 
01701     int i;
01702     char *config_file;
01703     char *repository;
01704     char *token_label;
01705     char *module_path;
01706     char *module_pin;
01707     hsm_config_t module_config;
01708     int result = HSM_OK;
01709     int tries;
01710     int repositories = 0;
01711 
01712     /* create an internal context with an attached session for each
01713      * configured HSM. */
01714     _hsm_ctx = hsm_ctx_new();
01715 
01716     if (config) {
01717         config_file = strdup(config);
01718     } else{
01719         config_file = strdup(HSM_DEFAULT_CONFIG);
01720     }
01721 
01722     /* Load XML document */
01723     doc = xmlParseFile(config_file);
01724     free(config_file);
01725     if (doc == NULL) {
01726         return HSM_CONFIG_FILE_ERROR;
01727     }
01728 
01729     /* Create xpath evaluation context */
01730     xpath_ctx = xmlXPathNewContext(doc);
01731     if(xpath_ctx == NULL) {
01732         xmlFreeDoc(doc);
01733         hsm_ctx_free(_hsm_ctx);
01734         _hsm_ctx = NULL;
01735         return -1;
01736     }
01737 
01738     /* Evaluate xpath expression */
01739     xexpr = (xmlChar *)"//Configuration/RepositoryList/Repository";
01740     xpath_obj = xmlXPathEvalExpression(xexpr, xpath_ctx);
01741     if(xpath_obj == NULL) {
01742         xmlXPathFreeContext(xpath_ctx);
01743         xmlFreeDoc(doc);
01744         hsm_ctx_free(_hsm_ctx);
01745         _hsm_ctx = NULL;
01746         return -1;
01747     }
01748 
01749     if (xpath_obj->nodesetval) {
01750         for (i = 0; i < xpath_obj->nodesetval->nodeNr; i++) {
01751             /*module = hsm_module_new();*/
01752             token_label = NULL;
01753             module_path = NULL;
01754             module_pin = NULL;
01755             hsm_config_default(&module_config);
01756                  
01757             curNode = xpath_obj->nodesetval->nodeTab[i]->xmlChildrenNode;
01758             repository = (char *) xmlGetProp(xpath_obj->nodesetval->nodeTab[i],
01759                                              (const xmlChar *)"name");
01760 
01761             while (curNode) {
01762                 if (xmlStrEqual(curNode->name, (const xmlChar *)"TokenLabel"))
01763                     token_label = (char *) xmlNodeGetContent(curNode);
01764                 if (xmlStrEqual(curNode->name, (const xmlChar *)"Module"))
01765                     module_path = (char *) xmlNodeGetContent(curNode);
01766                 if (xmlStrEqual(curNode->name, (const xmlChar *)"PIN"))
01767                     module_pin = (char *) xmlNodeGetContent(curNode);
01768                 if (xmlStrEqual(curNode->name, (const xmlChar *)"SkipPublicKey"))
01769                     module_config.use_pubkey = 0;                
01770                 curNode = curNode->next;
01771             }
01772 
01773             if (repository && token_label && module_path) {
01774                 if (module_pin) {
01775                     result = hsm_attach(repository,
01776                                         token_label,
01777                                         module_path,
01778                                         module_pin,
01779                                         &module_config);
01780                     free(module_pin);
01781                 } else {
01782                     if (pin_callback) {
01783                         result = HSM_PIN_INCORRECT;
01784                         tries = 0;
01785                         while (result == HSM_PIN_INCORRECT &&
01786                                tries < 3) {
01787                             module_pin = pin_callback(repository,
01788                                                       data);
01789                             result = hsm_attach(repository,
01790                                                 token_label,
01791                                                 module_path,
01792                                                 module_pin,
01793                                                 &module_config);
01794                             memset(module_pin, 0, strlen(module_pin));
01795                             tries++;
01796                         }
01797                     } else {
01798                         /* no pin, no callback, ignore
01799                          * module and token */
01800                         result = HSM_OK;
01801                     }
01802                 }
01803                 free(repository);
01804                 free(token_label);
01805                 free(module_path);
01806 
01807                 if (result != HSM_OK) {
01808                                         break;
01809                                 }
01810 
01811                 repositories++;
01812             }
01813         }
01814     }
01815 
01816     xmlXPathFreeObject(xpath_obj);
01817     xmlXPathFreeContext(xpath_ctx);
01818     xmlFreeDoc(doc);
01819 
01820     if (result == HSM_OK && repositories == 0) {
01821         hsm_ctx_set_error(_hsm_ctx, HSM_NO_REPOSITORIES, "hsm_open()",
01822             "No repositories found");
01823         return HSM_NO_REPOSITORIES;
01824     }
01825 
01826     return result;
01827 }
01828 
01829 char *
01830 hsm_prompt_pin(const char *repository, void *data)
01831 {
01832     char *prompt;
01833     char *r;
01834     (void) data;
01835     prompt = malloc(64);
01836     snprintf(prompt, 64, "Enter PIN for token %s:", repository);
01837 #ifdef HAVE_GETPASSPHRASE
01838     r = getpassphrase("Enter PIN:");
01839 #else
01840     r = getpass("Enter PIN:");
01841 #endif
01842     free(prompt);
01843     return r;
01844 }
01845 
01846 int
01847 hsm_close()
01848 {
01849     hsm_ctx_close(_hsm_ctx, 1);
01850     return 0;
01851 }
01852 
01853 hsm_ctx_t *
01854 hsm_create_context()
01855 {
01856     return hsm_ctx_clone(_hsm_ctx);
01857 }
01858 
01859 void
01860 hsm_destroy_context(hsm_ctx_t *ctx)
01861 {
01862     hsm_ctx_close(ctx, 0);
01863 }
01864 
01868 hsm_sign_params_t *
01869 hsm_sign_params_new()
01870 {
01871     hsm_sign_params_t *params;
01872     params = malloc(sizeof(hsm_sign_params_t));
01873     params->algorithm = LDNS_SIGN_RSASHA1;
01874     params->flags = LDNS_KEY_ZONE_KEY;
01875     params->inception = 0;
01876     params->expiration = 0;
01877     params->keytag = 0;
01878     params->owner = NULL;
01879     return params;
01880 }
01881 
01882 void
01883 hsm_sign_params_free(hsm_sign_params_t *params)
01884 {
01885     if (params) {
01886         if (params->owner) ldns_rdf_deep_free(params->owner);
01887         free(params);
01888     }
01889 }
01890 
01891 hsm_key_t **
01892 hsm_list_keys(hsm_ctx_t *ctx, size_t *count)
01893 {
01894     hsm_key_t **keys = NULL;
01895     size_t key_count = 0;
01896     size_t cur_key_count;
01897     hsm_key_t **session_keys;
01898     unsigned int i, j;
01899 
01900     if (!ctx) {
01901         ctx = _hsm_ctx;
01902     }
01903 
01904     for (i = 0; i < ctx->session_count; i++) {
01905         session_keys = hsm_list_keys_session(ctx, ctx->session[i],
01906                                              &cur_key_count);
01907         keys = realloc(keys,
01908                        (key_count + cur_key_count) * sizeof(hsm_key_t *));
01909         for (j = 0; j < cur_key_count; j++) {
01910             keys[key_count + j] = session_keys[j];
01911         }
01912         key_count += cur_key_count;
01913         free(session_keys);
01914     }
01915     if (count) {
01916         *count = key_count;
01917     }
01918     return keys;
01919 }
01920 
01921 hsm_key_t **
01922 hsm_list_keys_repository(hsm_ctx_t *ctx,
01923                          size_t *count,
01924                          const char *repository)
01925 {
01926     hsm_session_t *session;
01927 
01928     if (!repository) return NULL;
01929     if (!ctx) ctx = _hsm_ctx;
01930 
01931     session = hsm_find_repository_session(ctx, repository);
01932     if (!session) {
01933         *count = 0;
01934         return NULL;
01935     }
01936     return hsm_list_keys_session(ctx, session, count);
01937 }
01938 
01939 size_t
01940 hsm_count_keys(hsm_ctx_t *ctx)
01941 {
01942     size_t count = 0;
01943     unsigned int i;
01944 
01945     if (!ctx) ctx = _hsm_ctx;
01946     for (i = 0; i < ctx->session_count; i++) {
01947         count += hsm_count_keys_session(ctx, ctx->session[i]);
01948     }
01949     return count;
01950 }
01951 
01952 size_t
01953 hsm_count_keys_repository(hsm_ctx_t *ctx,
01954                           const char *repository)
01955 {
01956     hsm_session_t *session;
01957 
01958     if (!repository) return 0;
01959     if (!ctx) ctx = _hsm_ctx;
01960 
01961     session = hsm_find_repository_session(ctx, repository);
01962     if (!session) {
01963         return 0;
01964     }
01965     return hsm_count_keys_session(ctx, session);
01966 }
01967 
01968 hsm_key_t *
01969 hsm_find_key_by_id(hsm_ctx_t *ctx, const char *id)
01970 {
01971     unsigned char *id_bytes;
01972     size_t len;
01973     hsm_key_t *key;
01974 
01975     id_bytes = hsm_hex_parse(id, &len);
01976 
01977     if (!id_bytes) return NULL;
01978 
01979     key = hsm_find_key_by_id_bin(ctx, id_bytes, len);
01980     free(id_bytes);
01981     return key;
01982 }
01983 
01984 hsm_key_t *
01985 hsm_generate_rsa_key(hsm_ctx_t *ctx,
01986                      const char *repository,
01987                      unsigned long keysize)
01988 {
01989     hsm_key_t *new_key;
01990     hsm_session_t *session;
01991     /* ids we create are 16 bytes of data */
01992     unsigned char id[16];
01993     /* that's 33 bytes in string (16*2 + 1 for \0) */
01994     char id_str[33];
01995     CK_RV rv;
01996     CK_OBJECT_HANDLE publicKey, privateKey;
01997     CK_KEY_TYPE keyType = CKK_RSA;
01998     CK_MECHANISM mechanism = {
01999         CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0
02000     };
02001     CK_BYTE publicExponent[] = { 1, 0, 1 };
02002     CK_BBOOL ctrue = CK_TRUE;
02003     CK_BBOOL cfalse = CK_FALSE;
02004     CK_BBOOL ctoken = CK_TRUE;
02005 
02006     if (!ctx) ctx = _hsm_ctx;
02007     session = hsm_find_repository_session(ctx, repository);
02008     if (!session) return NULL;
02009 
02010     /* check whether this key doesn't happen to exist already */
02011     do {
02012         hsm_random_buffer(ctx, id, 16);
02013     } while (hsm_find_key_by_id_bin(ctx, id, 16));
02014     /* the CKA_LABEL will contain a hexadecimal string representation
02015      * of the id */
02016     hsm_hex_unparse(id_str, id, 16);
02017 
02018     if (! session->module->config->use_pubkey) {
02019         ctoken = CK_FALSE;
02020     }
02021 
02022     CK_ATTRIBUTE publicKeyTemplate[] = {
02023         { CKA_LABEL,(CK_UTF8CHAR*) id_str,   strlen(id_str)   },
02024         { CKA_ID,                  id,       16               },
02025         { CKA_KEY_TYPE,            &keyType, sizeof(keyType)  },
02026         { CKA_VERIFY,              &ctrue,   sizeof(ctrue)    },
02027         { CKA_ENCRYPT,             &cfalse,  sizeof(cfalse)   },
02028         { CKA_WRAP,                &cfalse,  sizeof(cfalse)   },
02029         { CKA_TOKEN,               &ctoken,  sizeof(ctoken)   },
02030         { CKA_MODULUS_BITS,        &keysize, sizeof(keysize)  },
02031         { CKA_PUBLIC_EXPONENT, &publicExponent, sizeof(publicExponent)}
02032     };
02033 
02034     CK_ATTRIBUTE privateKeyTemplate[] = {
02035         { CKA_LABEL,(CK_UTF8CHAR *) id_str, strlen (id_str) },
02036         { CKA_ID,          id,       16                     },
02037         { CKA_KEY_TYPE,    &keyType, sizeof(keyType) },
02038         { CKA_SIGN,        &ctrue,   sizeof (ctrue) },
02039         { CKA_DECRYPT,     &cfalse,  sizeof (cfalse) },
02040         { CKA_UNWRAP,      &cfalse,  sizeof (cfalse) },
02041         { CKA_SENSITIVE,   &ctrue,   sizeof (ctrue) },
02042         { CKA_TOKEN,       &ctrue,   sizeof (ctrue)  },
02043         { CKA_PRIVATE,     &ctrue,   sizeof (ctrue)  },
02044         { CKA_EXTRACTABLE, &cfalse,  sizeof (cfalse) }
02045     };
02046 
02047     rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GenerateKeyPair(session->session,
02048                                                  &mechanism,
02049                                                  publicKeyTemplate, 9,
02050                                                  privateKeyTemplate, 10,
02051                                                  &publicKey,
02052                                                  &privateKey);
02053     if (hsm_pkcs11_check_error(ctx, rv, "generate key pair")) {
02054         return NULL;
02055     }
02056 
02057     new_key = hsm_key_new();
02058     new_key->module = session->module;
02059 
02060     if (session->module->config->use_pubkey) {
02061         new_key->public_key = publicKey;        
02062     } else {
02063         new_key->public_key = 0;        
02064     }
02065 
02066     new_key->private_key = privateKey;
02067     return new_key;
02068 }
02069 
02070 int
02071 hsm_remove_key(hsm_ctx_t *ctx, hsm_key_t *key)
02072 {
02073     CK_RV rv;
02074     hsm_session_t *session;
02075     if (!ctx) ctx = _hsm_ctx;
02076     if (!key) return -1;
02077 
02078     session = hsm_find_key_session(ctx, key);
02079     if (!session) return -2;
02080 
02081     rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_DestroyObject(session->session,
02082                                                key->private_key);
02083     if (hsm_pkcs11_check_error(ctx, rv, "Destroy private key")) {
02084         return -3;
02085     }
02086     key->private_key = 0;
02087 
02088     if (session->module->config->use_pubkey) {
02089         rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_DestroyObject(session->session,
02090                                                    key->public_key);
02091         if (hsm_pkcs11_check_error(ctx, rv, "Destroy public key")) {
02092             return -4;
02093         }
02094     }
02095     key->public_key = 0;
02096 
02097     return 0;
02098 }
02099 
02100 void
02101 hsm_key_free(hsm_key_t *key)
02102 {
02103     if (key) {
02104         free(key);
02105     }
02106 }
02107 
02108 void
02109 hsm_key_list_free(hsm_key_t **key_list, size_t count)
02110 {
02111     size_t i;
02112     for (i = 0; i < count; i++) {
02113         hsm_key_free(key_list[i]);
02114     }
02115     free(key_list);
02116 }
02117 
02118 char *
02119 hsm_get_key_id(hsm_ctx_t *ctx, const hsm_key_t *key)
02120 {
02121     unsigned char *id;
02122     char *id_str;
02123     size_t len;
02124     hsm_session_t *session;
02125 
02126     if (!ctx) ctx = _hsm_ctx;
02127     if (!key) return NULL;
02128 
02129     session = hsm_find_key_session(ctx, key);
02130     if (!session) return NULL;
02131 
02132     id = hsm_get_id_for_object(ctx, session, key->private_key, &len);
02133     if (!id) return NULL;
02134 
02135     /* this is plain binary data, we need to convert it to hex */
02136     id_str = malloc(len * 2 + 1);
02137     if (!id_str) return NULL;
02138 
02139     hsm_hex_unparse(id_str, id, len);
02140 
02141     free(id);
02142 
02143     return id_str;
02144 }
02145 
02146 hsm_key_info_t *
02147 hsm_get_key_info(hsm_ctx_t *ctx,
02148                  const hsm_key_t *key)
02149 {
02150     hsm_key_info_t *key_info;
02151     hsm_session_t *session;
02152 
02153     if (!ctx) ctx = _hsm_ctx;
02154     session = hsm_find_key_session(ctx, key);
02155     if (!session) return NULL;
02156 
02157     key_info = malloc(sizeof(hsm_key_info_t));
02158 
02159     key_info->id = hsm_get_key_id(ctx, key);
02160     if (key_info->id == NULL) {
02161         key_info->id = strdup("");
02162     }
02163 
02164     key_info->algorithm = (unsigned long) hsm_get_key_algorithm(ctx,
02165                                                                 session,
02166                                                                 key);
02167     key_info->keysize = (unsigned long) hsm_get_key_size(ctx,
02168                                                          session,
02169                                                          key,
02170                                                          key_info->algorithm);
02171 
02172     switch(key_info->algorithm) {
02173         case CKK_RSA:
02174             key_info->algorithm_name = strdup("RSA");
02175             break;
02176          default:
02177             key_info->algorithm_name = malloc(HSM_MAX_ALGONAME);
02178             snprintf(key_info->algorithm_name, HSM_MAX_ALGONAME,
02179                 "%lu", key_info->algorithm);
02180             break;
02181     }
02182 
02183     return key_info;
02184 }
02185 
02186 void
02187 hsm_key_info_free(hsm_key_info_t *key_info)
02188 {
02189     if (key_info) {
02190         if (key_info->id) {
02191             free(key_info->id);
02192         }
02193         if (key_info->algorithm_name) {
02194             free(key_info->algorithm_name);
02195         }
02196         free(key_info);
02197     }
02198 }
02199 
02200 ldns_rr*
02201 hsm_sign_rrset(hsm_ctx_t *ctx,
02202                const ldns_rr_list* rrset,
02203                const hsm_key_t *key,
02204                const hsm_sign_params_t *sign_params)
02205 {
02206     ldns_rr *signature;
02207     ldns_buffer *sign_buf;
02208     ldns_rdf *b64_rdf;
02209     size_t i;
02210     (void) ctx;
02211 
02212     if (!key) return NULL;
02213     if (!sign_params) return NULL;
02214 
02215     signature = hsm_create_empty_rrsig((ldns_rr_list *)rrset,
02216                                        sign_params);
02217 
02218     /* right now, we have: a key, a semi-sig and an rrset. For
02219      * which we can create the sig and base64 encode that and
02220      * add that to the signature */
02221     sign_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
02222 
02223     if (ldns_rrsig2buffer_wire(sign_buf, signature)
02224         != LDNS_STATUS_OK) {
02225         ldns_buffer_free(sign_buf);
02226         /* ERROR */
02227         return NULL;
02228     }
02229 
02230     /* make it canonical */
02231     for(i = 0; i < ldns_rr_list_rr_count(rrset); i++) {
02232         ldns_rr2canonical(ldns_rr_list_rr(rrset, i));
02233     }
02234 
02235     /* add the rrset in sign_buf */
02236     if (ldns_rr_list2buffer_wire(sign_buf, rrset)
02237         != LDNS_STATUS_OK) {
02238         ldns_buffer_free(sign_buf);
02239         return NULL;
02240     }
02241 
02242     b64_rdf = hsm_sign_buffer(ctx, sign_buf, key, sign_params->algorithm);
02243 
02244     ldns_buffer_free(sign_buf);
02245     if (!b64_rdf) {
02246         /* signing went wrong */
02247         return NULL;
02248     }
02249 
02250     ldns_rr_rrsig_set_sig(signature, b64_rdf);
02251 
02252     return signature;
02253 }
02254 
02255 /* returns a newly allocated (not null-terminated!) string containing
02256  * the message digest of the given source string
02257  * digest length contains the length of the result
02258  * caller must free returned data with free()
02259  * returns NULL (and zero digest length) on error
02260  */
02261 static CK_BYTE *
02262 hsm_digest(hsm_ctx_t *ctx,
02263            hsm_session_t *session,
02264            CK_MECHANISM digest_mechanism,
02265            char *source,
02266            size_t length,
02267            size_t *digest_length)
02268 {
02269     CK_RV rv;
02270     CK_BYTE *digest;
02271     CK_ULONG d = 0;
02272 
02273     rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_DigestInit(session->session,
02274                                                  &digest_mechanism);
02275     if (hsm_pkcs11_check_error(ctx, rv, "digest init")) {
02276         *digest_length = 0;
02277         return NULL;
02278     }
02279 
02280     rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_Digest(session->session,
02281                                         (CK_BYTE *)source,
02282                                         length,
02283                                         NULL,
02284                                         &d);
02285 
02286     if (hsm_pkcs11_check_error(ctx, rv, "digest to determine result size")) {
02287         *digest_length = 0;
02288         return NULL;
02289     }
02290     digest = malloc(d);
02291     rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_Digest(session->session,
02292                                         (CK_BYTE *)source,
02293                                         length,
02294                                         digest,
02295                                         &d);
02296     if (hsm_pkcs11_check_error(ctx, rv, "digest")) {
02297         *digest_length = 0;
02298         free(digest);
02299         return NULL;
02300     }
02301 
02302     *digest_length = d;
02303     return digest;
02304 }
02305 
02306 ldns_rdf *
02307 hsm_nsec3_hash_name(hsm_ctx_t *ctx,
02308                     ldns_rdf *name,
02309                     uint8_t algorithm,
02310                     uint16_t iterations,
02311                     uint8_t salt_length,
02312                     uint8_t *salt)
02313 {
02314     char *orig_owner_str;
02315     size_t hashed_owner_str_len;
02316     ldns_rdf *hashed_owner;
02317     char *hashed_owner_str;
02318     char *hashed_owner_b32;
02319     int hashed_owner_b32_len;
02320     uint32_t cur_it;
02321     char *hash = NULL;
02322     size_t hash_length = 0;
02323     ldns_status status;
02324     CK_MECHANISM mechanism;
02325     unsigned int i;
02326     hsm_session_t *session = NULL;
02327     char *error_name;
02328 
02329     switch(algorithm) {
02330     case 1:
02331         mechanism.mechanism = CKM_SHA_1;
02332         mechanism.pParameter = NULL;
02333         mechanism.ulParameterLen = 0;
02334         break;
02335     default:
02336         printf("unknown algo: %u\n", (unsigned int)algorithm);
02337         return NULL;
02338         break;
02339     }
02340 
02341     /* just use the first available session */
02342     if (!ctx) ctx = _hsm_ctx;
02343     for (i = 0; i < ctx->session_count; i++) {
02344         if (ctx->session[i]) session = ctx->session[i];
02345     }
02346     if (!session) {
02347         return NULL;
02348     }
02349 
02350     /* prepare the owner name according to the draft section bla */
02351     orig_owner_str = ldns_rdf2str(name);
02352 
02353     hashed_owner_str_len = salt_length + ldns_rdf_size(name);
02354     hashed_owner_str = LDNS_XMALLOC(char, hashed_owner_str_len);
02355     memcpy(hashed_owner_str, ldns_rdf_data(name), ldns_rdf_size(name));
02356     memcpy(hashed_owner_str + ldns_rdf_size(name), salt, salt_length);
02357 
02358     for (cur_it = iterations + 1; cur_it > 0; cur_it--) {
02359         if (hash != NULL) free(hash);
02360         hash = (char *) hsm_digest(ctx,
02361                                    session,
02362                                    mechanism,
02363                                    hashed_owner_str,
02364                                    hashed_owner_str_len,
02365                                    &hash_length);
02366 
02367         LDNS_FREE(hashed_owner_str);
02368         hashed_owner_str_len = salt_length + hash_length;
02369         hashed_owner_str = LDNS_XMALLOC(char, hashed_owner_str_len);
02370         if (!hashed_owner_str) {
02371             hsm_ctx_set_error(ctx, -1, "hsm_nsec3_hash_name()",
02372                 "Memory error");
02373             return NULL;
02374         }
02375         memcpy(hashed_owner_str, hash, hash_length);
02376         memcpy(hashed_owner_str + hash_length, salt, salt_length);
02377     }
02378 
02379     LDNS_FREE(hashed_owner_str);
02380     hashed_owner_str = hash;
02381     hashed_owner_str_len = hash_length;
02382     hashed_owner_b32 = LDNS_XMALLOC(char,
02383                               ldns_b32_ntop_calculate_size(
02384                                    hashed_owner_str_len) + 1);
02385     LDNS_FREE(orig_owner_str);
02386     hashed_owner_b32_len =
02387         (size_t) ldns_b32_ntop_extended_hex((uint8_t *) hashed_owner_str,
02388                                      hashed_owner_str_len,
02389                                      hashed_owner_b32,
02390                                      ldns_b32_ntop_calculate_size(
02391                                          hashed_owner_str_len));
02392     if (hashed_owner_b32_len < 1) {
02393         error_name = ldns_rdf2str(name);
02394         hsm_ctx_set_error(ctx, -1, "hsm_nsec3_hash_name()",
02395              "Error in base32 extended hex encoding "
02396              "of hashed owner name (name: %s, return code: %d)",
02397              error_name, hashed_owner_b32_len);
02398         LDNS_FREE(error_name);
02399         LDNS_FREE(hashed_owner_b32);
02400         return NULL;
02401     }
02402     hashed_owner_str_len = hashed_owner_b32_len;
02403     hashed_owner_b32[hashed_owner_b32_len] = '\0';
02404 
02405     status = ldns_str2rdf_dname(&hashed_owner, hashed_owner_b32);
02406     if (status != LDNS_STATUS_OK) {
02407         hsm_ctx_set_error(ctx, -1, "hsm_nsec3_hash_name()",
02408             "Error creating rdf from %s", hashed_owner_b32);
02409         LDNS_FREE(hashed_owner_b32);
02410         return NULL;
02411     }
02412 
02413     free(hash);
02414     LDNS_FREE(hashed_owner_b32);
02415     return hashed_owner;
02416 }
02417 
02418 ldns_rr *
02419 hsm_get_dnskey(hsm_ctx_t *ctx,
02420                const hsm_key_t *key,
02421                const hsm_sign_params_t *sign_params)
02422 {
02423     /* CK_RV rv; */
02424     ldns_rr *dnskey;
02425     hsm_session_t *session;
02426     ldns_rdf *rdata;
02427 
02428     if (!ctx) ctx = _hsm_ctx;
02429     if (!key) {
02430         hsm_ctx_set_error(ctx, -1, "hsm_get_dnskey()", "Got NULL key");
02431         return NULL;
02432     }
02433     if (!sign_params) {
02434         hsm_ctx_set_error(ctx, -1, "hsm_get_dnskey()", "Got NULL sign_params");
02435         return NULL;
02436     }
02437     session = hsm_find_key_session(ctx, key);
02438     if (!session) return NULL;
02439 
02440     dnskey = ldns_rr_new();
02441     ldns_rr_set_type(dnskey, LDNS_RR_TYPE_DNSKEY);
02442 
02443     ldns_rr_set_owner(dnskey, ldns_rdf_clone(sign_params->owner));
02444 
02445     ldns_rr_push_rdf(dnskey,
02446             ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16,
02447                 sign_params->flags));
02448     ldns_rr_push_rdf(dnskey,
02449                      ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8,
02450                                           LDNS_DNSSEC_KEYPROTO));
02451     ldns_rr_push_rdf(dnskey,
02452                      ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG,
02453                                           sign_params->algorithm));
02454 
02455     rdata = hsm_get_key_rdata(ctx, session, key);
02456     if (rdata == NULL) {
02457         return NULL;
02458     }
02459     ldns_rr_push_rdf(dnskey, rdata);
02460 
02461     return dnskey;
02462 }
02463 
02464 int
02465 hsm_random_buffer(hsm_ctx_t *ctx,
02466                   unsigned char *buffer,
02467                   unsigned long length)
02468 {
02469     CK_RV rv;
02470     unsigned int i;
02471     hsm_session_t *session;
02472     if (!buffer) return -1;
02473     if (!ctx) ctx = _hsm_ctx;
02474 
02475     /* just try every attached token. If one errors (be it NO_RNG, or
02476      * any other error, simply try the next */
02477     for (i = 0; i < ctx->session_count; i++) {
02478         session = ctx->session[i];
02479         if (session) {
02480             rv = ((CK_FUNCTION_LIST_PTR)session->module->sym)->C_GenerateRandom(
02481                                          session->session,
02482                                          buffer,
02483                                          length);
02484             if (rv == CKR_OK) {
02485                 return 0;
02486             }
02487         }
02488     }
02489     return 1;
02490 }
02491 
02492 uint32_t
02493 hsm_random32(hsm_ctx_t *ctx)
02494 {
02495     uint32_t rnd;
02496     int result;
02497     unsigned char rnd_buf[4];
02498     result = hsm_random_buffer(ctx, rnd_buf, 4);
02499     if (result == 0) {
02500         memcpy(&rnd, rnd_buf, 4);
02501         return rnd;
02502     } else {
02503         return 0;
02504     }
02505 }
02506 
02507 uint64_t
02508 hsm_random64(hsm_ctx_t *ctx)
02509 {
02510     uint64_t rnd;
02511     int result;
02512     unsigned char rnd_buf[8];
02513     result = hsm_random_buffer(ctx, rnd_buf, 8);
02514     if (result == 0) {
02515         memcpy(&rnd, rnd_buf, 8);
02516         return rnd;
02517     } else {
02518         return 0;
02519     }
02520 }
02521 
02522 
02523 /*
02524  * Additional functions
02525  */
02526 
02527 int hsm_attach(const char *repository,
02528                const char *token_label,
02529                const char *path,
02530                const char *pin,
02531                const hsm_config_t *config)
02532 {
02533     hsm_session_t *session;
02534     int result;
02535 
02536     result = hsm_session_init(_hsm_ctx,
02537                               &session,
02538                               repository,
02539                               token_label,
02540                               path,
02541                               pin,
02542                               config);
02543     if (result == HSM_OK) {
02544         return hsm_ctx_add_session(_hsm_ctx, session);
02545     } else {
02546         return result;
02547     }
02548 }
02549 
02551 int hsm_detach(const char *repository)
02552 {
02553     unsigned int i;
02554     for (i = 0; i < _hsm_ctx->session_count; i++) {
02555         if (_hsm_ctx->session[i] &&
02556             strcmp(_hsm_ctx->session[i]->module->name,
02557                    repository) == 0) {
02558             hsm_session_close(_hsm_ctx, _hsm_ctx->session[i], 1);
02559             _hsm_ctx->session[i] = NULL;
02560             /* if this was the last session in the list, decrease the
02561              * session count */
02562             if (i == _hsm_ctx->session_count) {
02563                 while(_hsm_ctx->session_count > 0 &&
02564                       !_hsm_ctx->session[i]) {
02565                     _hsm_ctx->session_count--;
02566                 }
02567             }
02568             return 0;
02569         }
02570     }
02571     return -1;
02572 }
02573 
02574 int
02575 hsm_token_attached(hsm_ctx_t *ctx, const char *repository)
02576 {
02577     unsigned int i;
02578     if (!ctx) ctx = _hsm_ctx;
02579     for (i = 0; i < ctx->session_count; i++) {
02580         if (ctx->session[i] &&
02581             strcmp(ctx->session[i]->module->name, repository) == 0) {
02582                 return 1;
02583         }
02584     }
02585 
02586     hsm_ctx_set_error(ctx, HSM_REPOSITORY_NOT_FOUND,
02587                     "hsm_token_attached()",
02588                     "Can't find repository: %s", repository);
02589     return 0;
02590 }
02591 
02592 int
02593 hsm_supported_algorithm(ldns_algorithm algorithm)
02594 {
02595     switch(algorithm) {
02596         case LDNS_SIGN_RSAMD5:
02597         case LDNS_SIGN_RSASHA1:
02598         case LDNS_SIGN_RSASHA1_NSEC3:
02599         case LDNS_SIGN_RSASHA256:
02600         case LDNS_SIGN_RSASHA512:
02601             return 0;
02602             break;
02603         default:
02604             return -1;
02605     }
02606 }
02607 
02608 char *
02609 hsm_get_error(hsm_ctx_t *gctx)
02610 {
02611     hsm_ctx_t *ctx;
02612 
02613     char *message;
02614 
02615     if (!gctx) {
02616         ctx = _hsm_ctx;
02617     } else {
02618         ctx = gctx;
02619     }
02620 
02621     if (ctx->error) {
02622         ctx->error = 0;
02623         message = malloc(HSM_ERROR_MSGSIZE);
02624 
02625         if (message == NULL) {
02626             return strdup("libhsm memory allocation failed");
02627         }
02628 
02629         snprintf(message, HSM_ERROR_MSGSIZE,
02630             "%s: %s",
02631             ctx->error_action ? ctx->error_action : "unknown()",
02632             ctx->error_message ? ctx->error_message : "unknown error");
02633         return message;
02634     };
02635 
02636     return NULL;
02637 }
02638 
02639 void
02640 hsm_print_session(hsm_session_t *session)
02641 {
02642     printf("\t\tmodule at %p (sym %p)\n", (void *) session->module, (void *) session->module->sym);
02643     printf("\t\tmodule path: %s\n", session->module->path);
02644     printf("\t\trepository name: %s\n", session->module->name);
02645     printf("\t\ttoken label: %s\n", session->module->token_label);
02646     printf("\t\tsess handle: %u\n", (unsigned int) session->session);
02647 }
02648 
02649 void
02650 hsm_print_ctx(hsm_ctx_t *gctx) {
02651     hsm_ctx_t *ctx;
02652     unsigned int i;
02653     if (!gctx) {
02654         ctx = _hsm_ctx;
02655     } else {
02656         ctx = gctx;
02657     }
02658     printf("CTX Sessions: %lu\n",
02659            (long unsigned int) ctx->session_count);
02660     for (i = 0; i < ctx->session_count; i++) {
02661         printf("\tSession at %p\n", (void *) ctx->session[i]);
02662         hsm_print_session(ctx->session[i]);
02663     }
02664 }
02665 
02666 void
02667 hsm_print_key(hsm_key_t *key) {
02668     hsm_key_info_t *key_info;
02669     if (key) {
02670         key_info = hsm_get_key_info(NULL, key);
02671         if (key_info) {
02672             printf("key:\n");
02673             printf("\tmodule: %p\n", (void *) key->module);
02674             printf("\tprivkey handle: %u\n", (unsigned int) key->private_key);
02675             if (key->module->config->use_pubkey) {
02676                 printf("\tpubkey handle: %u\n", (unsigned int) key->public_key);
02677             } else {
02678                 printf("\tpubkey handle: %s\n", "NULL");
02679             }
02680             printf("\trepository: %s\n", key->module->name);
02681             printf("\talgorithm: %s\n", key_info->algorithm_name);
02682             printf("\tsize: %lu\n", key_info->keysize);
02683             printf("\tid: %s\n", key_info->id);
02684             hsm_key_info_free(key_info);
02685         } else {
02686             printf("key: hsm_get_key_info() returned NULL\n");
02687         }
02688     } else {
02689         printf("key: <void>\n");
02690     }
02691 }
02692 
02693 void
02694 hsm_print_error(hsm_ctx_t *gctx)
02695 {
02696     char *message;
02697 
02698     message = hsm_get_error(gctx);
02699 
02700     if (message) {
02701         fprintf(stderr, "%s\n", message);
02702         free(message);
02703     } else {
02704         fprintf(stderr, "Unknown error\n");
02705     }
02706 }
02707 
02708 void
02709 hsm_print_tokeninfo(hsm_ctx_t *gctx)
02710 {
02711     CK_RV rv;
02712     CK_SLOT_ID slot_id;
02713     CK_TOKEN_INFO token_info;
02714     hsm_ctx_t *ctx;
02715     unsigned int i;
02716     hsm_session_t *session;
02717     int result;
02718 
02719     if (!gctx) {
02720         ctx = _hsm_ctx;
02721     } else {
02722         ctx = gctx;
02723     }
02724 
02725     for (i = 0; i < ctx->session_count; i++) {
02726         session = ctx->session[i];
02727 
02728         result = hsm_get_slot_id(ctx,
02729                                   session->module->sym,
02730                                   session->module->token_label,
02731                                   &slot_id);
02732         if (result != HSM_OK) return;
02733 
02734         rv = ((CK_FUNCTION_LIST_PTR) session->module->sym)->C_GetTokenInfo(slot_id, &token_info);
02735         if (hsm_pkcs11_check_error(ctx, rv, "C_GetTokenInfo")) {
02736             return;
02737         }
02738 
02739         printf("Repository: %s\n",session->module->name);
02740 
02741         printf("\tModule:        %s\n", session->module->path);
02742         printf("\tSlot:          %lu\n", slot_id);
02743         printf("\tToken Label:   %.*s\n",
02744             (int) sizeof(token_info.label), token_info.label);
02745         printf("\tManufacturer:  %.*s\n",
02746             (int) sizeof(token_info.manufacturerID), token_info.manufacturerID);
02747         printf("\tModel:         %.*s\n",
02748             (int) sizeof(token_info.model), token_info.model);
02749         printf("\tSerial:        %.*s\n",
02750             (int) sizeof(token_info.serialNumber), token_info.serialNumber);
02751 
02752         if (i + 1 != ctx->session_count)
02753             printf("\n");
02754     }
02755 }

Generated on Sat Dec 17 2011 10:07:24 for OpenDNSSEC-libhsm by  doxygen 1.7.1