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
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 #include <config.h>
00111
00112 #include <stdio.h>
00113 #include <stdlib.h>
00114 #include <string.h>
00115
00116 #include <isc/log.h>
00117 #include <isc/mem.h>
00118 #include <isc/once.h>
00119 #include <isc/platform.h>
00120 #include <isc/stdio.h>
00121 #include <isc/thread.h>
00122 #include <isc/util.h>
00123
00124 #include <dst/result.h>
00125
00126 #include <pk11/pk11.h>
00127 #include <pk11/internal.h>
00128 #include <pk11/result.h>
00129
00130 #include <pkcs11/cryptoki.h>
00131 #include <pkcs11/pkcs11.h>
00132
00133
00134 #ifndef PINLEN
00135 #define PINLEN 256
00136 #endif
00137
00138 #ifndef PK11_NO_LOGERR
00139 #define PK11_NO_LOGERR 1
00140 #endif
00141
00142 static isc_once_t once = ISC_ONCE_INIT;
00143 static isc_mem_t *pk11_mctx = NULL;
00144 static isc_int32_t allocsize = 0;
00145 static isc_boolean_t initialized = ISC_FALSE;
00146
00147 typedef struct pk11_session pk11_session_t;
00148 typedef struct pk11_token pk11_token_t;
00149 typedef ISC_LIST(pk11_session_t) pk11_sessionlist_t;
00150
00151 struct pk11_session {
00152 unsigned int magic;
00153 CK_SESSION_HANDLE session;
00154 ISC_LINK(pk11_session_t) link;
00155 pk11_token_t *token;
00156 };
00157
00158 struct pk11_token {
00159 unsigned int magic;
00160 unsigned int operations;
00161 ISC_LINK(pk11_token_t) link;
00162 CK_SLOT_ID slotid;
00163 pk11_sessionlist_t sessions;
00164 isc_boolean_t logged;
00165 char name[32];
00166 char manuf[32];
00167 char model[16];
00168 char serial[16];
00169 char pin[PINLEN + 1];
00170 };
00171 static ISC_LIST(pk11_token_t) tokens;
00172
00173 static pk11_token_t *rand_token;
00174 static pk11_token_t *best_rsa_token;
00175 static pk11_token_t *best_dsa_token;
00176 static pk11_token_t *best_dh_token;
00177 static pk11_token_t *digest_token;
00178 static pk11_token_t *best_ec_token;
00179 static pk11_token_t *best_gost_token;
00180 static pk11_token_t *aes_token;
00181
00182 static isc_result_t free_all_sessions(void);
00183 static isc_result_t free_session_list(pk11_sessionlist_t *slist);
00184 static isc_result_t setup_session(pk11_session_t *sp,
00185 pk11_token_t *token,
00186 isc_boolean_t rw);
00187 static void choose_slots(void);
00188 static isc_result_t token_login(pk11_session_t *sp);
00189 static char *percent_decode(char *x, size_t *len);
00190 static isc_boolean_t pk11strcmp(const char *x, size_t lenx,
00191 const char *y, size_t leny);
00192 static CK_ATTRIBUTE *push_attribute(pk11_object_t *obj,
00193 isc_mem_t *mctx,
00194 size_t len);
00195
00196 static isc_mutex_t alloclock;
00197 static isc_mutex_t sessionlock;
00198
00199 static pk11_sessionlist_t actives;
00200
00201 static CK_C_INITIALIZE_ARGS pk11_init_args = {
00202 NULL_PTR,
00203 NULL_PTR,
00204 NULL_PTR,
00205 NULL_PTR,
00206 CKF_OS_LOCKING_OK,
00207 NULL_PTR,
00208 };
00209
00210 #ifndef PK11_LIB_LOCATION
00211 #define PK11_LIB_LOCATION "unknown_provider"
00212 #endif
00213
00214 #ifndef WIN32
00215 static const char *lib_name = PK11_LIB_LOCATION;
00216 #else
00217 static const char *lib_name = PK11_LIB_LOCATION ".dll";
00218 #endif
00219
00220 void
00221 pk11_set_lib_name(const char *name) {
00222 lib_name = name;
00223 }
00224
00225 const char *
00226 pk11_get_lib_name(void) {
00227 return (lib_name);
00228 }
00229
00230 static void
00231 initialize(void) {
00232 char *pk11_provider;
00233
00234 RUNTIME_CHECK(isc_mutex_init(&alloclock) == ISC_R_SUCCESS);
00235 RUNTIME_CHECK(isc_mutex_init(&sessionlock) == ISC_R_SUCCESS);
00236
00237 pk11_provider = getenv("PKCS11_PROVIDER");
00238 if (pk11_provider != NULL)
00239 lib_name = pk11_provider;
00240 }
00241
00242 void *
00243 pk11_mem_get(size_t size) {
00244 void *ptr;
00245
00246 LOCK(&alloclock);
00247 if (pk11_mctx != NULL)
00248 ptr = isc_mem_get(pk11_mctx, size);
00249 else {
00250 ptr = malloc(size);
00251 if (ptr != NULL)
00252 allocsize += (int)size;
00253 }
00254 UNLOCK(&alloclock);
00255
00256 if (ptr != NULL)
00257 memset(ptr, 0, size);
00258 return (ptr);
00259 }
00260
00261 void
00262 pk11_mem_put(void *ptr, size_t size) {
00263 if (ptr != NULL)
00264 memset(ptr, 0, size);
00265 LOCK(&alloclock);
00266 if (pk11_mctx != NULL)
00267 isc_mem_put(pk11_mctx, ptr, size);
00268 else {
00269 if (ptr != NULL)
00270 allocsize -= (int)size;
00271 free(ptr);
00272 }
00273 UNLOCK(&alloclock);
00274 }
00275
00276 isc_result_t
00277 pk11_initialize(isc_mem_t *mctx, const char *engine) {
00278 isc_result_t result;
00279 CK_RV rv;
00280
00281 RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
00282
00283 LOCK(&alloclock);
00284 if ((mctx != NULL) && (pk11_mctx == NULL) && (allocsize == 0))
00285 isc_mem_attach(mctx, &pk11_mctx);
00286 if (initialized) {
00287 UNLOCK(&alloclock);
00288 return (ISC_R_SUCCESS);
00289 } else {
00290 LOCK(&sessionlock);
00291 initialized = ISC_TRUE;
00292 UNLOCK(&alloclock);
00293 }
00294
00295 ISC_LIST_INIT(tokens);
00296 ISC_LIST_INIT(actives);
00297
00298 if (engine != NULL)
00299 lib_name = engine;
00300
00301
00302 rv = pkcs_C_Initialize((CK_VOID_PTR) &pk11_init_args);
00303
00304 if (rv == 0xfe) {
00305 result = PK11_R_NOPROVIDER;
00306 goto unlock;
00307 }
00308 if (rv != CKR_OK) {
00309 result = PK11_R_INITFAILED;
00310 goto unlock;
00311 }
00312
00313 choose_slots();
00314 #ifdef PKCS11CRYPTO
00315 if (rand_token == NULL) {
00316 result = PK11_R_NORANDOMSERVICE;
00317 goto unlock;
00318 }
00319 if (digest_token == NULL) {
00320 result = PK11_R_NODIGESTSERVICE;
00321 goto unlock;
00322 }
00323 #if defined(ISC_PLATFORM_USESIT) && defined(AES_SIT)
00324 if (aes_token == NULL) {
00325 result = PK11_R_NOAESSERVICE;
00326 goto unlock;
00327 }
00328 #endif
00329 #endif
00330 result = ISC_R_SUCCESS;
00331 unlock:
00332 UNLOCK(&sessionlock);
00333 return (result);
00334 }
00335
00336 isc_result_t
00337 pk11_finalize(void) {
00338 pk11_token_t *token, *next;
00339 isc_result_t ret;
00340
00341 ret = free_all_sessions();
00342 (void) pkcs_C_Finalize(NULL_PTR);
00343 token = ISC_LIST_HEAD(tokens);
00344 while (token != NULL) {
00345 next = ISC_LIST_NEXT(token, link);
00346 ISC_LIST_UNLINK(tokens, token, link);
00347 if (token == rand_token)
00348 rand_token = NULL;
00349 if (token == best_rsa_token)
00350 best_rsa_token = NULL;
00351 if (token == best_dsa_token)
00352 best_dsa_token = NULL;
00353 if (token == best_dh_token)
00354 best_dh_token = NULL;
00355 if (token == digest_token)
00356 digest_token = NULL;
00357 if (token == best_ec_token)
00358 best_ec_token = NULL;
00359 if (token == best_gost_token)
00360 best_gost_token = NULL;
00361 if (token == aes_token)
00362 aes_token = NULL;
00363 pk11_mem_put(token, sizeof(*token));
00364 token = next;
00365 }
00366 if (pk11_mctx != NULL)
00367 isc_mem_detach(&pk11_mctx);
00368 initialized = ISC_FALSE;
00369 return (ret);
00370 }
00371
00372 isc_result_t
00373 pk11_rand_bytes(unsigned char *buf, int num) {
00374 isc_result_t ret;
00375 CK_RV rv;
00376 pk11_context_t ctx;
00377
00378 ret = pk11_get_session(&ctx, OP_RAND, ISC_FALSE, ISC_FALSE,
00379 ISC_FALSE, NULL, 0);
00380 if ((ret != ISC_R_SUCCESS) &&
00381 (ret != PK11_R_NODIGESTSERVICE) &&
00382 (ret != PK11_R_NOAESSERVICE))
00383 return (ret);
00384 RUNTIME_CHECK(ctx.session != CK_INVALID_HANDLE);
00385 rv = pkcs_C_GenerateRandom(ctx.session,
00386 (CK_BYTE_PTR) buf, (CK_ULONG) num);
00387 pk11_return_session(&ctx);
00388 if (rv == CKR_OK)
00389 return (ISC_R_SUCCESS);
00390 else
00391 return (DST_R_CRYPTOFAILURE);
00392 }
00393
00394 #define SEEDSIZE 1024
00395
00396 static CK_BYTE seed[SEEDSIZE];
00397
00398 void
00399 pk11_rand_seed_fromfile(const char *randomfile) {
00400 pk11_context_t ctx;
00401 FILE *stream = NULL;
00402 size_t cc = 0;
00403 isc_result_t ret;
00404
00405 ret = pk11_get_session(&ctx, OP_RAND, ISC_FALSE, ISC_FALSE,
00406 ISC_FALSE, NULL, 0);
00407 if ((ret != ISC_R_SUCCESS) &&
00408 (ret != PK11_R_NODIGESTSERVICE) &&
00409 (ret != PK11_R_NOAESSERVICE))
00410 return;
00411 RUNTIME_CHECK(ctx.session != CK_INVALID_HANDLE);
00412 ret = isc_stdio_open(randomfile, "r", &stream);
00413 if (ret != ISC_R_SUCCESS)
00414 goto cleanup;
00415 ret = isc_stdio_read(seed, 1, SEEDSIZE, stream, &cc);
00416 if (ret!= ISC_R_SUCCESS)
00417 goto cleanup;
00418 ret = isc_stdio_close(stream);
00419 stream = NULL;
00420 if (ret!= ISC_R_SUCCESS)
00421 goto cleanup;
00422 (void) pkcs_C_SeedRandom(ctx.session, seed, (CK_ULONG) cc);
00423
00424 cleanup:
00425 if (stream != NULL)
00426 (void) isc_stdio_close(stream);
00427 pk11_return_session(&ctx);
00428 }
00429
00430 isc_result_t
00431 pk11_get_session(pk11_context_t *ctx, pk11_optype_t optype,
00432 isc_boolean_t need_services, isc_boolean_t rw,
00433 isc_boolean_t logon, const char *pin, CK_SLOT_ID slot)
00434 {
00435 pk11_token_t *token = NULL;
00436 pk11_sessionlist_t *freelist;
00437 pk11_session_t *sp;
00438 isc_result_t ret;
00439 #ifdef PKCS11CRYPTO
00440 isc_result_t service_ret = ISC_R_SUCCESS;
00441 #else
00442 UNUSED(need_services);
00443 #endif
00444
00445 memset(ctx, 0, sizeof(pk11_context_t));
00446 ctx->handle = NULL;
00447 ctx->session = CK_INVALID_HANDLE;
00448
00449 ret = pk11_initialize(NULL, NULL);
00450 #ifdef PKCS11CRYPTO
00451 if (ret == PK11_R_NORANDOMSERVICE ||
00452 ret == PK11_R_NODIGESTSERVICE ||
00453 ret == PK11_R_NOAESSERVICE) {
00454 if (need_services)
00455 return (ret);
00456 service_ret = ret;
00457 }
00458 else
00459 #endif
00460 if (ret != ISC_R_SUCCESS)
00461 return (ret);
00462
00463 LOCK(&sessionlock);
00464
00465 UNLOCK(&sessionlock);
00466
00467 switch(optype) {
00468 #ifdef PKCS11CRYPTO
00469 case OP_RAND:
00470 token = rand_token;
00471 break;
00472 case OP_DIGEST:
00473 token = digest_token;
00474 break;
00475 case OP_AES:
00476 token = aes_token;
00477 break;
00478 case OP_ANY:
00479 for (token = ISC_LIST_HEAD(tokens);
00480 token != NULL;
00481 token = ISC_LIST_NEXT(token, link))
00482 if (token->slotid == slot)
00483 break;
00484 break;
00485 #endif
00486 default:
00487 for (token = ISC_LIST_HEAD(tokens);
00488 token != NULL;
00489 token = ISC_LIST_NEXT(token, link))
00490 if (token->slotid == slot)
00491 break;
00492 #ifdef PKCS11CRYPTO
00493 if ((token == NULL) ||
00494 ((token->operations & (1 << optype)) == 0))
00495 return (ISC_R_NOTFOUND);
00496 #endif
00497 break;
00498 }
00499 if (token == NULL)
00500 return (ISC_R_NOTFOUND);
00501
00502
00503 if (logon && pin != NULL && *pin != '\0') {
00504 if (strlen(pin) > PINLEN)
00505 return ISC_R_RANGE;
00506 memset(token->pin, 0, PINLEN + 1);
00507 strncpy(token->pin, pin, PINLEN);
00508 }
00509
00510 freelist = &token->sessions;
00511
00512 LOCK(&sessionlock);
00513 sp = ISC_LIST_HEAD(*freelist);
00514 if (sp != NULL) {
00515 ISC_LIST_UNLINK(*freelist, sp, link);
00516 ISC_LIST_APPEND(actives, sp, link);
00517 UNLOCK(&sessionlock);
00518 if (logon)
00519 ret = token_login(sp);
00520 ctx->handle = sp;
00521 ctx->session = sp->session;
00522 return (ret);
00523 }
00524 UNLOCK(&sessionlock);
00525
00526 sp = pk11_mem_get(sizeof(*sp));
00527 if (sp == NULL)
00528 return (ISC_R_NOMEMORY);
00529 sp->magic = SES_MAGIC;
00530 sp->token = token;
00531 sp->session = CK_INVALID_HANDLE;
00532 ISC_LINK_INIT(sp, link);
00533 ret = setup_session(sp, token, rw);
00534 if ((ret == ISC_R_SUCCESS) && logon)
00535 ret = token_login(sp);
00536 LOCK(&sessionlock);
00537 ISC_LIST_APPEND(actives, sp, link);
00538 UNLOCK(&sessionlock);
00539 ctx->handle = sp;
00540 ctx->session = sp->session;
00541 #ifdef PKCS11CRYPTO
00542 if (ret == ISC_R_SUCCESS)
00543 ret = service_ret;
00544 #endif
00545 return (ret);
00546 }
00547
00548 void
00549 pk11_return_session(pk11_context_t *ctx) {
00550 pk11_session_t *sp = (pk11_session_t *) ctx->handle;
00551
00552 if (sp == NULL)
00553 return;
00554 ctx->handle = NULL;
00555 ctx->session = CK_INVALID_HANDLE;
00556
00557 LOCK(&sessionlock);
00558 ISC_LIST_UNLINK(actives, sp, link);
00559 UNLOCK(&sessionlock);
00560 if (sp->session == CK_INVALID_HANDLE) {
00561 pk11_mem_put(sp, sizeof(*sp));
00562 return;
00563 }
00564
00565 LOCK(&sessionlock);
00566 ISC_LIST_APPEND(sp->token->sessions, sp, link);
00567 UNLOCK(&sessionlock);
00568 }
00569
00570 static isc_result_t
00571 free_all_sessions(void) {
00572 pk11_token_t *token;
00573 isc_result_t ret = ISC_R_SUCCESS;
00574 isc_result_t oret;
00575
00576 for (token = ISC_LIST_HEAD(tokens);
00577 token != NULL;
00578 token = ISC_LIST_NEXT(token, link)) {
00579 oret = free_session_list(&token->sessions);
00580 if (oret != ISC_R_SUCCESS)
00581 ret = oret;
00582 }
00583 if (!ISC_LIST_EMPTY(actives)) {
00584 ret = ISC_R_ADDRINUSE;
00585 oret = free_session_list(&actives);
00586 if (oret != ISC_R_SUCCESS)
00587 ret = oret;
00588 }
00589 return (ret);
00590 }
00591
00592 static isc_result_t
00593 free_session_list(pk11_sessionlist_t *slist) {
00594 pk11_session_t *sp;
00595 CK_RV rv;
00596 isc_result_t ret;
00597
00598 ret = ISC_R_SUCCESS;
00599 LOCK(&sessionlock);
00600 while (!ISC_LIST_EMPTY(*slist)) {
00601 sp = ISC_LIST_HEAD(*slist);
00602 UNLOCK(&sessionlock);
00603 if (sp->session != CK_INVALID_HANDLE) {
00604 rv = pkcs_C_CloseSession(sp->session);
00605 if (rv != CKR_OK)
00606 ret = DST_R_CRYPTOFAILURE;
00607 }
00608 LOCK(&sessionlock);
00609 ISC_LIST_UNLINK(*slist, sp, link);
00610 pk11_mem_put(sp, sizeof(*sp));
00611 }
00612 UNLOCK(&sessionlock);
00613
00614 return (ret);
00615 }
00616
00617 static isc_result_t
00618 setup_session(pk11_session_t *sp, pk11_token_t *token,
00619 isc_boolean_t rw)
00620 {
00621 CK_RV rv;
00622 CK_FLAGS flags = CKF_SERIAL_SESSION;
00623
00624 if (rw)
00625 flags += CKF_RW_SESSION;
00626
00627 rv = pkcs_C_OpenSession(token->slotid, flags, NULL_PTR,
00628 NULL_PTR, &sp->session);
00629 if (rv != CKR_OK)
00630 return (DST_R_CRYPTOFAILURE);
00631 return (ISC_R_SUCCESS);
00632 }
00633
00634 static isc_result_t
00635 token_login(pk11_session_t *sp) {
00636 CK_RV rv;
00637 pk11_token_t *token = sp->token;
00638 isc_result_t ret = ISC_R_SUCCESS;
00639
00640 LOCK(&sessionlock);
00641 if (!token->logged) {
00642 rv = pkcs_C_Login(sp->session, CKU_USER,
00643 (CK_UTF8CHAR_PTR) token->pin,
00644 (CK_ULONG) strlen(token->pin));
00645 if (rv != CKR_OK) {
00646 ret = ISC_R_NOPERM;
00647 #if PK11_NO_LOGERR
00648 pk11_error_fatalcheck(__FILE__, __LINE__,
00649 "pkcs_C_Login", rv);
00650 #endif
00651 } else
00652 token->logged = ISC_TRUE;
00653 }
00654 UNLOCK(&sessionlock);
00655 return (ret);
00656 }
00657
00658 static void
00659 choose_slots(void) {
00660 CK_MECHANISM_INFO mechInfo;
00661 CK_TOKEN_INFO tokenInfo;
00662 CK_RV rv;
00663 CK_SLOT_ID slot;
00664 CK_SLOT_ID_PTR slotList;
00665 CK_ULONG slotCount;
00666 pk11_token_t *token;
00667 unsigned int i;
00668
00669 slotCount = 0;
00670 PK11_FATALCHECK(pkcs_C_GetSlotList, (CK_FALSE, NULL_PTR, &slotCount));
00671
00672 if (slotCount == 0)
00673 return;
00674 slotList = pk11_mem_get(sizeof(CK_SLOT_ID_PTR) * slotCount);
00675 RUNTIME_CHECK(slotList != NULL);
00676 PK11_FATALCHECK(pkcs_C_GetSlotList, (CK_FALSE, slotList, &slotCount));
00677
00678 for (i = 0; i < slotCount; i++) {
00679 slot = slotList[i];
00680
00681 rv = pkcs_C_GetTokenInfo(slot, &tokenInfo);
00682 if (rv != CKR_OK)
00683 continue;
00684 token = pk11_mem_get(sizeof(*token));
00685 RUNTIME_CHECK(token != NULL);
00686 token->magic = TOK_MAGIC;
00687 token->slotid = slot;
00688 ISC_LINK_INIT(token, link);
00689 ISC_LIST_INIT(token->sessions);
00690 memmove(token->name, tokenInfo.label, 32);
00691 memmove(token->manuf, tokenInfo.manufacturerID, 32);
00692 memmove(token->model, tokenInfo.model, 16);
00693 memmove(token->serial, tokenInfo.serialNumber, 16);
00694 ISC_LIST_APPEND(tokens, token, link);
00695 if ((tokenInfo.flags & CKF_RNG) == 0)
00696 goto try_rsa;
00697 token->operations |= 1 << OP_RAND;
00698 if (rand_token == NULL)
00699 rand_token = token;
00700
00701 try_rsa:
00702 rv = pkcs_C_GetMechanismInfo(slot, CKM_RSA_PKCS_KEY_PAIR_GEN,
00703 &mechInfo);
00704 if ((rv != CKR_OK) ||
00705 ((mechInfo.flags & CKF_GENERATE_KEY_PAIR) == 0))
00706 goto try_dsa;
00707 rv = pkcs_C_GetMechanismInfo(slot, CKM_MD5_RSA_PKCS,
00708 &mechInfo);
00709 if ((rv != CKR_OK) ||
00710 ((mechInfo.flags & CKF_SIGN) == 0) ||
00711 ((mechInfo.flags & CKF_VERIFY) == 0))
00712 goto try_dsa;
00713 rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA1_RSA_PKCS,
00714 &mechInfo);
00715 if ((rv != CKR_OK) ||
00716 ((mechInfo.flags & CKF_SIGN) == 0) ||
00717 ((mechInfo.flags & CKF_VERIFY) == 0))
00718 goto try_dsa;
00719 rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA256_RSA_PKCS,
00720 &mechInfo);
00721 if ((rv != CKR_OK) ||
00722 ((mechInfo.flags & CKF_SIGN) == 0) ||
00723 ((mechInfo.flags & CKF_VERIFY) == 0))
00724 goto try_dsa;
00725 rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA512_RSA_PKCS,
00726 &mechInfo);
00727 if ((rv != CKR_OK) ||
00728 ((mechInfo.flags & CKF_SIGN) == 0) ||
00729 ((mechInfo.flags & CKF_VERIFY) == 0))
00730 goto try_dsa;
00731 token->operations |= 1 << OP_RSA;
00732 if (best_rsa_token == NULL)
00733 best_rsa_token = token;
00734
00735 try_dsa:
00736 rv = pkcs_C_GetMechanismInfo(slot, CKM_DSA_PARAMETER_GEN,
00737 &mechInfo);
00738 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_GENERATE) == 0))
00739 goto try_dh;
00740 rv = pkcs_C_GetMechanismInfo(slot, CKM_DSA_KEY_PAIR_GEN,
00741 &mechInfo);
00742 if ((rv != CKR_OK) ||
00743 ((mechInfo.flags & CKF_GENERATE_KEY_PAIR) == 0))
00744 goto try_dh;
00745 rv = pkcs_C_GetMechanismInfo(slot, CKM_DSA_SHA1, &mechInfo);
00746 if ((rv != CKR_OK) ||
00747 ((mechInfo.flags & CKF_SIGN) == 0) ||
00748 ((mechInfo.flags & CKF_VERIFY) == 0))
00749 goto try_dh;
00750 token->operations |= 1 << OP_DSA;
00751 if (best_dsa_token == NULL)
00752 best_dsa_token = token;
00753
00754 try_dh:
00755 #ifdef notdef
00756 rv = pkcs_C_GetMechanismInfo(slot, CKM_DH_PKCS_PARAMETER_GEN,
00757 &mechInfo);
00758 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_GENERATE) == 0))
00759 goto try_digest;
00760 #endif
00761 rv = pkcs_C_GetMechanismInfo(slot, CKM_DH_PKCS_KEY_PAIR_GEN,
00762 &mechInfo);
00763 if ((rv != CKR_OK) ||
00764 ((mechInfo.flags & CKF_GENERATE_KEY_PAIR) == 0))
00765 goto try_digest;
00766 rv = pkcs_C_GetMechanismInfo(slot, CKM_DH_PKCS_DERIVE,
00767 &mechInfo);
00768 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DERIVE) == 0))
00769 goto try_digest;
00770 token->operations |= 1 << OP_DH;
00771 if (best_dh_token == NULL)
00772 best_dh_token = token;
00773
00774 try_digest:
00775 rv = pkcs_C_GetMechanismInfo(slot, CKM_MD5, &mechInfo);
00776 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0))
00777 continue;
00778 rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA_1, &mechInfo);
00779 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0))
00780 continue;
00781 rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA224, &mechInfo);
00782 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0))
00783 continue;
00784 rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA256, &mechInfo);
00785 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0))
00786 continue;
00787 rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA384, &mechInfo);
00788 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0))
00789 continue;
00790 rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA512, &mechInfo);
00791 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0))
00792 continue;
00793 #ifdef PKCS11CRYPTOWITHHMAC
00794 rv = pkcs_C_GetMechanismInfo(slot, CKM_MD5_HMAC, &mechInfo);
00795 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0))
00796 continue;
00797 #endif
00798 rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA_1_HMAC, &mechInfo);
00799 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0))
00800 continue;
00801 rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA224_HMAC, &mechInfo);
00802 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0))
00803 continue;
00804 rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA256_HMAC, &mechInfo);
00805 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0))
00806 continue;
00807 rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA384_HMAC, &mechInfo);
00808 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0))
00809 continue;
00810 rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA512_HMAC, &mechInfo);
00811 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0))
00812 continue;
00813 token->operations |= 1 << OP_DIGEST;
00814 if (digest_token == NULL)
00815 digest_token = token;
00816
00817
00818 rv = pkcs_C_GetMechanismInfo(slot, CKM_EC_KEY_PAIR_GEN,
00819 &mechInfo);
00820 if ((rv != CKR_OK) ||
00821 ((mechInfo.flags & CKF_GENERATE_KEY_PAIR) == 0))
00822 goto try_gost;
00823 rv = pkcs_C_GetMechanismInfo(slot, CKM_ECDSA, &mechInfo);
00824 if ((rv != CKR_OK) ||
00825 ((mechInfo.flags & CKF_SIGN) == 0) ||
00826 ((mechInfo.flags & CKF_VERIFY) == 0))
00827 goto try_gost;
00828 token->operations |= 1 << OP_EC;
00829 if (best_ec_token == NULL)
00830 best_ec_token = token;
00831
00832 try_gost:
00833
00834 rv = pkcs_C_GetMechanismInfo(slot, CKM_GOSTR3411, &mechInfo);
00835 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0))
00836 goto try_aes;
00837 rv = pkcs_C_GetMechanismInfo(slot, CKM_GOSTR3410_KEY_PAIR_GEN,
00838 &mechInfo);
00839 if ((rv != CKR_OK) ||
00840 ((mechInfo.flags & CKF_GENERATE_KEY_PAIR) == 0))
00841 goto try_aes;
00842 rv = pkcs_C_GetMechanismInfo(slot,
00843 CKM_GOSTR3410_WITH_GOSTR3411,
00844 &mechInfo);
00845 if ((rv != CKR_OK) ||
00846 ((mechInfo.flags & CKF_SIGN) == 0) ||
00847 ((mechInfo.flags & CKF_VERIFY) == 0))
00848 goto try_aes;
00849 token->operations |= 1 << OP_GOST;
00850 if (best_gost_token == NULL)
00851 best_gost_token = token;
00852
00853 try_aes:
00854 rv = pkcs_C_GetMechanismInfo(slot, CKM_AES_ECB, &mechInfo);
00855 if ((rv != CKR_OK) || ((mechInfo.flags & CKF_ENCRYPT) == 0))
00856 continue;
00857 token->operations |= 1 << OP_AES;
00858 if (aes_token == NULL)
00859 aes_token = token;
00860 }
00861
00862 if (slotList != NULL)
00863 pk11_mem_put(slotList, sizeof(CK_SLOT_ID_PTR) * slotCount);
00864 }
00865
00866 CK_SLOT_ID
00867 pk11_get_best_token(pk11_optype_t optype) {
00868 pk11_token_t *token = NULL;
00869
00870 switch (optype) {
00871 case OP_RAND:
00872 token = rand_token;
00873 break;
00874 case OP_RSA:
00875 token = best_rsa_token;
00876 break;
00877 case OP_DSA:
00878 token = best_dsa_token;
00879 break;
00880 case OP_DH:
00881 token = best_dh_token;
00882 break;
00883 case OP_DIGEST:
00884 token = digest_token;
00885 break;
00886 case OP_EC:
00887 token = best_ec_token;
00888 break;
00889 case OP_GOST:
00890 token = best_gost_token;
00891 break;
00892 case OP_AES:
00893 token = aes_token;
00894 break;
00895 default:
00896 break;
00897 }
00898 if (token == NULL)
00899 return (0);
00900 return (token->slotid);
00901 }
00902
00903 unsigned int
00904 pk11_numbits(CK_BYTE_PTR data, unsigned int bytecnt) {
00905 unsigned int bitcnt, i;
00906 CK_BYTE top;
00907
00908 if (bytecnt == 0)
00909 return (0);
00910 bitcnt = bytecnt * 8;
00911 for (i = 0; i < bytecnt; i++) {
00912 top = data[i];
00913 if (top == 0) {
00914 bitcnt -= 8;
00915 continue;
00916 }
00917 if (top & 0x80)
00918 return (bitcnt);
00919 if (top & 0x40)
00920 return (bitcnt - 1);
00921 if (top & 0x20)
00922 return (bitcnt - 2);
00923 if (top & 0x10)
00924 return (bitcnt - 3);
00925 if (top & 0x08)
00926 return (bitcnt - 4);
00927 if (top & 0x04)
00928 return (bitcnt - 5);
00929 if (top & 0x02)
00930 return (bitcnt - 6);
00931 if (top & 0x01)
00932 return (bitcnt - 7);
00933 break;
00934 }
00935 INSIST(0);
00936 }
00937
00938 CK_ATTRIBUTE *
00939 pk11_attribute_first(const pk11_object_t *obj) {
00940 return (obj->repr);
00941 }
00942
00943 CK_ATTRIBUTE *
00944 pk11_attribute_next(const pk11_object_t *obj, CK_ATTRIBUTE *attr) {
00945 CK_ATTRIBUTE *next;
00946
00947 next = attr + 1;
00948 if ((next - obj->repr) >= obj->attrcnt)
00949 return (NULL);
00950 return (next);
00951 }
00952
00953 CK_ATTRIBUTE *
00954 pk11_attribute_bytype(const pk11_object_t *obj, CK_ATTRIBUTE_TYPE type) {
00955 CK_ATTRIBUTE *attr;
00956
00957 for(attr = pk11_attribute_first(obj);
00958 attr != NULL;
00959 attr = pk11_attribute_next(obj, attr))
00960 if (attr->type == type)
00961 return (attr);
00962 return (NULL);
00963 }
00964
00965 static char *
00966 percent_decode(char *x, size_t *len) {
00967 char *p, *c;
00968 unsigned char v;
00969
00970 INSIST(len != NULL);
00971
00972 for (p = c = x; p[0] != '\0'; p++, c++) {
00973 switch (p[0]) {
00974 case '%':
00975 v = 0;
00976 switch (p[1]) {
00977 case '0':
00978 case '1':
00979 case '2':
00980 case '3':
00981 case '4':
00982 case '5':
00983 case '6':
00984 case '7':
00985 case '8':
00986 case '9':
00987 v = (p[1] - '0') << 4;
00988 break;
00989 case 'A':
00990 case 'B':
00991 case 'C':
00992 case 'D':
00993 case 'E':
00994 case 'F':
00995 v = (p[1] - 'A' + 10) << 4;
00996 break;
00997 case 'a':
00998 case 'b':
00999 case 'c':
01000 case 'd':
01001 case 'e':
01002 case 'f':
01003 v = (p[1] - 'a' + 10) << 4;
01004 break;
01005 default:
01006 return (NULL);
01007 }
01008 switch (p[2]) {
01009 case '0':
01010 case '1':
01011 case '2':
01012 case '3':
01013 case '4':
01014 case '5':
01015 case '6':
01016 case '7':
01017 case '8':
01018 case '9':
01019 v |= (p[2] - '0') & 0x0f;
01020 break;
01021 case 'A':
01022 case 'B':
01023 case 'C':
01024 case 'D':
01025 case 'E':
01026 case 'F':
01027 v = (p[2] - 'A' + 10) & 0x0f;
01028 break;
01029 case 'a':
01030 case 'b':
01031 case 'c':
01032 case 'd':
01033 case 'e':
01034 case 'f':
01035 v = (p[2] - 'a' + 10) & 0x0f;
01036 break;
01037 default:
01038 return (NULL);
01039 }
01040 p += 2;
01041 *c = (char) v;
01042 (*len)++;
01043 break;
01044 default:
01045 *c = *p;
01046 (*len)++;
01047 }
01048 }
01049 return (x);
01050 }
01051
01052 static isc_boolean_t
01053 pk11strcmp(const char *x, size_t lenx, const char *y, size_t leny) {
01054 char buf[32];
01055
01056 INSIST((leny == 32) || (leny == 16));
01057
01058 memset(buf, ' ', 32);
01059 if (lenx > leny)
01060 lenx = leny;
01061 memmove(buf, x, lenx);
01062 return (ISC_TF(memcmp(buf, y, leny) == 0));
01063 }
01064
01065 static CK_ATTRIBUTE *
01066 push_attribute(pk11_object_t *obj, isc_mem_t *mctx, size_t len) {
01067 CK_ATTRIBUTE *old = obj->repr;
01068 CK_ATTRIBUTE *attr;
01069 CK_BYTE cnt = obj->attrcnt;
01070
01071 obj->repr = isc_mem_get(mctx, (cnt + 1) * sizeof(*attr));
01072 if (obj->repr == NULL) {
01073 obj->repr = old;
01074 return (NULL);
01075 }
01076 memset(obj->repr, 0, (cnt + 1) * sizeof(*attr));
01077 memmove(obj->repr, old, cnt * sizeof(*attr));
01078 attr = obj->repr + cnt;
01079 attr->ulValueLen = (CK_ULONG) len;
01080 attr->pValue = isc_mem_get(mctx, len);
01081 if (attr->pValue == NULL) {
01082 memset(obj->repr, 0, (cnt + 1) * sizeof(*attr));
01083 isc_mem_put(mctx, obj->repr, (cnt + 1) * sizeof(*attr));
01084 obj->repr = old;
01085 return (NULL);
01086 }
01087 memset(attr->pValue, 0, len);
01088 if (old != NULL) {
01089 memset(old, 0, cnt * sizeof(*attr));
01090 isc_mem_put(mctx, old, cnt * sizeof(*attr));
01091 }
01092 obj->attrcnt++;
01093 return (attr);
01094 }
01095
01096 #define DST_RET(a) { ret = a; goto err; }
01097
01098 isc_result_t
01099 pk11_parse_uri(pk11_object_t *obj, const char *label,
01100 isc_mem_t *mctx, pk11_optype_t optype)
01101 {
01102 CK_ATTRIBUTE *attr;
01103 pk11_token_t *token = NULL;
01104 char *uri, *p, *a, *na, *v;
01105 size_t len, l;
01106 FILE *stream = NULL;
01107 char pin[PINLEN + 1];
01108 isc_boolean_t gotpin = ISC_FALSE;
01109 isc_result_t ret;
01110
01111
01112 len = strlen(label) + 1;
01113 uri = isc_mem_get(mctx, len);
01114 if (uri == NULL)
01115 return (ISC_R_NOMEMORY);
01116 memmove(uri, label, len);
01117
01118
01119 p = strchr(uri, ':');
01120 if (p == NULL)
01121 DST_RET(PK11_R_NOPROVIDER);
01122 *p++ = '\0';
01123 if (strcmp(uri, "pkcs11") != 0)
01124 DST_RET(PK11_R_NOPROVIDER);
01125
01126
01127 for (na = p; na != NULL;) {
01128 a = na;
01129 p = strchr(a, ';');
01130 if (p == NULL) {
01131
01132 na = NULL;
01133 } else {
01134 *p++ = '\0';
01135 na = p;
01136 }
01137 p = strchr(a, '=');
01138 if (p != NULL) {
01139 *p++ = '\0';
01140 v = p;
01141 } else
01142 v = a;
01143 l = 0;
01144 v = percent_decode(v, &l);
01145 if (v == NULL)
01146 DST_RET(PK11_R_NOPROVIDER);
01147 if ((a == v) || (strcmp(a, "object") == 0)) {
01148
01149 attr = pk11_attribute_bytype(obj, CKA_LABEL);
01150 if (attr != NULL)
01151 DST_RET(PK11_R_NOPROVIDER);
01152 attr = push_attribute(obj, mctx, l);
01153 if (attr == NULL)
01154 DST_RET(ISC_R_NOMEMORY);
01155 attr->type = CKA_LABEL;
01156 memmove(attr->pValue, v, l);
01157 } else if (strcmp(a, "token") == 0) {
01158
01159 if (token == NULL)
01160 for (token = ISC_LIST_HEAD(tokens);
01161 token != NULL;
01162 token = ISC_LIST_NEXT(token, link))
01163 if (pk11strcmp(v, l, token->name, 32))
01164 break;
01165 } else if (strcmp(a, "manufacturer") == 0) {
01166
01167 if (token == NULL)
01168 for (token = ISC_LIST_HEAD(tokens);
01169 token != NULL;
01170 token = ISC_LIST_NEXT(token, link))
01171 if (pk11strcmp(v, l, token->manuf, 32))
01172 break;
01173 } else if (strcmp(a, "serial") == 0) {
01174
01175 if (token == NULL)
01176 for (token = ISC_LIST_HEAD(tokens);
01177 token != NULL;
01178 token = ISC_LIST_NEXT(token, link))
01179 if (pk11strcmp(v, l, token->serial, 16))
01180 break;
01181 } else if (strcmp(a, "model") == 0) {
01182
01183 if (token == NULL)
01184 for (token = ISC_LIST_HEAD(tokens);
01185 token != NULL;
01186 token = ISC_LIST_NEXT(token, link))
01187 if (pk11strcmp(v, l, token->model, 16))
01188 break;
01189 } else if (strcmp(a, "library-manufacturer") == 0) {
01190
01191 } else if (strcmp(a, "library-description") == 0) {
01192
01193 } else if (strcmp(a, "library-version") == 0) {
01194
01195 } else if (strcmp(a, "object-type") == 0) {
01196
01197
01198 if (strcmp(v, "private") != 0)
01199 DST_RET(PK11_R_NOPROVIDER);
01200 } else if (strcmp(a, "id") == 0) {
01201
01202 attr = pk11_attribute_bytype(obj, CKA_ID);
01203 if (attr != NULL)
01204 DST_RET(PK11_R_NOPROVIDER);
01205 attr = push_attribute(obj, mctx, l);
01206 if (attr == NULL)
01207 DST_RET(ISC_R_NOMEMORY);
01208 attr->type = CKA_ID;
01209 memmove(attr->pValue, v, l);
01210 } else if (strcmp(a, "pin-source") == 0) {
01211
01212 ret = isc_stdio_open(v, "r", &stream);
01213 if (ret != ISC_R_SUCCESS)
01214 goto err;
01215 memset(pin, 0, PINLEN + 1);
01216 ret = isc_stdio_read(pin, 1, PINLEN + 1, stream, &l);
01217 if ((ret != ISC_R_SUCCESS) && (ret != ISC_R_EOF))
01218 goto err;
01219 if (l > PINLEN)
01220 DST_RET(ISC_R_RANGE);
01221 ret = isc_stdio_close(stream);
01222 stream = NULL;
01223 if (ret != ISC_R_SUCCESS)
01224 goto err;
01225 gotpin = ISC_TRUE;
01226 } else
01227 DST_RET(PK11_R_NOPROVIDER);
01228 }
01229
01230 if ((pk11_attribute_bytype(obj, CKA_LABEL) == NULL) &&
01231 (pk11_attribute_bytype(obj, CKA_ID) == NULL))
01232 DST_RET(ISC_R_NOTFOUND);
01233
01234 if (token == NULL) {
01235 if (optype == OP_RSA)
01236 token = best_rsa_token;
01237 else if (optype == OP_DSA)
01238 token = best_dsa_token;
01239 else if (optype == OP_DH)
01240 token = best_dh_token;
01241 else if (optype == OP_EC)
01242 token = best_ec_token;
01243 }
01244 if (token == NULL)
01245 DST_RET(ISC_R_NOTFOUND);
01246 obj->slot = token->slotid;
01247 if (gotpin) {
01248 memmove(token->pin, pin, PINLEN + 1);
01249 obj->reqlogon = ISC_TRUE;
01250 }
01251
01252 ret = ISC_R_SUCCESS;
01253
01254 err:
01255 if (stream != NULL)
01256 (void) isc_stdio_close(stream);
01257 isc_mem_put(mctx, uri, len);
01258 return (ret);
01259 }
01260
01261 void
01262 pk11_error_fatalcheck(const char *file, int line,
01263 const char *funcname, CK_RV rv)
01264 {
01265 isc_error_fatal(file, line, "%s: Error = 0x%.8lX\n", funcname, rv);
01266 }
01267
01268 void
01269 pk11_dump_tokens(void)
01270 {
01271 pk11_token_t *token;
01272 isc_boolean_t first;
01273
01274 printf("DEFAULTS\n");
01275 printf("\trand_token=%p\n", rand_token);
01276 printf("\tbest_rsa_token=%p\n", best_rsa_token);
01277 printf("\tbest_dsa_token=%p\n", best_dsa_token);
01278 printf("\tbest_dh_token=%p\n", best_dh_token);
01279 printf("\tdigest_token=%p\n", digest_token);
01280 printf("\tbest_ec_token=%p\n", best_ec_token);
01281 printf("\tbest_gost_token=%p\n", best_gost_token);
01282 printf("\taes_token=%p\n", aes_token);
01283
01284 for (token = ISC_LIST_HEAD(tokens);
01285 token != NULL;
01286 token = ISC_LIST_NEXT(token, link)) {
01287 printf("\nTOKEN\n");
01288 printf("\taddress=%p\n", token);
01289 printf("\tslotID=%lu\n", token->slotid);
01290 printf("\tlabel=%.32s\n", token->name);
01291 printf("\tmanufacturerID=%.32s\n", token->manuf);
01292 printf("\tmodel=%.16s\n", token->model);
01293 printf("\tserialNumber=%.16s\n", token->serial);
01294 printf("\tsupported operations=0x%x (", token->operations);
01295 first = ISC_TRUE;
01296 if (token->operations & (1 << OP_RAND)) {
01297 if (!first)
01298 printf(",");
01299 first = ISC_FALSE;
01300 printf("RAND");
01301 }
01302 if (token->operations & (1 << OP_RSA)) {
01303 if (!first)
01304 printf(",");
01305 first = ISC_FALSE;
01306 printf("RSA");
01307 }
01308 if (token->operations & (1 << OP_DSA)) {
01309 if (!first)
01310 printf(",");
01311 first = ISC_FALSE;
01312 printf("DSA");
01313 }
01314 if (token->operations & (1 << OP_DH)) {
01315 if (!first)
01316 printf(",");
01317 first = ISC_FALSE;
01318 printf("DH");
01319 }
01320 if (token->operations & (1 << OP_DIGEST)) {
01321 if (!first)
01322 printf(",");
01323 first = ISC_FALSE;
01324 printf("DIGEST");
01325 }
01326 if (token->operations & (1 << OP_EC)) {
01327 if (!first)
01328 printf(",");
01329 first = ISC_FALSE;
01330 printf("EC");
01331 }
01332 printf(")\n");
01333 }
01334 }