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