pk11.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2014  Internet Systems Consortium, Inc. ("ISC")
00003  *
00004  * Permission to use, copy, modify, and/or distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00009  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00010  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00011  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00012  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00013  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00014  * PERFORMANCE OF THIS SOFTWARE.
00015  */
00016 
00017 /*
00018  * Portions copyright (c) 2008 Nominet UK.  All rights reserved.
00019  *
00020  * Redistribution and use in source and binary forms, with or without
00021  * modification, are permitted provided that the following conditions
00022  * are met:
00023  * 1. Redistributions of source code must retain the above copyright
00024  *    notice, this list of conditions and the following disclaimer.
00025  * 2. Redistributions in binary form must reproduce the above copyright
00026  *    notice, this list of conditions and the following disclaimer in the
00027  *    documentation and/or other materials provided with the distribution.
00028  *
00029  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00030  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00031  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00032  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00033  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00034  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00035  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00036  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00037  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00038  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00039  */
00040 
00041 /*
00042  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
00043  * Use is subject to license terms.
00044  */
00045 
00046 /*
00047  * This product includes software developed by the OpenSSL Project for
00048  * use in the OpenSSL Toolkit (http://www.openssl.org/).
00049  *
00050  * This project also referenced hw_pkcs11-0.9.7b.patch written by
00051  * Afchine Madjlessi.
00052  */
00053 /*
00054  * ====================================================================
00055  * Copyright (c) 2000-2001 The OpenSSL Project.  All rights reserved.
00056  *
00057  * Redistribution and use in source and binary forms, with or without
00058  * modification, are permitted provided that the following conditions
00059  * are met:
00060  *
00061  * 1. Redistributions of source code must retain the above copyright
00062  *    notice, this list of conditions and the following disclaimer.
00063  *
00064  * 2. Redistributions in binary form must reproduce the above copyright
00065  *    notice, this list of conditions and the following disclaimer in
00066  *    the documentation and/or other materials provided with the
00067  *    distribution.
00068  *
00069  * 3. All advertising materials mentioning features or use of this
00070  *    software must display the following acknowledgment:
00071  *    "This product includes software developed by the OpenSSL Project
00072  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
00073  *
00074  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
00075  *    endorse or promote products derived from this software without
00076  *    prior written permission. For written permission, please contact
00077  *    licensing@OpenSSL.org.
00078  *
00079  * 5. Products derived from this software may not be called "OpenSSL"
00080  *    nor may "OpenSSL" appear in their names without prior written
00081  *    permission of the OpenSSL Project.
00082  *
00083  * 6. Redistributions of any form whatsoever must retain the following
00084  *    acknowledgment:
00085  *    "This product includes software developed by the OpenSSL Project
00086  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
00087  *
00088  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
00089  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00090  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00091  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
00092  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00093  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00094  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00095  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00096  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
00097  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00098  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
00099  * OF THE POSSIBILITY OF SUCH DAMAGE.
00100  * ====================================================================
00101  *
00102  * This product includes cryptographic software written by Eric Young
00103  * (eay@cryptsoft.com).  This product includes software written by Tim
00104  * Hudson (tjh@cryptsoft.com).
00105  *
00106  */
00107 
00108 /* $Id$ */
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 /* was 32 octets, Petr Spacek suggested 1024, SoftHSMv2 uses 256... */
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,               /* CreateMutex */
00203         NULL_PTR,               /* DestroyMutex */
00204         NULL_PTR,               /* LockMutex */
00205         NULL_PTR,               /* UnlockMutex */
00206         CKF_OS_LOCKING_OK,      /* flags */
00207         NULL_PTR,               /* pReserved */
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         /* Initialize the CRYPTOKI library */
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 /* PKCS11CRYPTO */
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 /* PKCS11CRYPTO */
00460         if (ret != ISC_R_SUCCESS)
00461                 return (ret);
00462 
00463         LOCK(&sessionlock);
00464         /* wait for initialization to finish */
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         /* Override the token's PIN */
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         /* it's not an error if we didn't find any providers */
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                 /* ECDSA requires digest */
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                 /* does GOST require digest too? */
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         /* get values to work on */
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         /* get the URI scheme */
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         /* get attributes */
01127         for (na = p; na != NULL;) {
01128                 a = na;
01129                 p = strchr(a, ';');
01130                 if (p == NULL) {
01131                         /* last attribute */
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                         /* object: CKA_LABEL */
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                         /* token: CK_TOKEN_INFO label */
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                         /* manufacturer: CK_TOKEN_INFO manufacturerID */
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                         /* serial: CK_TOKEN_INFO serialNumber */
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                         /* model: CK_TOKEN_INFO model */
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                         /* ignored */
01191                 } else if (strcmp(a, "library-description") == 0) {
01192                         /* ignored */
01193                 } else if (strcmp(a, "library-version") == 0) {
01194                         /* ignored */
01195                 } else if (strcmp(a, "object-type") == 0) {
01196                         /* object-type: CKA_CLASS */
01197                         /* only private makes sense */
01198                         if (strcmp(v, "private") != 0)
01199                                 DST_RET(PK11_R_NOPROVIDER);
01200                 } else if (strcmp(a, "id") == 0) {
01201                         /* id: CKA_ID */
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                         /* pin-source: PIN */
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 }

Generated on Tue Apr 28 17:41:05 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha