00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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
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
00273
00274 #if defined(HAVE_LOADLIBRARY)
00275
00276 HINSTANCE hDLL = LoadLibrary(_T(module->path));
00277
00278 if (hDLL == NULL) {
00279
00280 return CKR_FUNCTION_FAILED;
00281 }
00282
00283
00284 pGetFunctionList = (CK_C_GetFunctionList)
00285 GetProcAddress(hDLL, _T("C_GetFunctionList"));
00286
00287 #elif defined(HAVE_DLOPEN)
00288
00289 void* pDynLib = dlopen(module->path, RTLD_NOW | RTLD_LOCAL);
00290
00291 if (pDynLib == NULL) {
00292
00293 return CKR_FUNCTION_FAILED;
00294 }
00295
00296
00297 pGetFunctionList = (CK_C_GetFunctionList) dlsym(pDynLib, "C_GetFunctionList");
00298
00299 module->handle = pDynLib;
00300
00301 #else
00302 return CKR_FUNCTION_FAILED;
00303 #endif
00304 } else {
00305
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
00315 return CKR_FUNCTION_FAILED;
00316 }
00317
00318
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
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
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;
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
00479
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
00509
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
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
00552
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
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
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
00628
00629
00630
00631
00632
00633
00634 static void
00635 hsm_session_close(hsm_ctx_t *ctx, hsm_session_t *session, int unload)
00636 {
00637
00638
00639
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
00664
00665
00666
00667
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
00677
00678
00679 hsm_session_close(ctx, ctx->session[i], unload);
00680 ctx->session[i] = NULL;
00681
00682
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
00695
00696
00697
00698
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
00724
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
00746
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
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
00781
00782
00783
00784 return 0;
00785 }
00786
00787 if ((CK_LONG)template[0].ulValueLen < 1) {
00788
00789
00790
00791
00792 return 0;
00793 }
00794
00795 return key_type;
00796 }
00797
00798
00799
00800
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
00810 CK_ATTRIBUTE template[] = {
00811 {CKA_MODULUS_BITS, &modulus_bits, sizeof(CK_KEY_TYPE)}
00812 };
00813
00814
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
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
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
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
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
00883
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
00941
00942
00943
00944 static unsigned char *
00945 hsm_hex_parse(const char *hex, size_t *len)
00946 {
00947 unsigned char *bytes;
00948
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
00971
00972
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
00987
00988
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
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
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
01037
01038
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
01073
01074
01075
01076
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
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
01140 keys[i] = key;
01141 }
01142 }
01143 free(key_handles);
01144
01145 *count = total_count;
01146 return keys;
01147 }
01148
01149
01150
01151
01152
01153
01154
01155
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
01165
01166
01167
01168
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
01179
01180
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
01205
01206
01207
01208
01209
01210
01211
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
01372
01373
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
01455
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
01478
01479
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
01515
01516 free(signature);
01517 return NULL;
01518 }
01519
01520 if (!digest) {
01521 free(signature);
01522 return NULL;
01523 }
01524
01525
01526
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
01542
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
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
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
01622
01623
01624 (void)ldns_rr_rrsig_set_origttl(
01625 rrsig,
01626 ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32,
01627 orig_ttl));
01628
01629 (void)ldns_rr_rrsig_set_signame(
01630 rrsig,
01631 ldns_rdf_clone(sign_params->owner));
01632
01633 (void)ldns_rr_rrsig_set_labels(
01634 rrsig,
01635 ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8,
01636 label_count));
01637
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
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
01713
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
01723 doc = xmlParseFile(config_file);
01724 free(config_file);
01725 if (doc == NULL) {
01726 return HSM_CONFIG_FILE_ERROR;
01727 }
01728
01729
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
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
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
01799
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
01992 unsigned char id[16];
01993
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
02011 do {
02012 hsm_random_buffer(ctx, id, 16);
02013 } while (hsm_find_key_by_id_bin(ctx, id, 16));
02014
02015
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
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
02219
02220
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
02227 return NULL;
02228 }
02229
02230
02231 for(i = 0; i < ldns_rr_list_rr_count(rrset); i++) {
02232 ldns_rr2canonical(ldns_rr_list_rr(rrset, i));
02233 }
02234
02235
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
02247 return NULL;
02248 }
02249
02250 ldns_rr_rrsig_set_sig(signature, b64_rdf);
02251
02252 return signature;
02253 }
02254
02255
02256
02257
02258
02259
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
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
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
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
02476
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
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
02561
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 }