LCOV - code coverage report
Current view: top level - third_party/heimdal/lib/hx509 - ks_p11.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 2 2 100.0 %
Date: 2024-04-21 15:09:00 Functions: 1 1 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2004 - 2008 Kungliga Tekniska Högskolan
       3             :  * (Royal Institute of Technology, Stockholm, Sweden).
       4             :  * All rights reserved.
       5             :  *
       6             :  * Redistribution and use in source and binary forms, with or without
       7             :  * modification, are permitted provided that the following conditions
       8             :  * are met:
       9             :  *
      10             :  * 1. Redistributions of source code must retain the above copyright
      11             :  *    notice, this list of conditions and the following disclaimer.
      12             :  *
      13             :  * 2. Redistributions in binary form must reproduce the above copyright
      14             :  *    notice, this list of conditions and the following disclaimer in the
      15             :  *    documentation and/or other materials provided with the distribution.
      16             :  *
      17             :  * 3. Neither the name of the Institute nor the names of its contributors
      18             :  *    may be used to endorse or promote products derived from this software
      19             :  *    without specific prior written permission.
      20             :  *
      21             :  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
      22             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      23             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      24             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
      25             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      26             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      27             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      28             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      29             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      30             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      31             :  * SUCH DAMAGE.
      32             :  */
      33             : 
      34             : #include "hx_locl.h"
      35             : 
      36             : #ifdef HAVE_DLOPEN
      37             : 
      38             : #include "ref/pkcs11.h"
      39             : 
      40             : struct p11_slot {
      41             :     uint64_t flags;
      42             : #define P11_SESSION             1
      43             : #define P11_SESSION_IN_USE      2
      44             : #define P11_LOGIN_REQ           4
      45             : #define P11_LOGIN_DONE          8
      46             : #define P11_TOKEN_PRESENT       16
      47             :     CK_SESSION_HANDLE session;
      48             :     CK_SLOT_ID id;
      49             :     CK_BBOOL token;
      50             :     char *name;
      51             :     hx509_certs certs;
      52             :     char *pin;
      53             :     struct {
      54             :         CK_MECHANISM_TYPE_PTR list;
      55             :         CK_ULONG num;
      56             :         CK_MECHANISM_INFO_PTR *infos;
      57             :     } mechs;
      58             : };
      59             : 
      60             : struct p11_module {
      61             :     void *dl_handle;
      62             :     CK_FUNCTION_LIST_PTR funcs;
      63             :     CK_ULONG num_slots;
      64             :     unsigned int ref;
      65             :     unsigned int selected_slot;
      66             :     struct p11_slot *slot;
      67             : };
      68             : 
      69             : #define P11FUNC(module,f,args) (*(module)->funcs->C_##f)args
      70             : 
      71             : static int p11_get_session(hx509_context,
      72             :                            struct p11_module *,
      73             :                            struct p11_slot *,
      74             :                            hx509_lock,
      75             :                            CK_SESSION_HANDLE *);
      76             : static int p11_put_session(struct p11_module *,
      77             :                            struct p11_slot *,
      78             :                            CK_SESSION_HANDLE);
      79             : static void p11_release_module(struct p11_module *);
      80             : 
      81             : static int p11_list_keys(hx509_context,
      82             :                          struct p11_module *,
      83             :                          struct p11_slot *,
      84             :                          CK_SESSION_HANDLE,
      85             :                          hx509_lock,
      86             :                          hx509_certs *);
      87             : 
      88             : /*
      89             :  *
      90             :  */
      91             : 
      92             : struct p11_rsa {
      93             :     struct p11_module *p;
      94             :     struct p11_slot *slot;
      95             :     CK_OBJECT_HANDLE private_key;
      96             :     CK_OBJECT_HANDLE public_key;
      97             : };
      98             : 
      99             : static int
     100             : p11_rsa_public_encrypt(int flen,
     101             :                        const unsigned char *from,
     102             :                        unsigned char *to,
     103             :                        RSA *rsa,
     104             :                        int padding)
     105             : {
     106             :     return -1;
     107             : }
     108             : 
     109             : static int
     110             : p11_rsa_public_decrypt(int flen,
     111             :                        const unsigned char *from,
     112             :                        unsigned char *to,
     113             :                        RSA *rsa,
     114             :                        int padding)
     115             : {
     116             :     return -1;
     117             : }
     118             : 
     119             : 
     120             : static int
     121             : p11_rsa_private_encrypt(int flen,
     122             :                         const unsigned char *from,
     123             :                         unsigned char *to,
     124             :                         RSA *rsa,
     125             :                         int padding)
     126             : {
     127             :     struct p11_rsa *p11rsa = RSA_get_app_data(rsa);
     128             :     CK_OBJECT_HANDLE key = p11rsa->private_key;
     129             :     CK_SESSION_HANDLE session;
     130             :     CK_MECHANISM mechanism;
     131             :     CK_ULONG ck_sigsize;
     132             :     int ret;
     133             : 
     134             :     if (padding != RSA_PKCS1_PADDING)
     135             :         return -1;
     136             : 
     137             :     memset(&mechanism, 0, sizeof(mechanism));
     138             :     mechanism.mechanism = CKM_RSA_PKCS;
     139             : 
     140             :     ck_sigsize = RSA_size(rsa);
     141             : 
     142             :     ret = p11_get_session(NULL, p11rsa->p, p11rsa->slot, NULL, &session);
     143             :     if (ret)
     144             :         return -1;
     145             : 
     146             :     ret = P11FUNC(p11rsa->p, SignInit, (session, &mechanism, key));
     147             :     if (ret != CKR_OK) {
     148             :         p11_put_session(p11rsa->p, p11rsa->slot, session);
     149             :         return -1;
     150             :     }
     151             : 
     152             :     ret = P11FUNC(p11rsa->p, Sign,
     153             :                   (session, (CK_BYTE *)(intptr_t)from, flen, to, &ck_sigsize));
     154             :     p11_put_session(p11rsa->p, p11rsa->slot, session);
     155             :     if (ret != CKR_OK)
     156             :         return -1;
     157             : 
     158             :     return ck_sigsize;
     159             : }
     160             : 
     161             : static int
     162             : p11_rsa_private_decrypt(int flen, const unsigned char *from, unsigned char *to,
     163             :                         RSA * rsa, int padding)
     164             : {
     165             :     struct p11_rsa *p11rsa = RSA_get_app_data(rsa);
     166             :     CK_OBJECT_HANDLE key = p11rsa->private_key;
     167             :     CK_SESSION_HANDLE session;
     168             :     CK_MECHANISM mechanism;
     169             :     CK_ULONG ck_sigsize;
     170             :     int ret;
     171             : 
     172             :     if (padding != RSA_PKCS1_PADDING)
     173             :         return -1;
     174             : 
     175             :     memset(&mechanism, 0, sizeof(mechanism));
     176             :     mechanism.mechanism = CKM_RSA_PKCS;
     177             : 
     178             :     ck_sigsize = RSA_size(rsa);
     179             : 
     180             :     ret = p11_get_session(NULL, p11rsa->p, p11rsa->slot, NULL, &session);
     181             :     if (ret)
     182             :         return -1;
     183             : 
     184             :     ret = P11FUNC(p11rsa->p, DecryptInit, (session, &mechanism, key));
     185             :     if (ret != CKR_OK) {
     186             :         p11_put_session(p11rsa->p, p11rsa->slot, session);
     187             :         return -1;
     188             :     }
     189             : 
     190             :     ret = P11FUNC(p11rsa->p, Decrypt,
     191             :                   (session, (CK_BYTE *)(intptr_t)from, flen, to, &ck_sigsize));
     192             :     p11_put_session(p11rsa->p, p11rsa->slot, session);
     193             :     if (ret != CKR_OK)
     194             :         return -1;
     195             : 
     196             :     return ck_sigsize;
     197             : }
     198             : 
     199             : static int
     200             : p11_rsa_init(RSA *rsa)
     201             : {
     202             :     return 1;
     203             : }
     204             : 
     205             : static int
     206             : p11_rsa_finish(RSA *rsa)
     207             : {
     208             :     struct p11_rsa *p11rsa = RSA_get_app_data(rsa);
     209             :     p11_release_module(p11rsa->p);
     210             :     free(p11rsa);
     211             :     return 1;
     212             : }
     213             : 
     214             : static const RSA_METHOD p11_rsa_pkcs1_method = {
     215             :     "hx509 PKCS11 PKCS#1 RSA",
     216             :     p11_rsa_public_encrypt,
     217             :     p11_rsa_public_decrypt,
     218             :     p11_rsa_private_encrypt,
     219             :     p11_rsa_private_decrypt,
     220             :     NULL,
     221             :     NULL,
     222             :     p11_rsa_init,
     223             :     p11_rsa_finish,
     224             :     0,
     225             :     NULL,
     226             :     NULL,
     227             :     NULL,
     228             :     NULL
     229             : };
     230             : 
     231             : /*
     232             :  *
     233             :  */
     234             : 
     235             : static int
     236             : p11_mech_info(hx509_context context,
     237             :               struct p11_module *p,
     238             :               struct p11_slot *slot,
     239             :               int num)
     240             : {
     241             :     CK_ULONG i;
     242             :     int ret;
     243             : 
     244             :     ret = P11FUNC(p, GetMechanismList, (slot->id, NULL_PTR, &i));
     245             :     if (ret) {
     246             :         hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH,
     247             :                                "Failed to get mech list count for slot %d",
     248             :                                num);
     249             :         return HX509_PKCS11_NO_MECH;
     250             :     }
     251             :     if (i == 0) {
     252             :         hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH,
     253             :                                "no mech supported for slot %d", num);
     254             :         return HX509_PKCS11_NO_MECH;
     255             :     }
     256             :     slot->mechs.list = calloc(i, sizeof(slot->mechs.list[0]));
     257             :     if (slot->mechs.list == NULL) {
     258             :         hx509_set_error_string(context, 0, ENOMEM,
     259             :                                "out of memory");
     260             :         return ENOMEM;
     261             :     }
     262             :     slot->mechs.num = i;
     263             :     ret = P11FUNC(p, GetMechanismList, (slot->id, slot->mechs.list, &i));
     264             :     if (ret) {
     265             :         hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH,
     266             :                                "Failed to get mech list for slot %d",
     267             :                                num);
     268             :         return HX509_PKCS11_NO_MECH;
     269             :     }
     270             :     assert(i == slot->mechs.num);
     271             : 
     272             :     slot->mechs.infos = calloc(i, sizeof(*slot->mechs.infos));
     273             :     if (slot->mechs.list == NULL) {
     274             :         hx509_set_error_string(context, 0, ENOMEM,
     275             :                                "out of memory");
     276             :         return ENOMEM;
     277             :     }
     278             : 
     279             :     for (i = 0; i < slot->mechs.num; i++) {
     280             :         slot->mechs.infos[i] = calloc(1, sizeof(*(slot->mechs.infos[0])));
     281             :         if (slot->mechs.infos[i] == NULL) {
     282             :             hx509_set_error_string(context, 0, ENOMEM,
     283             :                                    "out of memory");
     284             :             return ENOMEM;
     285             :         }
     286             :         ret = P11FUNC(p, GetMechanismInfo, (slot->id, slot->mechs.list[i],
     287             :                                             slot->mechs.infos[i]));
     288             :         if (ret) {
     289             :             hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH,
     290             :                                    "Failed to get mech info for slot %d",
     291             :                                    num);
     292             :             return HX509_PKCS11_NO_MECH;
     293             :         }
     294             :     }
     295             : 
     296             :     return 0;
     297             : }
     298             : 
     299             : static int
     300             : p11_init_slot(hx509_context context,
     301             :               struct p11_module *p,
     302             :               hx509_lock lock,
     303             :               CK_SLOT_ID id,
     304             :               int num,
     305             :               struct p11_slot *slot)
     306             : {
     307             :     CK_SESSION_HANDLE session;
     308             :     CK_SLOT_INFO slot_info;
     309             :     CK_TOKEN_INFO token_info;
     310             :     size_t i;
     311             :     int ret;
     312             : 
     313             :     slot->certs = NULL;
     314             :     slot->id = id;
     315             : 
     316             :     ret = P11FUNC(p, GetSlotInfo, (slot->id, &slot_info));
     317             :     if (ret) {
     318             :         hx509_set_error_string(context, 0, HX509_PKCS11_TOKEN_CONFUSED,
     319             :                                "Failed to init PKCS11 slot %d",
     320             :                                num);
     321             :         return HX509_PKCS11_TOKEN_CONFUSED;
     322             :     }
     323             : 
     324             :     for (i = sizeof(slot_info.slotDescription) - 1; i > 0; i--) {
     325             :         char c = slot_info.slotDescription[i];
     326             :         if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\0')
     327             :             continue;
     328             :         i++;
     329             :         break;
     330             :     }
     331             : 
     332             :     ret = asprintf(&slot->name, "%.*s", (int)i,
     333             :                    slot_info.slotDescription);
     334             :     if (ret == -1)
     335             :         return ENOMEM;
     336             : 
     337             :     if ((slot_info.flags & CKF_TOKEN_PRESENT) == 0)
     338             :         return 0;
     339             : 
     340             :     ret = P11FUNC(p, GetTokenInfo, (slot->id, &token_info));
     341             :     if (ret) {
     342             :         hx509_set_error_string(context, 0, HX509_PKCS11_NO_TOKEN,
     343             :                                "Failed to init PKCS11 slot %d "
     344             :                                "with error 0x%08x",
     345             :                                num, ret);
     346             :         return HX509_PKCS11_NO_TOKEN;
     347             :     }
     348             :     slot->flags |= P11_TOKEN_PRESENT;
     349             : 
     350             :     if (token_info.flags & CKF_LOGIN_REQUIRED)
     351             :         slot->flags |= P11_LOGIN_REQ;
     352             : 
     353             :     ret = p11_get_session(context, p, slot, lock, &session);
     354             :     if (ret)
     355             :         return ret;
     356             : 
     357             :     ret = p11_mech_info(context, p, slot, num);
     358             :     if (ret)
     359             :         goto out;
     360             : 
     361             :     ret = p11_list_keys(context, p, slot, session, lock, &slot->certs);
     362             :  out:
     363             :     p11_put_session(p, slot, session);
     364             : 
     365             :     return ret;
     366             : }
     367             : 
     368             : static int
     369             : p11_get_session(hx509_context context,
     370             :                 struct p11_module *p,
     371             :                 struct p11_slot *slot,
     372             :                 hx509_lock lock,
     373             :                 CK_SESSION_HANDLE *psession)
     374             : {
     375             :     CK_RV ret;
     376             : 
     377             :     if (slot->flags & P11_SESSION_IN_USE)
     378             :         _hx509_abort("slot already in session");
     379             : 
     380             :     if (slot->flags & P11_SESSION) {
     381             :         slot->flags |= P11_SESSION_IN_USE;
     382             :         *psession = slot->session;
     383             :         return 0;
     384             :     }
     385             : 
     386             :     ret = P11FUNC(p, OpenSession, (slot->id,
     387             :                                    CKF_SERIAL_SESSION,
     388             :                                    NULL,
     389             :                                    NULL,
     390             :                                    &slot->session));
     391             :     if (ret != CKR_OK) {
     392             :         if (context)
     393             :             hx509_set_error_string(context, 0, HX509_PKCS11_OPEN_SESSION,
     394             :                                    "Failed to OpenSession for slot id %d "
     395             :                                    "with error: 0x%08x",
     396             :                                    (int)slot->id, ret);
     397             :         return HX509_PKCS11_OPEN_SESSION;
     398             :     }
     399             : 
     400             :     slot->flags |= P11_SESSION;
     401             : 
     402             :     /*
     403             :      * If we have have to login, and haven't tried before and have a
     404             :      * prompter or known to work pin code.
     405             :      *
     406             :      * This code is very conversative and only uses the prompter in
     407             :      * the hx509_lock, the reason is that it's bad to try many
     408             :      * passwords on a pkcs11 token, it might lock up and have to be
     409             :      * unlocked by a administrator.
     410             :      *
     411             :      * XXX try harder to not use pin several times on the same card.
     412             :      */
     413             : 
     414             :     if (   (slot->flags & P11_LOGIN_REQ)
     415             :         && (slot->flags & P11_LOGIN_DONE) == 0
     416             :         && (lock || slot->pin))
     417             :     {
     418             :         hx509_prompt prompt;
     419             :         char pin[20];
     420             :         char *str;
     421             : 
     422             :         if (slot->pin == NULL) {
     423             : 
     424             :             memset(&prompt, 0, sizeof(prompt));
     425             : 
     426             :             ret = asprintf(&str, "PIN code for %s: ", slot->name);
     427             :             if (ret == -1 || str == NULL) {
     428             :                 if (context)
     429             :                     hx509_set_error_string(context, 0, ENOMEM, "out of memory");
     430             :                 return ENOMEM;
     431             :             }
     432             :             prompt.prompt = str;
     433             :             prompt.type = HX509_PROMPT_TYPE_PASSWORD;
     434             :             prompt.reply.data = pin;
     435             :             prompt.reply.length = sizeof(pin);
     436             : 
     437             :             ret = hx509_lock_prompt(lock, &prompt);
     438             :             if (ret) {
     439             :                 free(str);
     440             :                 if (context)
     441             :                     hx509_set_error_string(context, 0, ret,
     442             :                                            "Failed to get pin code for slot "
     443             :                                            "id %d with error: %d",
     444             :                                            (int)slot->id, ret);
     445             :                 return ret;
     446             :             }
     447             :             free(str);
     448             :         } else {
     449             :             strlcpy(pin, slot->pin, sizeof(pin));
     450             :         }
     451             : 
     452             :         ret = P11FUNC(p, Login, (slot->session, CKU_USER,
     453             :                                  (unsigned char*)pin, strlen(pin)));
     454             :         if (ret != CKR_OK) {
     455             :             if (context)
     456             :                 hx509_set_error_string(context, 0, HX509_PKCS11_LOGIN,
     457             :                                        "Failed to login on slot id %d "
     458             :                                        "with error: 0x%08x",
     459             :                                        (int)slot->id, ret);
     460             :             switch(ret) {
     461             :                 case CKR_PIN_LOCKED:
     462             :                     return HX509_PKCS11_PIN_LOCKED;
     463             :                 case CKR_PIN_EXPIRED:
     464             :                     return HX509_PKCS11_PIN_EXPIRED;
     465             :                 case CKR_PIN_INCORRECT:
     466             :                     return HX509_PKCS11_PIN_INCORRECT;
     467             :                 case CKR_USER_PIN_NOT_INITIALIZED:
     468             :                     return HX509_PKCS11_PIN_NOT_INITIALIZED;
     469             :                 default:
     470             :                     return HX509_PKCS11_LOGIN;
     471             :             }
     472             :         } else
     473             :             slot->flags |= P11_LOGIN_DONE;
     474             : 
     475             :         if (slot->pin == NULL) {
     476             :             slot->pin = strdup(pin);
     477             :             if (slot->pin == NULL) {
     478             :                 if (context)
     479             :                     hx509_set_error_string(context, 0, ENOMEM,
     480             :                                            "out of memory");
     481             :                 return ENOMEM;
     482             :             }
     483             :         }
     484             :     } else
     485             :         slot->flags |= P11_LOGIN_DONE;
     486             : 
     487             :     slot->flags |= P11_SESSION_IN_USE;
     488             : 
     489             :     *psession = slot->session;
     490             : 
     491             :     return 0;
     492             : }
     493             : 
     494             : static int
     495             : p11_put_session(struct p11_module *p,
     496             :                 struct p11_slot *slot,
     497             :                 CK_SESSION_HANDLE session)
     498             : {
     499             :     if ((slot->flags & P11_SESSION_IN_USE) == 0)
     500             :         _hx509_abort("slot not in session");
     501             :     slot->flags &= ~P11_SESSION_IN_USE;
     502             : 
     503             :     return 0;
     504             : }
     505             : 
     506             : static int
     507             : iterate_entries(hx509_context context,
     508             :                 struct p11_module *p, struct p11_slot *slot,
     509             :                 CK_SESSION_HANDLE session,
     510             :                 CK_ATTRIBUTE *search_data, int num_search_data,
     511             :                 CK_ATTRIBUTE *query, int num_query,
     512             :                 int (*func)(hx509_context,
     513             :                             struct p11_module *, struct p11_slot *,
     514             :                             CK_SESSION_HANDLE session,
     515             :                             CK_OBJECT_HANDLE object,
     516             :                             void *, CK_ATTRIBUTE *, int), void *ptr)
     517             : {
     518             :     CK_OBJECT_HANDLE object;
     519             :     CK_ULONG object_count;
     520             :     int ret, ret2, i;
     521             : 
     522             :     ret = P11FUNC(p, FindObjectsInit, (session, search_data, num_search_data));
     523             :     if (ret != CKR_OK) {
     524             :         return -1;
     525             :     }
     526             :     while (1) {
     527             :         ret = P11FUNC(p, FindObjects, (session, &object, 1, &object_count));
     528             :         if (ret != CKR_OK) {
     529             :             return -1;
     530             :         }
     531             :         if (object_count == 0)
     532             :             break;
     533             : 
     534             :         for (i = 0; i < num_query; i++)
     535             :             query[i].pValue = NULL;
     536             : 
     537             :         ret = P11FUNC(p, GetAttributeValue,
     538             :                       (session, object, query, num_query));
     539             :         if (ret != CKR_OK) {
     540             :             return -1;
     541             :         }
     542             :         for (i = 0; i < num_query; i++) {
     543             :             query[i].pValue = malloc(query[i].ulValueLen);
     544             :             if (query[i].pValue == NULL) {
     545             :                 ret = ENOMEM;
     546             :                 goto out;
     547             :             }
     548             :         }
     549             :         ret = P11FUNC(p, GetAttributeValue,
     550             :                       (session, object, query, num_query));
     551             :         if (ret != CKR_OK) {
     552             :             ret = -1;
     553             :             goto out;
     554             :         }
     555             : 
     556             :         ret = (*func)(context, p, slot, session, object, ptr, query, num_query);
     557             :         if (ret)
     558             :             goto out;
     559             : 
     560             :         for (i = 0; i < num_query; i++) {
     561             :             if (query[i].pValue)
     562             :                 free(query[i].pValue);
     563             :             query[i].pValue = NULL;
     564             :         }
     565             :     }
     566             :  out:
     567             : 
     568             :     for (i = 0; i < num_query; i++) {
     569             :         if (query[i].pValue)
     570             :             free(query[i].pValue);
     571             :         query[i].pValue = NULL;
     572             :     }
     573             : 
     574             :     ret2 = P11FUNC(p, FindObjectsFinal, (session));
     575             :     if (ret2 != CKR_OK) {
     576             :         return ret2;
     577             :     }
     578             : 
     579             :     return ret;
     580             : }
     581             : 
     582             : static BIGNUM *
     583             : getattr_bn(struct p11_module *p,
     584             :            struct p11_slot *slot,
     585             :            CK_SESSION_HANDLE session,
     586             :            CK_OBJECT_HANDLE object,
     587             :            unsigned int type)
     588             : {
     589             :     CK_ATTRIBUTE query;
     590             :     BIGNUM *bn;
     591             :     int ret;
     592             : 
     593             :     query.type = type;
     594             :     query.pValue = NULL;
     595             :     query.ulValueLen = 0;
     596             : 
     597             :     ret = P11FUNC(p, GetAttributeValue,
     598             :                   (session, object, &query, 1));
     599             :     if (ret != CKR_OK)
     600             :         return NULL;
     601             : 
     602             :     query.pValue = malloc(query.ulValueLen);
     603             : 
     604             :     ret = P11FUNC(p, GetAttributeValue,
     605             :                   (session, object, &query, 1));
     606             :     if (ret != CKR_OK) {
     607             :         free(query.pValue);
     608             :         return NULL;
     609             :     }
     610             :     bn = BN_bin2bn(query.pValue, query.ulValueLen, NULL);
     611             :     free(query.pValue);
     612             : 
     613             :     return bn;
     614             : }
     615             : 
     616             : static int
     617             : collect_private_key(hx509_context context,
     618             :                     struct p11_module *p, struct p11_slot *slot,
     619             :                     CK_SESSION_HANDLE session,
     620             :                     CK_OBJECT_HANDLE object,
     621             :                     void *ptr, CK_ATTRIBUTE *query, int num_query)
     622             : {
     623             :     struct hx509_collector *collector = ptr;
     624             :     hx509_private_key key;
     625             :     heim_octet_string localKeyId;
     626             :     int ret;
     627             :     RSA *rsa;
     628             :     struct p11_rsa *p11rsa;
     629             : 
     630             :     localKeyId.data = query[0].pValue;
     631             :     localKeyId.length = query[0].ulValueLen;
     632             : 
     633             :     ret = hx509_private_key_init(&key, NULL, NULL);
     634             :     if (ret)
     635             :         return ret;
     636             : 
     637             :     rsa = RSA_new();
     638             :     if (rsa == NULL)
     639             :         _hx509_abort("out of memory");
     640             : 
     641             :     /*
     642             :      * The exponent and modulus should always be present according to
     643             :      * the pkcs11 specification, but some smartcards leaves it out,
     644             :      * let ignore any failure to fetch it.
     645             :      */
     646             :     rsa->n = getattr_bn(p, slot, session, object, CKA_MODULUS);
     647             :     rsa->e = getattr_bn(p, slot, session, object, CKA_PUBLIC_EXPONENT);
     648             : 
     649             :     p11rsa = calloc(1, sizeof(*p11rsa));
     650             :     if (p11rsa == NULL)
     651             :         _hx509_abort("out of memory");
     652             : 
     653             :     p11rsa->p = p;
     654             :     p11rsa->slot = slot;
     655             :     p11rsa->private_key = object;
     656             : 
     657             :     if (p->ref == 0)
     658             :         _hx509_abort("pkcs11 ref == 0 on alloc");
     659             :     p->ref++;
     660             :     if (p->ref == UINT_MAX)
     661             :         _hx509_abort("pkcs11 ref == UINT_MAX on alloc");
     662             : 
     663             :     RSA_set_method(rsa, &p11_rsa_pkcs1_method);
     664             :     ret = RSA_set_app_data(rsa, p11rsa);
     665             :     if (ret != 1)
     666             :         _hx509_abort("RSA_set_app_data");
     667             : 
     668             :     hx509_private_key_assign_rsa(key, rsa);
     669             : 
     670             :     ret = _hx509_collector_private_key_add(context,
     671             :                                            collector,
     672             :                                            hx509_signature_rsa(),
     673             :                                            key,
     674             :                                            NULL,
     675             :                                            &localKeyId);
     676             : 
     677             :     if (ret) {
     678             :         hx509_private_key_free(&key);
     679             :         return ret;
     680             :     }
     681             :     return 0;
     682             : }
     683             : 
     684             : static void
     685             : p11_cert_release(hx509_cert cert, void *ctx)
     686             : {
     687             :     struct p11_module *p = ctx;
     688             :     p11_release_module(p);
     689             : }
     690             : 
     691             : 
     692             : static int
     693             : collect_cert(hx509_context context,
     694             :              struct p11_module *p, struct p11_slot *slot,
     695             :              CK_SESSION_HANDLE session,
     696             :              CK_OBJECT_HANDLE object,
     697             :              void *ptr, CK_ATTRIBUTE *query, int num_query)
     698             : {
     699             :     struct hx509_collector *collector = ptr;
     700             :     heim_error_t error = NULL;
     701             :     hx509_cert cert;
     702             :     int ret;
     703             : 
     704             :     if ((CK_LONG)query[0].ulValueLen == -1 ||
     705             :         (CK_LONG)query[1].ulValueLen == -1)
     706             :     {
     707             :         return 0;
     708             :     }
     709             : 
     710             :     cert = hx509_cert_init_data(context, query[1].pValue,
     711             :                                query[1].ulValueLen, &error);
     712             :     if (cert == NULL) {
     713             :         ret = heim_error_get_code(error);
     714             :         heim_release(error);
     715             :         return ret;
     716             :     }
     717             : 
     718             :     if (p->ref == 0)
     719             :         _hx509_abort("pkcs11 ref == 0 on alloc");
     720             :     p->ref++;
     721             :     if (p->ref == UINT_MAX)
     722             :         _hx509_abort("pkcs11 ref to high");
     723             : 
     724             :     _hx509_cert_set_release(cert, p11_cert_release, p);
     725             : 
     726             :     {
     727             :         heim_octet_string data;
     728             : 
     729             :         data.data = query[0].pValue;
     730             :         data.length = query[0].ulValueLen;
     731             : 
     732             :         _hx509_set_cert_attribute(context,
     733             :                                   cert,
     734             :                                   &asn1_oid_id_pkcs_9_at_localKeyId,
     735             :                                   &data);
     736             :     }
     737             : 
     738             :     if ((CK_LONG)query[2].ulValueLen != -1) {
     739             :         char *str;
     740             : 
     741             :         ret = asprintf(&str, "%.*s",
     742             :                        (int)query[2].ulValueLen, (char *)query[2].pValue);
     743             :         if (ret != -1 && str) {
     744             :             hx509_cert_set_friendly_name(cert, str);
     745             :             free(str);
     746             :         }
     747             :     }
     748             : 
     749             :     ret = _hx509_collector_certs_add(context, collector, cert);
     750             :     hx509_cert_free(cert);
     751             : 
     752             :     return ret;
     753             : }
     754             : 
     755             : 
     756             : static int
     757             : p11_list_keys(hx509_context context,
     758             :               struct p11_module *p,
     759             :               struct p11_slot *slot,
     760             :               CK_SESSION_HANDLE session,
     761             :               hx509_lock lock,
     762             :               hx509_certs *certs)
     763             : {
     764             :     struct hx509_collector *collector;
     765             :     CK_OBJECT_CLASS key_class;
     766             :     CK_ATTRIBUTE search_data[] = {
     767             :         {CKA_CLASS, NULL, 0},
     768             :     };
     769             :     CK_ATTRIBUTE query_data[3] = {
     770             :         {CKA_ID, NULL, 0},
     771             :         {CKA_VALUE, NULL, 0},
     772             :         {CKA_LABEL, NULL, 0}
     773             :     };
     774             :     int ret;
     775             : 
     776             :     search_data[0].pValue = &key_class;
     777             :     search_data[0].ulValueLen = sizeof(key_class);
     778             : 
     779             :     if (lock == NULL)
     780             :         lock = _hx509_empty_lock;
     781             : 
     782             :     ret = _hx509_collector_alloc(context, lock, &collector);
     783             :     if (ret)
     784             :         return ret;
     785             : 
     786             :     key_class = CKO_PRIVATE_KEY;
     787             :     ret = iterate_entries(context, p, slot, session,
     788             :                           search_data, 1,
     789             :                           query_data, 1,
     790             :                           collect_private_key, collector);
     791             :     if (ret)
     792             :         goto out;
     793             : 
     794             :     key_class = CKO_CERTIFICATE;
     795             :     ret = iterate_entries(context, p, slot, session,
     796             :                           search_data, 1,
     797             :                           query_data, 3,
     798             :                           collect_cert, collector);
     799             :     if (ret)
     800             :         goto out;
     801             : 
     802             :     ret = _hx509_collector_collect_certs(context, collector, &slot->certs);
     803             : 
     804             : out:
     805             :     _hx509_collector_free(collector);
     806             : 
     807             :     return ret;
     808             : }
     809             : 
     810             : 
     811             : static int
     812             : p11_init(hx509_context context,
     813             :          hx509_certs certs, void **data, int flags,
     814             :          const char *residue, hx509_lock lock)
     815             : {
     816             :     CK_C_GetFunctionList getFuncs;
     817             :     struct p11_module *p;
     818             :     char *list, *str;
     819             :     int ret;
     820             : 
     821             :     *data = NULL;
     822             : 
     823             :     if (flags & HX509_CERTS_NO_PRIVATE_KEYS) {
     824             :         hx509_set_error_string(context, 0, ENOTSUP,
     825             :                                "PKCS#11 store does not support "
     826             :                                "HX509_CERTS_NO_PRIVATE_KEYS flag");
     827             :         return ENOTSUP;
     828             :     }
     829             : 
     830             :     if (residue == NULL || residue[0] == '\0') {
     831             :         hx509_set_error_string(context, 0, EINVAL,
     832             :                                "PKCS#11 store not specified");
     833             :         return EINVAL;
     834             :     }
     835             :     list = strdup(residue);
     836             :     if (list == NULL)
     837             :         return ENOMEM;
     838             : 
     839             :     p = calloc(1, sizeof(*p));
     840             :     if (p == NULL) {
     841             :         free(list);
     842             :         return ENOMEM;
     843             :     }
     844             : 
     845             :     p->ref = 1;
     846             :     p->selected_slot = 0;
     847             : 
     848             :     str = strchr(list, ',');
     849             :     if (str)
     850             :         *str++ = '\0';
     851             :     while (str) {
     852             :         char *strnext;
     853             :         strnext = strchr(str, ',');
     854             :         if (strnext)
     855             :             *strnext++ = '\0';
     856             :         if (strncasecmp(str, "slot=", 5) == 0)
     857             :             p->selected_slot = atoi(str + 5);
     858             :         str = strnext;
     859             :     }
     860             : 
     861             :     p->dl_handle = dlopen(list, RTLD_NOW | RTLD_LOCAL | RTLD_GROUP);
     862             :     if (p->dl_handle == NULL) {
     863             :         ret = HX509_PKCS11_LOAD;
     864             :         hx509_set_error_string(context, 0, ret,
     865             :                                "Failed to open %s: %s", list, dlerror());
     866             :         goto out;
     867             :     }
     868             : 
     869             :     getFuncs = (CK_C_GetFunctionList) dlsym(p->dl_handle, "C_GetFunctionList");
     870             :     if (getFuncs == NULL) {
     871             :         ret = HX509_PKCS11_LOAD;
     872             :         hx509_set_error_string(context, 0, ret,
     873             :                                "C_GetFunctionList missing in %s: %s",
     874             :                                list, dlerror());
     875             :         goto out;
     876             :     }
     877             : 
     878             :     ret = (*getFuncs)(&p->funcs);
     879             :     if (ret) {
     880             :         ret = HX509_PKCS11_LOAD;
     881             :         hx509_set_error_string(context, 0, ret,
     882             :                                "C_GetFunctionList failed in %s", list);
     883             :         goto out;
     884             :     }
     885             : 
     886             :     ret = P11FUNC(p, Initialize, (NULL_PTR));
     887             :     if (ret != CKR_OK) {
     888             :         ret = HX509_PKCS11_TOKEN_CONFUSED;
     889             :         hx509_set_error_string(context, 0, ret,
     890             :                                "Failed initialize the PKCS11 module");
     891             :         goto out;
     892             :     }
     893             : 
     894             :     ret = P11FUNC(p, GetSlotList, (FALSE, NULL, &p->num_slots));
     895             :     if (ret) {
     896             :         ret = HX509_PKCS11_TOKEN_CONFUSED;
     897             :         hx509_set_error_string(context, 0, ret,
     898             :                                "Failed to get number of PKCS11 slots");
     899             :         goto out;
     900             :     }
     901             : 
     902             :    if (p->num_slots == 0) {
     903             :         ret = HX509_PKCS11_NO_SLOT;
     904             :         hx509_set_error_string(context, 0, ret,
     905             :                                "Selected PKCS11 module have no slots");
     906             :         goto out;
     907             :    }
     908             : 
     909             : 
     910             :     {
     911             :         CK_SLOT_ID_PTR slot_ids;
     912             :         int num_tokens = 0;
     913             :         size_t i;
     914             : 
     915             :         slot_ids = malloc(p->num_slots * sizeof(*slot_ids));
     916             :         if (slot_ids == NULL) {
     917             :             hx509_clear_error_string(context);
     918             :             ret = ENOMEM;
     919             :             goto out;
     920             :         }
     921             : 
     922             :         ret = P11FUNC(p, GetSlotList, (FALSE, slot_ids, &p->num_slots));
     923             :         if (ret) {
     924             :             free(slot_ids);
     925             :             hx509_set_error_string(context, 0, HX509_PKCS11_TOKEN_CONFUSED,
     926             :                                    "Failed getting slot-list from "
     927             :                                    "PKCS11 module");
     928             :             ret = HX509_PKCS11_TOKEN_CONFUSED;
     929             :             goto out;
     930             :         }
     931             : 
     932             :         p->slot = calloc(p->num_slots, sizeof(p->slot[0]));
     933             :         if (p->slot == NULL) {
     934             :             free(slot_ids);
     935             :             hx509_set_error_string(context, 0, ENOMEM,
     936             :                                    "Failed to get memory for slot-list");
     937             :             ret = ENOMEM;
     938             :             goto out;
     939             :         }
     940             : 
     941             :         for (i = 0; i < p->num_slots; i++) {
     942             :             if ((p->selected_slot != 0) && (slot_ids[i] != (p->selected_slot - 1)))
     943             :                 continue;
     944             :             ret = p11_init_slot(context, p, lock, slot_ids[i], i, &p->slot[i]);
     945             :             if (!ret) {
     946             :                 if (p->slot[i].flags & P11_TOKEN_PRESENT)
     947             :                     num_tokens++;
     948             :             }
     949             :         }
     950             :         free(slot_ids);
     951             :         if (ret)
     952             :             goto out;
     953             :         if (num_tokens == 0) {
     954             :             ret = HX509_PKCS11_NO_TOKEN;
     955             :             goto out;
     956             :         }
     957             :     }
     958             : 
     959             :     free(list);
     960             : 
     961             :     *data = p;
     962             : 
     963             :     return 0;
     964             :  out:
     965             :     if (list)
     966             :         free(list);
     967             :     p11_release_module(p);
     968             :     return ret;
     969             : }
     970             : 
     971             : static void
     972             : p11_release_module(struct p11_module *p)
     973             : {
     974             :     size_t i;
     975             : 
     976             :     if (p->ref == 0)
     977             :         _hx509_abort("pkcs11 ref to low");
     978             :     if (--p->ref > 0)
     979             :         return;
     980             : 
     981             :     for (i = 0; i < p->num_slots; i++) {
     982             :         if (p->slot[i].flags & P11_SESSION_IN_USE)
     983             :             _hx509_abort("pkcs11 module release while session in use");
     984             :         if (p->slot[i].flags & P11_SESSION) {
     985             :             P11FUNC(p, CloseSession, (p->slot[i].session));
     986             :         }
     987             : 
     988             :         if (p->slot[i].name)
     989             :             free(p->slot[i].name);
     990             :         if (p->slot[i].pin) {
     991             :             memset(p->slot[i].pin, 0, strlen(p->slot[i].pin));
     992             :             free(p->slot[i].pin);
     993             :         }
     994             :         if (p->slot[i].mechs.num) {
     995             :             free(p->slot[i].mechs.list);
     996             : 
     997             :             if (p->slot[i].mechs.infos) {
     998             :                 size_t j;
     999             : 
    1000             :                 for (j = 0 ; j < p->slot[i].mechs.num ; j++)
    1001             :                     free(p->slot[i].mechs.infos[j]);
    1002             :                 free(p->slot[i].mechs.infos);
    1003             :             }
    1004             :         }
    1005             :     }
    1006             :     free(p->slot);
    1007             : 
    1008             :     if (p->funcs)
    1009             :         P11FUNC(p, Finalize, (NULL));
    1010             : 
    1011             :     if (p->dl_handle)
    1012             :         dlclose(p->dl_handle);
    1013             : 
    1014             :     memset(p, 0, sizeof(*p));
    1015             :     free(p);
    1016             : }
    1017             : 
    1018             : static int
    1019             : p11_free(hx509_certs certs, void *data)
    1020             : {
    1021             :     struct p11_module *p = data;
    1022             :     size_t i;
    1023             : 
    1024             :     for (i = 0; i < p->num_slots; i++) {
    1025             :         if (p->slot[i].certs)
    1026             :             hx509_certs_free(&p->slot[i].certs);
    1027             :     }
    1028             :     p11_release_module(p);
    1029             :     return 0;
    1030             : }
    1031             : 
    1032             : struct p11_cursor {
    1033             :     hx509_certs certs;
    1034             :     void *cursor;
    1035             : };
    1036             : 
    1037             : static int
    1038             : p11_iter_start(hx509_context context,
    1039             :                hx509_certs certs, void *data, void **cursor)
    1040             : {
    1041             :     struct p11_module *p = data;
    1042             :     struct p11_cursor *c;
    1043             :     int ret;
    1044             :     size_t i;
    1045             : 
    1046             :     c = malloc(sizeof(*c));
    1047             :     if (c == NULL) {
    1048             :         hx509_clear_error_string(context);
    1049             :         return ENOMEM;
    1050             :     }
    1051             :     ret = hx509_certs_init(context, "MEMORY:pkcs11-iter", 0, NULL, &c->certs);
    1052             :     if (ret) {
    1053             :         free(c);
    1054             :         return ret;
    1055             :     }
    1056             : 
    1057             :     for (i = 0 ; i < p->num_slots; i++) {
    1058             :         if (p->slot[i].certs == NULL)
    1059             :             continue;
    1060             :         ret = hx509_certs_merge(context, c->certs, p->slot[i].certs);
    1061             :         if (ret) {
    1062             :             hx509_certs_free(&c->certs);
    1063             :             free(c);
    1064             :             return ret;
    1065             :         }
    1066             :     }
    1067             : 
    1068             :     ret = hx509_certs_start_seq(context, c->certs, &c->cursor);
    1069             :     if (ret) {
    1070             :         hx509_certs_free(&c->certs);
    1071             :         free(c);
    1072             :         return 0;
    1073             :     }
    1074             :     *cursor = c;
    1075             : 
    1076             :     return 0;
    1077             : }
    1078             : 
    1079             : static int
    1080             : p11_iter(hx509_context context,
    1081             :          hx509_certs certs, void *data, void *cursor, hx509_cert *cert)
    1082             : {
    1083             :     struct p11_cursor *c = cursor;
    1084             :     return hx509_certs_next_cert(context, c->certs, c->cursor, cert);
    1085             : }
    1086             : 
    1087             : static int
    1088             : p11_iter_end(hx509_context context,
    1089             :              hx509_certs certs, void *data, void *cursor)
    1090             : {
    1091             :     struct p11_cursor *c = cursor;
    1092             :     int ret;
    1093             :     ret = hx509_certs_end_seq(context, c->certs, c->cursor);
    1094             :     hx509_certs_free(&c->certs);
    1095             :     free(c);
    1096             :     return ret;
    1097             : }
    1098             : 
    1099             : #define MECHFLAG(x) { "unknown-flag-" #x, x }
    1100             : static struct units mechflags[] = {
    1101             :         MECHFLAG(0x80000000),
    1102             :         MECHFLAG(0x40000000),
    1103             :         MECHFLAG(0x20000000),
    1104             :         MECHFLAG(0x10000000),
    1105             :         MECHFLAG(0x08000000),
    1106             :         MECHFLAG(0x04000000),
    1107             :         {"ec-compress",               0x2000000 },
    1108             :         {"ec-uncompress",     0x1000000 },
    1109             :         {"ec-namedcurve",     0x0800000 },
    1110             :         {"ec-ecparameters",   0x0400000 },
    1111             :         {"ec-f-2m",           0x0200000 },
    1112             :         {"ec-f-p",            0x0100000 },
    1113             :         {"derive",            0x0080000 },
    1114             :         {"unwrap",            0x0040000 },
    1115             :         {"wrap",              0x0020000 },
    1116             :         {"genereate-key-pair",        0x0010000 },
    1117             :         {"generate",          0x0008000 },
    1118             :         {"verify-recover",    0x0004000 },
    1119             :         {"verify",            0x0002000 },
    1120             :         {"sign-recover",      0x0001000 },
    1121             :         {"sign",              0x0000800 },
    1122             :         {"digest",            0x0000400 },
    1123             :         {"decrypt",           0x0000200 },
    1124             :         {"encrypt",           0x0000100 },
    1125             :         MECHFLAG(0x00080),
    1126             :         MECHFLAG(0x00040),
    1127             :         MECHFLAG(0x00020),
    1128             :         MECHFLAG(0x00010),
    1129             :         MECHFLAG(0x00008),
    1130             :         MECHFLAG(0x00004),
    1131             :         MECHFLAG(0x00002),
    1132             :         {"hw",                        0x0000001 },
    1133             :         { NULL,                 0x0000000 }
    1134             : };
    1135             : #undef MECHFLAG
    1136             : 
    1137             : static int
    1138             : p11_printinfo(hx509_context context,
    1139             :               hx509_certs certs,
    1140             :               void *data,
    1141             :               int (*func)(void *, const char *),
    1142             :               void *ctx)
    1143             : {
    1144             :     struct p11_module *p = data;
    1145             :     size_t i, j;
    1146             : 
    1147             :     _hx509_pi_printf(func, ctx, "pkcs11 driver with %d slot%s",
    1148             :                      p->num_slots, p->num_slots > 1 ? "s" : "");
    1149             : 
    1150             :     for (i = 0; i < p->num_slots; i++) {
    1151             :         struct p11_slot *s = &p->slot[i];
    1152             : 
    1153             :         _hx509_pi_printf(func, ctx, "slot %d: id: %d name: %s flags: %08x",
    1154             :                          i, (int)s->id, s->name, s->flags);
    1155             : 
    1156             :         _hx509_pi_printf(func, ctx, "number of supported mechanisms: %lu",
    1157             :                          (unsigned long)s->mechs.num);
    1158             :         for (j = 0; j < s->mechs.num; j++) {
    1159             :             const char *mechname = "unknown";
    1160             :             char flags[256], unknownname[40];
    1161             : #define MECHNAME(s,n) case s: mechname = n; break
    1162             :             switch(s->mechs.list[j]) {
    1163             :                 MECHNAME(CKM_RSA_PKCS_KEY_PAIR_GEN, "rsa-pkcs-key-pair-gen");
    1164             :                 MECHNAME(CKM_RSA_PKCS, "rsa-pkcs");
    1165             :                 MECHNAME(CKM_RSA_X_509, "rsa-x-509");
    1166             :                 MECHNAME(CKM_MD5_RSA_PKCS, "md5-rsa-pkcs");
    1167             :                 MECHNAME(CKM_SHA1_RSA_PKCS, "sha1-rsa-pkcs");
    1168             :                 MECHNAME(CKM_SHA256_RSA_PKCS, "sha256-rsa-pkcs");
    1169             :                 MECHNAME(CKM_SHA384_RSA_PKCS, "sha384-rsa-pkcs");
    1170             :                 MECHNAME(CKM_SHA512_RSA_PKCS, "sha512-rsa-pkcs");
    1171             :                 MECHNAME(CKM_RIPEMD160_RSA_PKCS, "ripemd160-rsa-pkcs");
    1172             :                 MECHNAME(CKM_RSA_PKCS_OAEP, "rsa-pkcs-oaep");
    1173             :                 MECHNAME(CKM_SHA512_HMAC, "sha512-hmac");
    1174             :                 MECHNAME(CKM_SHA512, "sha512");
    1175             :                 MECHNAME(CKM_SHA384_HMAC, "sha384-hmac");
    1176             :                 MECHNAME(CKM_SHA384, "sha384");
    1177             :                 MECHNAME(CKM_SHA256_HMAC, "sha256-hmac");
    1178             :                 MECHNAME(CKM_SHA256, "sha256");
    1179             :                 MECHNAME(CKM_SHA_1, "sha1");
    1180             :                 MECHNAME(CKM_MD5, "md5");
    1181             :                 MECHNAME(CKM_RIPEMD160, "ripemd-160");
    1182             :                 MECHNAME(CKM_DES_ECB, "des-ecb");
    1183             :                 MECHNAME(CKM_DES_CBC, "des-cbc");
    1184             :                 MECHNAME(CKM_AES_ECB, "aes-ecb");
    1185             :                 MECHNAME(CKM_AES_CBC, "aes-cbc");
    1186             :                 MECHNAME(CKM_DH_PKCS_PARAMETER_GEN, "dh-pkcs-parameter-gen");
    1187             :             default:
    1188             :                 snprintf(unknownname, sizeof(unknownname),
    1189             :                          "unknown-mech-%lu",
    1190             :                          (unsigned long)s->mechs.list[j]);
    1191             :                 mechname = unknownname;
    1192             :                 break;
    1193             :             }
    1194             : #undef MECHNAME
    1195             :             unparse_flags(s->mechs.infos[j]->flags, mechflags,
    1196             :                           flags, sizeof(flags));
    1197             : 
    1198             :             _hx509_pi_printf(func, ctx, "  %s: %s", mechname, flags);
    1199             :         }
    1200             :     }
    1201             : 
    1202             :     return 0;
    1203             : }
    1204             : 
    1205             : static struct hx509_keyset_ops keyset_pkcs11 = {
    1206             :     "PKCS11",
    1207             :     0,
    1208             :     p11_init,
    1209             :     NULL,
    1210             :     p11_free,
    1211             :     NULL,
    1212             :     NULL,
    1213             :     p11_iter_start,
    1214             :     p11_iter,
    1215             :     p11_iter_end,
    1216             :     p11_printinfo,
    1217             :     NULL,
    1218             :     NULL,
    1219             :     NULL
    1220             : };
    1221             : 
    1222             : #endif /* HAVE_DLOPEN */
    1223             : 
    1224             : HX509_LIB_FUNCTION void HX509_LIB_CALL
    1225      792004 : _hx509_ks_pkcs11_register(hx509_context context)
    1226             : {
    1227             : #ifdef HAVE_DLOPEN
    1228             :     _hx509_ks_register(context, &keyset_pkcs11);
    1229             : #endif
    1230      792004 : }

Generated by: LCOV version 1.14