2002-01-16 22:49:03 +00:00
|
|
|
/*
|
|
|
|
* misc.c: Miscellaneous PKCS#11 library helper functions
|
|
|
|
*
|
2006-12-19 21:33:15 +00:00
|
|
|
* Copyright (C) 2002 Timo Teräs <timo.teras@iki.fi>
|
2002-01-16 22:49:03 +00:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
|
2002-03-20 19:33:52 +00:00
|
|
|
#include <stdlib.h>
|
2002-03-21 09:36:38 +00:00
|
|
|
#include <string.h>
|
2002-03-25 12:39:35 +00:00
|
|
|
#include "sc-pkcs11.h"
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2002-03-18 11:05:21 +00:00
|
|
|
#define DUMP_TEMPLATE_MAX 32
|
|
|
|
|
2005-01-19 18:15:43 +00:00
|
|
|
void strcpy_bp(u8 *dst, const char *src, size_t dstsize)
|
2002-01-16 22:49:03 +00:00
|
|
|
{
|
2005-01-19 18:15:43 +00:00
|
|
|
size_t c;
|
2004-03-29 20:34:30 +00:00
|
|
|
|
|
|
|
if (!dst || !src || !dstsize)
|
|
|
|
return;
|
|
|
|
|
|
|
|
memset((char *) dst, ' ', dstsize);
|
|
|
|
|
|
|
|
c = strlen(src) > dstsize ? dstsize : strlen(src);
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2002-01-17 12:05:44 +00:00
|
|
|
memcpy((char *) dst, src, c);
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CK_RV sc_to_cryptoki_error(int rc, int reader)
|
|
|
|
{
|
|
|
|
switch (rc) {
|
|
|
|
case SC_SUCCESS:
|
|
|
|
return CKR_OK;
|
|
|
|
case SC_ERROR_NOT_SUPPORTED:
|
|
|
|
return CKR_FUNCTION_NOT_SUPPORTED;
|
|
|
|
case SC_ERROR_OUT_OF_MEMORY:
|
|
|
|
return CKR_HOST_MEMORY;
|
|
|
|
case SC_ERROR_PIN_CODE_INCORRECT:
|
|
|
|
return CKR_PIN_INCORRECT;
|
2003-02-11 10:38:43 +00:00
|
|
|
case SC_ERROR_AUTH_METHOD_BLOCKED:
|
|
|
|
return CKR_PIN_LOCKED;
|
2002-01-16 22:49:03 +00:00
|
|
|
case SC_ERROR_BUFFER_TOO_SMALL:
|
|
|
|
return CKR_BUFFER_TOO_SMALL;
|
|
|
|
case SC_ERROR_CARD_NOT_PRESENT:
|
|
|
|
card_removed(reader);
|
|
|
|
return CKR_TOKEN_NOT_PRESENT;
|
|
|
|
case SC_ERROR_INVALID_CARD:
|
|
|
|
return CKR_TOKEN_NOT_RECOGNIZED;
|
2002-12-09 13:33:39 +00:00
|
|
|
case SC_ERROR_WRONG_LENGTH:
|
|
|
|
return CKR_DATA_LEN_RANGE;
|
2003-01-06 19:28:48 +00:00
|
|
|
case SC_ERROR_INVALID_PIN_LENGTH:
|
|
|
|
return CKR_PIN_LEN_RANGE;
|
2003-01-31 12:50:26 +00:00
|
|
|
case SC_ERROR_KEYPAD_CANCELLED:
|
2003-03-03 21:07:42 +00:00
|
|
|
case SC_ERROR_KEYPAD_TIMEOUT:
|
2003-01-31 12:50:26 +00:00
|
|
|
return CKR_FUNCTION_CANCELED;
|
2003-02-12 14:20:53 +00:00
|
|
|
case SC_ERROR_CARD_REMOVED:
|
|
|
|
return CKR_DEVICE_REMOVED;
|
2003-02-16 18:09:10 +00:00
|
|
|
case SC_ERROR_SECURITY_STATUS_NOT_SATISFIED:
|
|
|
|
return CKR_USER_NOT_LOGGED_IN;
|
2003-02-26 07:27:42 +00:00
|
|
|
case SC_ERROR_KEYPAD_PIN_MISMATCH:
|
|
|
|
return CKR_PIN_INVALID;
|
2003-07-17 22:59:12 +00:00
|
|
|
case SC_ERROR_INVALID_ARGUMENTS:
|
|
|
|
return CKR_ARGUMENTS_BAD;
|
2003-11-23 15:33:56 +00:00
|
|
|
case SC_ERROR_INVALID_DATA:
|
2005-03-26 20:00:14 +00:00
|
|
|
case SC_ERROR_INCORRECT_PARAMETERS:
|
2003-11-23 15:33:56 +00:00
|
|
|
return CKR_DATA_INVALID;
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
2003-08-25 14:21:18 +00:00
|
|
|
sc_debug(context, "opensc error: %s (%d)\n", sc_strerror(rc), rc);
|
2002-01-16 22:49:03 +00:00
|
|
|
return CKR_GENERAL_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Pool */
|
2002-11-22 09:10:10 +00:00
|
|
|
CK_RV pool_initialize(struct sc_pkcs11_pool *pool, int type)
|
2002-01-16 22:49:03 +00:00
|
|
|
{
|
2002-11-22 09:10:10 +00:00
|
|
|
pool->type = type;
|
2002-01-16 22:49:03 +00:00
|
|
|
pool->next_free_handle = 1;
|
|
|
|
pool->num_items = 0;
|
|
|
|
pool->head = pool->tail = NULL;
|
|
|
|
|
2005-01-19 18:15:43 +00:00
|
|
|
return CKR_OK;
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CK_RV pool_insert(struct sc_pkcs11_pool *pool, void *item_ptr, CK_ULONG_PTR pHandle)
|
|
|
|
{
|
|
|
|
struct sc_pkcs11_pool_item *item;
|
2005-01-19 18:15:43 +00:00
|
|
|
int handle = pool->next_free_handle++;
|
2002-01-16 22:49:03 +00:00
|
|
|
|
|
|
|
item = (struct sc_pkcs11_pool_item*) malloc(sizeof(struct sc_pkcs11_pool_item));
|
|
|
|
|
|
|
|
if (pHandle != NULL)
|
2005-01-19 18:15:43 +00:00
|
|
|
*pHandle = handle;
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2005-01-19 18:15:43 +00:00
|
|
|
item->handle = handle;
|
2002-01-16 22:49:03 +00:00
|
|
|
item->item = item_ptr;
|
|
|
|
item->next = NULL;
|
2005-01-19 18:15:43 +00:00
|
|
|
item->prev = pool->tail;
|
2002-01-16 22:49:03 +00:00
|
|
|
|
|
|
|
if (pool->head != NULL && pool->tail != NULL) {
|
|
|
|
pool->tail->next = item;
|
2005-01-19 18:15:43 +00:00
|
|
|
pool->tail = item;
|
2002-01-16 22:49:03 +00:00
|
|
|
} else
|
2005-01-19 18:15:43 +00:00
|
|
|
pool->head = pool->tail = item;
|
|
|
|
|
|
|
|
return CKR_OK;
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CK_RV pool_find(struct sc_pkcs11_pool *pool, CK_ULONG handle, void **item_ptr)
|
|
|
|
{
|
|
|
|
struct sc_pkcs11_pool_item *item;
|
|
|
|
|
|
|
|
if (context == NULL)
|
2005-01-19 18:15:43 +00:00
|
|
|
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
2002-01-16 22:49:03 +00:00
|
|
|
|
|
|
|
for (item = pool->head; item != NULL; item = item->next) {
|
|
|
|
if (item->handle == handle) {
|
|
|
|
*item_ptr = item->item;
|
2005-01-19 18:15:43 +00:00
|
|
|
return CKR_OK;
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-11-22 09:10:10 +00:00
|
|
|
return (pool->type == POOL_TYPE_OBJECT)? CKR_OBJECT_HANDLE_INVALID
|
|
|
|
: CKR_SESSION_HANDLE_INVALID;
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CK_RV pool_find_and_delete(struct sc_pkcs11_pool *pool, CK_ULONG handle, void **item_ptr)
|
|
|
|
{
|
|
|
|
struct sc_pkcs11_pool_item *item;
|
|
|
|
|
|
|
|
if (context == NULL)
|
|
|
|
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
|
|
|
|
|
|
for (item = pool->head; item != NULL; item = item->next) {
|
|
|
|
if (handle == 0 || item->handle == handle) {
|
|
|
|
if (item->prev) item->prev->next = item->next;
|
|
|
|
if (item->next) item->next->prev = item->prev;
|
|
|
|
if (pool->head == item) pool->head = item->next;
|
2005-02-11 20:09:34 +00:00
|
|
|
if (pool->tail == item) pool->tail = item->prev;
|
2002-01-16 22:49:03 +00:00
|
|
|
|
|
|
|
*item_ptr = item->item;
|
2005-01-19 18:15:43 +00:00
|
|
|
free(item);
|
2002-01-16 22:49:03 +00:00
|
|
|
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-11-22 09:10:10 +00:00
|
|
|
return (pool->type == POOL_TYPE_OBJECT)? CKR_OBJECT_HANDLE_INVALID
|
|
|
|
: CKR_SESSION_HANDLE_INVALID;
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Session manipulation */
|
2002-12-17 11:49:12 +00:00
|
|
|
CK_RV session_start_operation(struct sc_pkcs11_session *session,
|
|
|
|
int type,
|
|
|
|
sc_pkcs11_mechanism_type_t *mech,
|
|
|
|
struct sc_pkcs11_operation **operation)
|
2002-01-16 22:49:03 +00:00
|
|
|
{
|
2002-12-17 11:49:12 +00:00
|
|
|
sc_pkcs11_operation_t *op;
|
|
|
|
|
2002-01-16 22:49:03 +00:00
|
|
|
if (context == NULL)
|
2005-01-19 18:15:43 +00:00
|
|
|
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2002-12-17 11:49:12 +00:00
|
|
|
if (type < 0 || type >= SC_PKCS11_OPERATION_MAX)
|
|
|
|
return CKR_ARGUMENTS_BAD;
|
|
|
|
|
|
|
|
if (session->operation[type] != NULL)
|
2002-01-16 22:49:03 +00:00
|
|
|
return CKR_OPERATION_ACTIVE;
|
|
|
|
|
2002-12-17 11:49:12 +00:00
|
|
|
if (!(op = sc_pkcs11_new_operation(session, mech)))
|
|
|
|
return CKR_HOST_MEMORY;
|
|
|
|
|
|
|
|
session->operation[type] = op;
|
|
|
|
if (operation)
|
|
|
|
*operation = op;
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2005-01-19 18:15:43 +00:00
|
|
|
return CKR_OK;
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
|
2002-12-17 11:49:12 +00:00
|
|
|
CK_RV session_get_operation(struct sc_pkcs11_session *session, int type,
|
|
|
|
sc_pkcs11_operation_t **operation)
|
2002-01-16 22:49:03 +00:00
|
|
|
{
|
2002-12-17 11:49:12 +00:00
|
|
|
sc_pkcs11_operation_t *op;
|
|
|
|
|
|
|
|
if (type < 0 || type >= SC_PKCS11_OPERATION_MAX)
|
|
|
|
return CKR_ARGUMENTS_BAD;
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2002-12-17 11:49:12 +00:00
|
|
|
if (!(op = session->operation[type]))
|
2002-01-16 22:49:03 +00:00
|
|
|
return CKR_OPERATION_NOT_INITIALIZED;
|
|
|
|
|
2002-12-17 11:49:12 +00:00
|
|
|
if (operation)
|
|
|
|
*operation = op;
|
|
|
|
|
2005-01-19 18:15:43 +00:00
|
|
|
return CKR_OK;
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
|
2002-12-17 11:49:12 +00:00
|
|
|
CK_RV session_stop_operation(struct sc_pkcs11_session *session, int type)
|
2002-01-16 22:49:03 +00:00
|
|
|
{
|
2002-12-17 11:49:12 +00:00
|
|
|
if (type < 0 || type >= SC_PKCS11_OPERATION_MAX)
|
|
|
|
return CKR_ARGUMENTS_BAD;
|
|
|
|
|
|
|
|
if (session->operation[type] == NULL)
|
2002-01-16 22:49:03 +00:00
|
|
|
return CKR_OPERATION_NOT_INITIALIZED;
|
|
|
|
|
2002-12-17 11:49:12 +00:00
|
|
|
sc_pkcs11_release_operation(&session->operation[type]);
|
2005-01-19 18:15:43 +00:00
|
|
|
return CKR_OK;
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
2002-04-11 15:17:33 +00:00
|
|
|
|
|
|
|
CK_RV attr_extract(CK_ATTRIBUTE_PTR pAttr, void *ptr, size_t *sizep)
|
|
|
|
{
|
|
|
|
unsigned int size;
|
|
|
|
|
|
|
|
if (sizep) {
|
|
|
|
size = *sizep;
|
|
|
|
if (size < pAttr->ulValueLen)
|
|
|
|
return CKR_ATTRIBUTE_VALUE_INVALID;
|
|
|
|
*sizep = pAttr->ulValueLen;
|
|
|
|
} else {
|
|
|
|
switch (pAttr->type) {
|
|
|
|
case CKA_CLASS:
|
|
|
|
size = sizeof(CK_OBJECT_CLASS); break;
|
|
|
|
case CKA_KEY_TYPE:
|
|
|
|
size = sizeof(CK_KEY_TYPE); break;
|
2002-04-13 19:00:37 +00:00
|
|
|
case CKA_PRIVATE:
|
|
|
|
size = sizeof(CK_BBOOL); break;
|
2003-06-04 12:24:19 +00:00
|
|
|
case CKA_CERTIFICATE_TYPE:
|
|
|
|
size = sizeof(CKA_CERTIFICATE_TYPE); break;
|
2003-11-12 18:28:03 +00:00
|
|
|
case CKA_MODULUS_BITS:
|
|
|
|
size = sizeof(CK_ULONG); break;
|
2007-06-21 09:37:18 +00:00
|
|
|
case CKA_OBJECT_ID:
|
|
|
|
size = sizeof(struct sc_object_id); break;
|
2002-04-11 15:17:33 +00:00
|
|
|
default:
|
|
|
|
return CKR_FUNCTION_FAILED;
|
|
|
|
}
|
|
|
|
if (size != pAttr->ulValueLen)
|
|
|
|
return CKR_ATTRIBUTE_VALUE_INVALID;
|
|
|
|
}
|
|
|
|
memcpy(ptr, pAttr->pValue, pAttr->ulValueLen);
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
CK_RV attr_find(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
|
|
|
|
CK_ULONG type, void *ptr, size_t *sizep)
|
|
|
|
{
|
|
|
|
unsigned int n;
|
|
|
|
|
|
|
|
for (n = 0; n < ulCount; n++, pTemplate++) {
|
|
|
|
if (pTemplate->type == type)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (n >= ulCount)
|
|
|
|
return CKR_TEMPLATE_INCOMPLETE;
|
|
|
|
return attr_extract(pTemplate, ptr, sizep);
|
|
|
|
}
|
|
|
|
|
2003-06-03 13:57:52 +00:00
|
|
|
CK_RV attr_find2(CK_ATTRIBUTE_PTR pTemp1, CK_ULONG ulCount1,
|
|
|
|
CK_ATTRIBUTE_PTR pTemp2, CK_ULONG ulCount2,
|
|
|
|
CK_ULONG type, void *ptr, size_t *sizep)
|
|
|
|
{
|
|
|
|
CK_RV rv;
|
|
|
|
|
|
|
|
rv = attr_find(pTemp1, ulCount1, type, ptr, sizep);
|
|
|
|
if (rv != CKR_OK)
|
|
|
|
rv = attr_find(pTemp2, ulCount2, type, ptr, sizep);
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2002-04-11 15:17:33 +00:00
|
|
|
CK_RV attr_find_ptr(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
|
|
|
|
CK_ULONG type, void **ptr, size_t *sizep)
|
|
|
|
{
|
|
|
|
unsigned int n;
|
|
|
|
|
|
|
|
for (n = 0; n < ulCount; n++, pTemplate++) {
|
|
|
|
if (pTemplate->type == type)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (n >= ulCount)
|
|
|
|
return CKR_TEMPLATE_INCOMPLETE;
|
|
|
|
|
|
|
|
if (sizep)
|
|
|
|
*sizep = pTemplate->ulValueLen;
|
|
|
|
*ptr = pTemplate->pValue;
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
CK_RV attr_find_var(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
|
|
|
|
CK_ULONG type, void *ptr, size_t *sizep)
|
|
|
|
{
|
|
|
|
unsigned int n;
|
|
|
|
|
|
|
|
for (n = 0; n < ulCount; n++, pTemplate++) {
|
|
|
|
if (pTemplate->type == type)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (n >= ulCount)
|
|
|
|
return CKR_TEMPLATE_INCOMPLETE;
|
|
|
|
|
|
|
|
return attr_extract(pTemplate, ptr, sizep);
|
|
|
|
}
|
|
|
|
|
2005-03-09 00:04:44 +00:00
|
|
|
void load_pkcs11_parameters(struct sc_pkcs11_config *conf, sc_context_t *ctx)
|
2002-12-21 16:45:37 +00:00
|
|
|
{
|
|
|
|
scconf_block *conf_block = NULL, **blocks;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* Set defaults */
|
2008-03-06 15:04:29 +00:00
|
|
|
conf->pkcs11_max_virtual_slots = SC_PKCS11_DEF_MAX_VIRTUAL_SLOTS;
|
2003-01-13 21:38:43 +00:00
|
|
|
conf->num_slots = SC_PKCS11_DEF_SLOTS_PER_CARD;
|
|
|
|
conf->hide_empty_tokens = 0;
|
2006-06-21 20:05:17 +00:00
|
|
|
conf->lock_login = 0;
|
2007-04-24 07:54:18 +00:00
|
|
|
conf->cache_pins = 1;
|
2003-06-03 13:57:52 +00:00
|
|
|
conf->soft_keygen_allowed = 1;
|
2002-12-21 16:45:37 +00:00
|
|
|
|
|
|
|
for (i = 0; ctx->conf_blocks[i] != NULL; i++) {
|
|
|
|
blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[i],
|
|
|
|
"pkcs11", NULL);
|
|
|
|
conf_block = blocks[0];
|
|
|
|
free(blocks);
|
|
|
|
if (conf_block != NULL)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!conf_block)
|
|
|
|
return;
|
|
|
|
|
2008-03-06 15:04:29 +00:00
|
|
|
conf->pkcs11_max_virtual_slots = scconf_get_int(conf_block, "max_virtual_slots", conf->pkcs11_max_virtual_slots);
|
2002-12-21 16:45:37 +00:00
|
|
|
conf->num_slots = scconf_get_int(conf_block, "num_slots", conf->num_slots);
|
2003-01-13 21:38:43 +00:00
|
|
|
conf->hide_empty_tokens = scconf_get_bool(conf_block, "hide_empty_tokens", 0);
|
2006-06-21 20:05:17 +00:00
|
|
|
conf->lock_login = scconf_get_bool(conf_block, "lock_login", 0);
|
2007-04-24 07:54:18 +00:00
|
|
|
conf->cache_pins = scconf_get_bool(conf_block, "cache_pins", 1);
|
2003-06-03 13:57:52 +00:00
|
|
|
conf->soft_keygen_allowed = scconf_get_bool(conf_block, "soft_keygen_allowed", 1);
|
2002-12-21 16:45:37 +00:00
|
|
|
}
|