OpenDNSSEC-libhsm 1.3.0rc3
|
00001 /* $Id: libhsm.c 5227 2011-06-12 08:51:24Z jakob $ */ 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 }