git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@16070 ec53bebd-3082-4978-b11e-865c3cabbd6b
		
			
				
	
	
		
			577 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			577 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * Copyright (c) 2004 - 2005 Kungliga Tekniska Högskolan
 | 
						|
 * (Royal Institute of Technology, Stockholm, Sweden). 
 | 
						|
 * All rights reserved. 
 | 
						|
 *
 | 
						|
 * Redistribution and use in source and binary forms, with or without 
 | 
						|
 * modification, are permitted provided that the following conditions 
 | 
						|
 * are met: 
 | 
						|
 *
 | 
						|
 * 1. Redistributions of source code must retain the above copyright 
 | 
						|
 *    notice, this list of conditions and the following disclaimer. 
 | 
						|
 *
 | 
						|
 * 2. Redistributions in binary form must reproduce the above copyright 
 | 
						|
 *    notice, this list of conditions and the following disclaimer in the 
 | 
						|
 *    documentation and/or other materials provided with the distribution. 
 | 
						|
 *
 | 
						|
 * 3. Neither the name of the Institute nor the names of its contributors 
 | 
						|
 *    may be used to endorse or promote products derived from this software 
 | 
						|
 *    without specific prior written permission. 
 | 
						|
 *
 | 
						|
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
 | 
						|
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 | 
						|
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
 | 
						|
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
 | 
						|
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
 | 
						|
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
 | 
						|
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
 | 
						|
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 | 
						|
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
 | 
						|
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
 | 
						|
 * SUCH DAMAGE. 
 | 
						|
 */
 | 
						|
 | 
						|
#include "hx_locl.h"
 | 
						|
RCSID("$Id$");
 | 
						|
 | 
						|
/* http://developer.netscape.com/support/faqs/pkcs_11.html */
 | 
						|
 | 
						|
#include <openssl/ui.h>
 | 
						|
 | 
						|
#include <dlfcn.h>
 | 
						|
 | 
						|
#include "pkcs11u.h"
 | 
						|
#include "pkcs11.h"
 | 
						|
 | 
						|
typedef struct hx509_security_device_data *hx509_security_device;
 | 
						|
typedef struct hx509_keyset_data *hx509_keyset;
 | 
						|
 | 
						|
struct p11_slot {
 | 
						|
    int flags;
 | 
						|
#define P11_SESSION		1
 | 
						|
#define P11_LOGIN_REQ		2
 | 
						|
#define P11_LOGIN_DONE		4
 | 
						|
    CK_SESSION_HANDLE session;
 | 
						|
    CK_SLOT_ID id;
 | 
						|
    CK_BBOOL token;
 | 
						|
    char *name;
 | 
						|
    char *pin;
 | 
						|
};
 | 
						|
 | 
						|
struct hx509_security_device_data {
 | 
						|
    int refcount;
 | 
						|
    void *handle;
 | 
						|
    CK_FUNCTION_LIST_PTR funcs;
 | 
						|
    CK_ULONG num_slots;
 | 
						|
    struct p11_slot *slots;
 | 
						|
    int selected_slot; /* XXX */
 | 
						|
};
 | 
						|
 | 
						|
#define P11SESSION(module) ((module)->slots[(module)->selected_slot].session)
 | 
						|
#define P11FUNC(module,f,args) (*(module)->funcs->C_##f)args
 | 
						|
 | 
						|
struct hx509_keyset_data {
 | 
						|
    hx509_security_device device;
 | 
						|
    hx509_certs certs;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
typedef struct hx509_key_data *hx509_key;
 | 
						|
 | 
						|
static int
 | 
						|
hx509_p11_load_module(const char *fn, hx509_security_device *module)
 | 
						|
{
 | 
						|
    CK_C_GetFunctionList getFuncs;
 | 
						|
    hx509_security_device p;
 | 
						|
    int ret;
 | 
						|
 | 
						|
    *module = NULL;
 | 
						|
 | 
						|
    p = calloc(1, sizeof(*p));
 | 
						|
    if (p == NULL)
 | 
						|
	return ENOMEM;
 | 
						|
 | 
						|
    p->selected_slot = 0;
 | 
						|
 | 
						|
    p->handle = dlopen(fn, RTLD_NOW);
 | 
						|
    if (p->handle == NULL) {
 | 
						|
	ret = EINVAL; /* XXX */
 | 
						|
	goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    getFuncs = dlsym(p->handle, "C_GetFunctionList");
 | 
						|
    if (getFuncs == NULL) {
 | 
						|
	ret = EINVAL;
 | 
						|
	goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    ret = (*getFuncs)(&p->funcs);
 | 
						|
    if (ret) {
 | 
						|
	ret = EINVAL;
 | 
						|
	goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    ret = P11FUNC(p, Initialize, (NULL_PTR));
 | 
						|
    if (ret != CKR_OK) {
 | 
						|
	ret = EINVAL;
 | 
						|
	goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    {
 | 
						|
	CK_INFO info;
 | 
						|
 | 
						|
	ret = P11FUNC(p, GetInfo, (&info));
 | 
						|
	if (ret != CKR_OK) {
 | 
						|
	    ret = EINVAL;
 | 
						|
	    goto out;
 | 
						|
	}
 | 
						|
 | 
						|
	printf("module information:\n");
 | 
						|
	printf("version: %04x.%04x\n",
 | 
						|
	       (unsigned int)info.cryptokiVersion.major,
 | 
						|
	       (unsigned int)info.cryptokiVersion.minor);
 | 
						|
	printf("manufacturer: %.*s\n",
 | 
						|
	       (int)sizeof(info.manufacturerID) - 1,
 | 
						|
	       info.manufacturerID);
 | 
						|
	printf("flags: 0x%04x\n", (unsigned int)info.flags);
 | 
						|
	printf("library description: %.*s\n",
 | 
						|
	       (int)sizeof(info.libraryDescription) - 1,
 | 
						|
	       info.libraryDescription);
 | 
						|
	printf("version: %04x.%04x\n",
 | 
						|
	       (unsigned int)info.libraryVersion.major,
 | 
						|
	       (unsigned int)info.libraryVersion.minor);
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    ret = P11FUNC(p, GetSlotList, (FALSE, NULL, &p->num_slots));
 | 
						|
    if (ret) {
 | 
						|
	ret = EINVAL;
 | 
						|
	goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    printf("num slots: %ld\n", (long)p->num_slots);
 | 
						|
 | 
						|
    {
 | 
						|
	CK_SLOT_ID_PTR slot_ids;
 | 
						|
	int i, j;
 | 
						|
 | 
						|
	slot_ids = malloc(p->num_slots * sizeof(*slot_ids));
 | 
						|
	if (slot_ids == NULL) {
 | 
						|
	    ret = ENOMEM;
 | 
						|
	    goto out;
 | 
						|
	}
 | 
						|
 | 
						|
	ret = P11FUNC(p, GetSlotList, (FALSE, slot_ids, &p->num_slots));
 | 
						|
	if (ret) {
 | 
						|
	    free(slot_ids);
 | 
						|
	    ret = EINVAL;
 | 
						|
	    goto out;
 | 
						|
	}
 | 
						|
 | 
						|
	p->slots = calloc(p->num_slots, sizeof(p->slots[0]));
 | 
						|
	if (p->slots == NULL) {
 | 
						|
	    free(slot_ids);
 | 
						|
	    ret = ENOMEM;
 | 
						|
	    goto out;
 | 
						|
	}
 | 
						|
 | 
						|
	for (i = 0; i < p->num_slots; i++) {
 | 
						|
	    CK_SLOT_INFO slot_info;
 | 
						|
	    CK_TOKEN_INFO token_info;
 | 
						|
 | 
						|
	    printf("slot %d = id %d\n", i, (int)slot_ids[i]);
 | 
						|
 | 
						|
	    p->slots[i].id = slot_ids[i];
 | 
						|
 | 
						|
	    ret = P11FUNC(p, GetSlotInfo, (slot_ids[i], &slot_info));
 | 
						|
	    if (ret)
 | 
						|
		continue;
 | 
						|
 | 
						|
	    for (j = sizeof(slot_info.slotDescription) - 1; j > 0; j--) {
 | 
						|
		char c = slot_info.slotDescription[j];
 | 
						|
		if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\0')
 | 
						|
		    continue;
 | 
						|
		j++;
 | 
						|
		break;
 | 
						|
	    }
 | 
						|
 | 
						|
	    asprintf(&p->slots[i].name, "%.*s (slot %d)",
 | 
						|
		     j, slot_info.slotDescription, i);
 | 
						|
 | 
						|
	    printf("description: %s\n", p->slots[i].name);
 | 
						|
 | 
						|
	    printf("manufacturer: %.*s\n",
 | 
						|
		   (int)sizeof(slot_info.manufacturerID),
 | 
						|
		   slot_info.manufacturerID);
 | 
						|
 | 
						|
	    if ((slot_info.flags & CKF_TOKEN_PRESENT) == 0) {
 | 
						|
		printf("no token present\n");
 | 
						|
		continue;
 | 
						|
	    }
 | 
						|
 | 
						|
	    ret = P11FUNC(p, GetTokenInfo, (slot_ids[i], &token_info));
 | 
						|
	    if (ret)
 | 
						|
		continue;
 | 
						|
 | 
						|
	    printf("token present\n");
 | 
						|
 | 
						|
	    printf("label: %.*s\n",
 | 
						|
		   (int)sizeof(token_info.label),
 | 
						|
		   token_info.label);
 | 
						|
	    printf("manufacturer: %.*s\n",
 | 
						|
		   (int)sizeof(token_info.manufacturerID),
 | 
						|
		   token_info.manufacturerID);
 | 
						|
	    printf("model: %.*s\n",
 | 
						|
		   (int)sizeof(token_info.model),
 | 
						|
		   token_info.model);
 | 
						|
	    printf("serialNumber: %.*s\n",
 | 
						|
		   (int)sizeof(token_info.serialNumber),
 | 
						|
		   token_info.serialNumber);
 | 
						|
 | 
						|
	    printf("flags: 0x%04x\n", (unsigned int)token_info.flags);
 | 
						|
 | 
						|
	    printf("slotinfo.flags 0x%x & 0x%x = 0x%x\n",
 | 
						|
		   (int)slot_info.flags, (int)CKF_LOGIN_REQUIRED,
 | 
						|
		   (int)(slot_info.flags & CKF_LOGIN_REQUIRED));
 | 
						|
	    if (token_info.flags & CKF_LOGIN_REQUIRED) {
 | 
						|
		printf("login required\n");
 | 
						|
		p->slots[i].flags |= P11_LOGIN_REQ;
 | 
						|
	    }
 | 
						|
	}	
 | 
						|
    }
 | 
						|
 | 
						|
    *module = p;
 | 
						|
 | 
						|
    return 0;
 | 
						|
 out:    
 | 
						|
    if (p->slots)
 | 
						|
	free(p->slots);
 | 
						|
    if (p->handle)
 | 
						|
	dlclose(p->handle);
 | 
						|
    free(p);
 | 
						|
    return ret;
 | 
						|
    
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
p11_get_session(hx509_security_device module, const char *conf, int slot)
 | 
						|
{
 | 
						|
    CK_RV ret;
 | 
						|
 | 
						|
    module->selected_slot = slot;
 | 
						|
 | 
						|
    if (slot >= module->num_slots)
 | 
						|
	return EINVAL;
 | 
						|
 | 
						|
    if (module->slots[slot].flags & P11_SESSION)
 | 
						|
	return EINVAL; /* XXX */
 | 
						|
 | 
						|
    ret = P11FUNC(module, OpenSession, (module->slots[slot].id, 
 | 
						|
					CKF_SERIAL_SESSION,
 | 
						|
					NULL,
 | 
						|
					NULL,
 | 
						|
					&module->slots[slot].session));
 | 
						|
    if (ret != CKR_OK)
 | 
						|
	return EINVAL;
 | 
						|
    
 | 
						|
    module->slots[slot].flags |= P11_SESSION;
 | 
						|
    
 | 
						|
    if ((module->slots[slot].flags & P11_LOGIN_REQ) &&
 | 
						|
	(module->slots[slot].flags & P11_LOGIN_DONE) == 0) {
 | 
						|
	char pin[20];
 | 
						|
	char *prompt;
 | 
						|
 | 
						|
	module->slots[slot].flags |= P11_LOGIN_DONE;
 | 
						|
 | 
						|
	asprintf(&prompt, "PIN code for %s: ", module->slots[slot].name);
 | 
						|
 | 
						|
	if (UI_UTIL_read_pw_string(pin, sizeof(pin), prompt, 0)) {
 | 
						|
	    printf("no pin");
 | 
						|
	    goto out;
 | 
						|
	}
 | 
						|
	free(prompt);
 | 
						|
 | 
						|
	ret = P11FUNC(module, Login,
 | 
						|
		      (P11SESSION(module), CKU_USER, (unsigned char*)"3962", 4));
 | 
						|
	if (ret != CKR_OK)
 | 
						|
	    printf("login failed\n");
 | 
						|
	else
 | 
						|
	    module->slots[slot].pin = strdup(pin);
 | 
						|
    out:;
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
p11_put_session(hx509_security_device module, int slot)
 | 
						|
{
 | 
						|
    int ret;
 | 
						|
 | 
						|
    if (module->slots[slot].flags & P11_SESSION)
 | 
						|
	return EINVAL;
 | 
						|
    ret = P11FUNC(module, CloseSession, (module->slots[slot].session));
 | 
						|
    if (ret != CKR_OK)
 | 
						|
	return EINVAL;
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int
 | 
						|
iterate_entries(hx509_security_device module, hx509_certs ks,
 | 
						|
		CK_ATTRIBUTE *search_data, int num_search_data,
 | 
						|
		CK_ATTRIBUTE *query, int num_query,
 | 
						|
		int (*func)(void *, CK_ATTRIBUTE *, int), void *ptr)
 | 
						|
{
 | 
						|
    CK_OBJECT_HANDLE object;
 | 
						|
    CK_ULONG object_count;
 | 
						|
    int ret, i;
 | 
						|
 | 
						|
    printf("current slot: %d\n", module->selected_slot);
 | 
						|
    
 | 
						|
    ret = P11FUNC(module, FindObjectsInit,
 | 
						|
		  (P11SESSION(module), search_data, num_search_data));
 | 
						|
    if (ret != CKR_OK) {
 | 
						|
	return -1;
 | 
						|
    }
 | 
						|
    while (1) {
 | 
						|
	ret = P11FUNC(module, FindObjects, 
 | 
						|
		      (P11SESSION(module), &object, 1, &object_count));
 | 
						|
	if (ret != CKR_OK) {
 | 
						|
	    return -1;
 | 
						|
	}
 | 
						|
	printf("object count = %d\n", (int)object_count);
 | 
						|
	if (object_count == 0)
 | 
						|
	    break;
 | 
						|
	
 | 
						|
	for (i = 0; i < num_query; i++)
 | 
						|
	    query[i].pValue = NULL;
 | 
						|
 | 
						|
	ret = P11FUNC(module, GetAttributeValue, 
 | 
						|
		      (P11SESSION(module), object, query, num_query));
 | 
						|
	if (ret != CKR_OK) {
 | 
						|
	    return -1;
 | 
						|
	}
 | 
						|
	for (i = 0; i < num_query; i++) {
 | 
						|
	    printf("id %d len = %d\n", i, (int)query[i].ulValueLen);
 | 
						|
	    query[i].pValue = malloc(query[i].ulValueLen);
 | 
						|
	    if (query[i].pValue == NULL) {
 | 
						|
		ret = ENOMEM;
 | 
						|
		goto out;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	ret = P11FUNC(module, GetAttributeValue,
 | 
						|
		      (P11SESSION(module), object, query, num_query));
 | 
						|
	if (ret != CKR_OK) {
 | 
						|
	    ret = -1;
 | 
						|
	    goto out;
 | 
						|
	}
 | 
						|
	
 | 
						|
	ret = (*func)(ptr, query, num_query);
 | 
						|
	if (ret)
 | 
						|
	    goto out;
 | 
						|
 | 
						|
	for (i = 0; i < num_query; i++) {
 | 
						|
	    if (query[i].pValue)
 | 
						|
		free(query[i].pValue);
 | 
						|
	    query[i].pValue = NULL;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 out:
 | 
						|
 | 
						|
    for (i = 0; i < num_query; i++) {
 | 
						|
	if (query[i].pValue)
 | 
						|
	    free(query[i].pValue);
 | 
						|
	query[i].pValue = NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    ret = P11FUNC(module, FindObjectsFinal, (P11SESSION(module)));
 | 
						|
    if (ret != CKR_OK) {
 | 
						|
	return -2;
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
		
 | 
						|
static int
 | 
						|
print_id(void *ptr, CK_ATTRIBUTE *query, int num_query)
 | 
						|
{
 | 
						|
    printf("id: %.*s\n", (int)query[0].ulValueLen, (char *)query[0].pValue);
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
print_cert(void *ptr, CK_ATTRIBUTE *query, int num_query)
 | 
						|
{
 | 
						|
    hx509_validate_ctx ctx;
 | 
						|
    hx509_cert cert;
 | 
						|
    Certificate c;
 | 
						|
    int ret;
 | 
						|
 | 
						|
    printf("id: %d\n", (int)query[0].ulValueLen);
 | 
						|
 | 
						|
    memset(&c, 0, sizeof(c));
 | 
						|
    ret = decode_Certificate(query[1].pValue, query[1].ulValueLen,
 | 
						|
			     &c, NULL);
 | 
						|
    if (ret) {
 | 
						|
	printf("decode_Certificate failed with %d\n", ret);
 | 
						|
	return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    ret = hx509_cert_init(&c, &cert);
 | 
						|
    if (ret)
 | 
						|
	abort();
 | 
						|
    free_Certificate(&c);
 | 
						|
 | 
						|
    hx509_validate_ctx_init(&ctx);
 | 
						|
    hx509_validate_ctx_set_print(ctx, hx509_print_stdout, stdout);
 | 
						|
    hx509_validate_ctx_add_flags(ctx, HX509_VALIDATE_F_VERBOSE);
 | 
						|
 | 
						|
    hx509_validate_cert(ctx, cert);
 | 
						|
 | 
						|
    hx509_validate_ctx_free(ctx);
 | 
						|
    hx509_cert_free(cert);
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int
 | 
						|
p11_list_keys(hx509_security_device module, hx509_certs ks)
 | 
						|
{
 | 
						|
    CK_OBJECT_CLASS key_class;
 | 
						|
    CK_ATTRIBUTE search_data[] = {
 | 
						|
	{CKA_CLASS, &key_class, sizeof(key_class)},
 | 
						|
    };
 | 
						|
    CK_ATTRIBUTE query_data[2] = {
 | 
						|
	{CKA_ID, NULL, 0},
 | 
						|
	{CKA_VALUE, NULL, 0}
 | 
						|
    };
 | 
						|
    int ret;
 | 
						|
 | 
						|
    printf("---- private\n");
 | 
						|
    key_class = CKO_PRIVATE_KEY;
 | 
						|
    ret = iterate_entries(module, ks, search_data, 1,
 | 
						|
			  query_data, 1,
 | 
						|
			  print_id, NULL);
 | 
						|
    if (ret) {
 | 
						|
	return ret;
 | 
						|
    }
 | 
						|
 | 
						|
    printf("---- public\n");
 | 
						|
    key_class = CKO_PUBLIC_KEY;
 | 
						|
    ret = iterate_entries(module, ks, search_data, 1,
 | 
						|
			  query_data, 1,
 | 
						|
			  print_id, NULL);
 | 
						|
    if (ret) {
 | 
						|
	return ret;
 | 
						|
    }
 | 
						|
 | 
						|
    printf("---- cert\n");
 | 
						|
    key_class = CKO_CERTIFICATE;
 | 
						|
    ret = iterate_entries(module, ks, search_data, 1,
 | 
						|
			  query_data, 2,
 | 
						|
			  print_cert, NULL);
 | 
						|
    if (ret) {
 | 
						|
	return ret;
 | 
						|
    }
 | 
						|
    printf("----\n");
 | 
						|
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
security_device_add(hx509_security_device *device, const char *conf)
 | 
						|
{
 | 
						|
    hx509_security_device module;
 | 
						|
    char *c, *fn;
 | 
						|
    int ret;
 | 
						|
 | 
						|
    *device = NULL;
 | 
						|
 | 
						|
    c = strdup(conf);
 | 
						|
    if (c == NULL)
 | 
						|
	return ENOMEM;
 | 
						|
 | 
						|
    fn = strchr(c, ':');
 | 
						|
    if (fn)
 | 
						|
	*fn++ = '\0';
 | 
						|
    else
 | 
						|
	fn = "/usr/lib/default-pkcs11.so";
 | 
						|
 | 
						|
    if (strcasecmp(c, "PKCS11") != 0) {
 | 
						|
	free(c);
 | 
						|
	return EINVAL;
 | 
						|
    }
 | 
						|
 | 
						|
    ret = hx509_p11_load_module(fn, &module);
 | 
						|
    free(c);
 | 
						|
    if (ret)
 | 
						|
	return ret;
 | 
						|
 | 
						|
    *device = module;
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int
 | 
						|
hx509_keyset_init(const char *file, const char *conf)
 | 
						|
{
 | 
						|
    hx509_security_device module;
 | 
						|
    hx509_keyset ks;
 | 
						|
    int ret, slot;
 | 
						|
		  
 | 
						|
    ret = security_device_add(&module, file);
 | 
						|
    if (ret) {
 | 
						|
	printf("security_device_add: %d\n", ret);
 | 
						|
	return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    module->refcount++;
 | 
						|
 | 
						|
    ks = calloc(1, sizeof(*ks));
 | 
						|
    if (ks == NULL)
 | 
						|
	return ENOMEM;
 | 
						|
 | 
						|
    ks->device = module;
 | 
						|
 | 
						|
    ret = hx509_certs_init("MEMORY:pkcs-11-store", 0, NULL, &ks->certs);
 | 
						|
    if (ret)
 | 
						|
	goto out;
 | 
						|
 | 
						|
    /* 
 | 
						|
     * XXX just check if the device change changed, and if that case
 | 
						|
     * refresh contents of cache
 | 
						|
     */
 | 
						|
 | 
						|
    slot = 0;
 | 
						|
 | 
						|
    ret = p11_get_session(module, conf, slot);
 | 
						|
    if (ret)
 | 
						|
	goto out;
 | 
						|
 | 
						|
    /* fetch certificates and keys */
 | 
						|
    ret = p11_list_keys(module, ks->certs);
 | 
						|
    if (ret)
 | 
						|
	goto out_session;
 | 
						|
 | 
						|
 out_session:
 | 
						|
 | 
						|
    ret = p11_put_session(module, slot);
 | 
						|
 | 
						|
 out:
 | 
						|
    if (ret) {
 | 
						|
	hx509_certs_free(&ks->certs);
 | 
						|
	memset(ks, 0, sizeof(ks));
 | 
						|
	free(ks);
 | 
						|
	module->refcount--;
 | 
						|
    } else {
 | 
						|
	hx509_certs_iter(ks->certs, hx509_ci_print_names, stdout);
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 |