2002-01-16 22:49:03 +00:00
|
|
|
/*
|
|
|
|
* framework-pkcs15.c: PKCS#15 framework and related objects
|
|
|
|
*
|
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
|
|
|
|
*/
|
|
|
|
|
2010-03-04 08:14:36 +00:00
|
|
|
#include "config.h"
|
2011-05-29 18:35:34 +00:00
|
|
|
#include "libopensc/log.h"
|
2010-03-04 08:14:36 +00:00
|
|
|
|
2002-03-20 19:33:52 +00:00
|
|
|
#include <stdlib.h>
|
2002-01-16 22:49:03 +00:00
|
|
|
#include <string.h>
|
2010-03-04 08:14:36 +00:00
|
|
|
|
2002-01-16 22:49:03 +00:00
|
|
|
#include "sc-pkcs11.h"
|
2002-06-20 13:16:22 +00:00
|
|
|
#ifdef USE_PKCS15_INIT
|
2010-03-04 08:14:36 +00:00
|
|
|
#include "pkcs15init/pkcs15-init.h"
|
2002-06-20 13:16:22 +00:00
|
|
|
#endif
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2007-03-29 10:25:16 +00:00
|
|
|
extern int hack_enabled;
|
|
|
|
|
2002-04-11 15:17:33 +00:00
|
|
|
struct pkcs15_slot_data {
|
|
|
|
struct sc_pkcs15_object *auth_obj;
|
|
|
|
};
|
2003-11-26 13:12:26 +00:00
|
|
|
#define slot_data(p) ((struct pkcs15_slot_data *) (p))
|
2010-03-10 09:23:01 +00:00
|
|
|
#define slot_data_auth(p) (((p) && slot_data(p)) ? slot_data(p)->auth_obj : NULL)
|
2003-11-26 13:12:26 +00:00
|
|
|
#define slot_data_pin_info(p) (((p) && slot_data_auth(p))? \
|
2002-04-11 15:17:33 +00:00
|
|
|
(struct sc_pkcs15_pin_info *) slot_data_auth(p)->data : NULL)
|
|
|
|
|
2002-01-16 22:49:03 +00:00
|
|
|
#define check_attribute_buffer(attr,size) \
|
|
|
|
if (attr->pValue == NULL_PTR) { \
|
|
|
|
attr->ulValueLen = size; \
|
|
|
|
return CKR_OK; \
|
|
|
|
} \
|
|
|
|
if (attr->ulValueLen < size) { \
|
|
|
|
attr->ulValueLen = size; \
|
|
|
|
return CKR_BUFFER_TOO_SMALL; \
|
|
|
|
} \
|
2005-02-11 20:09:34 +00:00
|
|
|
attr->ulValueLen = size;
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2003-02-23 17:50:33 +00:00
|
|
|
#define MAX_OBJECTS 64
|
|
|
|
struct pkcs15_fw_data {
|
|
|
|
struct sc_pkcs15_card * p15_card;
|
|
|
|
struct pkcs15_any_object * objects[MAX_OBJECTS];
|
|
|
|
unsigned int num_objects;
|
2003-06-24 11:26:17 +00:00
|
|
|
unsigned int locked;
|
2010-01-08 15:41:07 +00:00
|
|
|
unsigned char user_puk[64];
|
|
|
|
unsigned int user_puk_len;
|
2003-02-23 17:50:33 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct pkcs15_any_object {
|
|
|
|
struct sc_pkcs11_object base;
|
|
|
|
unsigned int refcount;
|
|
|
|
size_t size;
|
|
|
|
struct sc_pkcs15_object * p15_object;
|
|
|
|
struct pkcs15_pubkey_object * related_pubkey;
|
|
|
|
struct pkcs15_cert_object * related_cert;
|
2003-04-17 12:38:08 +00:00
|
|
|
struct pkcs15_prkey_object * related_privkey;
|
2003-02-23 17:50:33 +00:00
|
|
|
};
|
2002-01-16 22:49:03 +00:00
|
|
|
|
|
|
|
struct pkcs15_cert_object {
|
2003-02-23 17:50:33 +00:00
|
|
|
struct pkcs15_any_object base;
|
2002-03-03 17:36:23 +00:00
|
|
|
|
2003-02-23 17:50:33 +00:00
|
|
|
struct sc_pkcs15_cert_info * cert_info;
|
2005-01-19 18:15:43 +00:00
|
|
|
struct sc_pkcs15_cert * cert_data;
|
2002-01-16 22:49:03 +00:00
|
|
|
};
|
2003-02-23 17:50:33 +00:00
|
|
|
#define cert_flags base.base.flags
|
|
|
|
#define cert_p15obj base.p15_object
|
|
|
|
#define cert_pubkey base.related_pubkey
|
|
|
|
#define cert_issuer base.related_cert
|
2009-10-22 09:18:16 +00:00
|
|
|
#define cert_prvkey base.related_privkey
|
2002-01-16 22:49:03 +00:00
|
|
|
|
|
|
|
struct pkcs15_prkey_object {
|
2003-02-23 17:50:33 +00:00
|
|
|
struct pkcs15_any_object base;
|
2002-03-03 17:36:23 +00:00
|
|
|
|
2003-02-23 17:50:33 +00:00
|
|
|
struct sc_pkcs15_prkey_info * prv_info;
|
2002-01-16 22:49:03 +00:00
|
|
|
};
|
2003-02-23 17:50:33 +00:00
|
|
|
#define prv_flags base.base.flags
|
|
|
|
#define prv_p15obj base.p15_object
|
|
|
|
#define prv_pubkey base.related_pubkey
|
2003-04-17 12:38:08 +00:00
|
|
|
#define prv_next base.related_privkey
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2003-02-23 17:50:33 +00:00
|
|
|
struct pkcs15_pubkey_object {
|
|
|
|
struct pkcs15_any_object base;
|
2002-03-03 17:36:23 +00:00
|
|
|
|
2003-02-23 17:50:33 +00:00
|
|
|
struct sc_pkcs15_pubkey_info * pub_info; /* NULL for key extracted from cert */
|
|
|
|
struct sc_pkcs15_pubkey * pub_data;
|
2002-01-24 16:27:09 +00:00
|
|
|
};
|
2003-02-23 17:50:33 +00:00
|
|
|
#define pub_flags base.base.flags
|
|
|
|
#define pub_p15obj base.p15_object
|
2009-10-22 09:18:16 +00:00
|
|
|
#define pub_genfrom base.related_cert
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2005-09-07 09:32:52 +00:00
|
|
|
#define __p15_type(obj) (((obj) && (obj)->p15_object)? ((obj)->p15_object->type) : (unsigned int)-1)
|
2010-12-01 20:08:42 +00:00
|
|
|
#define is_privkey(obj) ((__p15_type(obj) & SC_PKCS15_TYPE_CLASS_MASK) == SC_PKCS15_TYPE_PRKEY)
|
|
|
|
#define is_pubkey(obj) ((__p15_type(obj) & SC_PKCS15_TYPE_CLASS_MASK) == SC_PKCS15_TYPE_PUBKEY)
|
2003-02-23 17:50:33 +00:00
|
|
|
#define is_cert(obj) (__p15_type(obj) == SC_PKCS15_TYPE_CERT_X509)
|
2002-03-12 14:36:40 +00:00
|
|
|
|
2004-07-26 18:47:23 +00:00
|
|
|
struct pkcs15_data_object {
|
|
|
|
struct pkcs15_any_object base;
|
|
|
|
|
|
|
|
struct sc_pkcs15_data_info *info;
|
2005-01-19 18:15:43 +00:00
|
|
|
struct sc_pkcs15_data *value;
|
2004-07-26 18:47:23 +00:00
|
|
|
};
|
|
|
|
#define data_flags base.base.flags
|
|
|
|
#define data_p15obj base.p15_object
|
|
|
|
#define is_data(obj) (__p15_type(obj) == SC_PKCS15_TYPE_DATA_OBJECT)
|
|
|
|
|
2003-02-23 17:50:33 +00:00
|
|
|
extern struct sc_pkcs11_object_ops pkcs15_cert_ops;
|
|
|
|
extern struct sc_pkcs11_object_ops pkcs15_prkey_ops;
|
|
|
|
extern struct sc_pkcs11_object_ops pkcs15_pubkey_ops;
|
2004-07-26 18:47:23 +00:00
|
|
|
extern struct sc_pkcs11_object_ops pkcs15_dobj_ops;
|
2002-03-12 14:36:40 +00:00
|
|
|
|
2009-10-05 20:10:07 +00:00
|
|
|
#define GOST_PARAMS_OID_SIZE 9
|
|
|
|
static const struct {
|
|
|
|
const CK_BYTE oid[GOST_PARAMS_OID_SIZE];
|
|
|
|
unsigned char param;
|
|
|
|
} gostr3410_param_oid [] = {
|
|
|
|
{ { 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x23, 0x01 },
|
|
|
|
SC_PKCS15_PARAMSET_GOSTR3410_A },
|
|
|
|
{ { 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x23, 0x02 },
|
|
|
|
SC_PKCS15_PARAMSET_GOSTR3410_B },
|
|
|
|
{ { 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x23, 0x03 },
|
|
|
|
SC_PKCS15_PARAMSET_GOSTR3410_C }
|
|
|
|
};
|
2003-02-23 17:50:33 +00:00
|
|
|
|
|
|
|
static int __pkcs15_release_object(struct pkcs15_any_object *);
|
2010-12-17 17:12:22 +00:00
|
|
|
static CK_RV register_mechanisms(struct sc_pkcs11_card *p11card);
|
2002-12-18 19:26:18 +00:00
|
|
|
static CK_RV get_public_exponent(struct sc_pkcs15_pubkey *,
|
2002-03-12 14:36:40 +00:00
|
|
|
CK_ATTRIBUTE_PTR);
|
2002-12-18 19:26:18 +00:00
|
|
|
static CK_RV get_modulus(struct sc_pkcs15_pubkey *,
|
2002-03-12 14:36:40 +00:00
|
|
|
CK_ATTRIBUTE_PTR);
|
2002-12-18 19:26:18 +00:00
|
|
|
static CK_RV get_modulus_bits(struct sc_pkcs15_pubkey *,
|
2002-03-12 14:36:40 +00:00
|
|
|
CK_ATTRIBUTE_PTR);
|
2002-12-18 19:26:18 +00:00
|
|
|
static CK_RV get_usage_bit(unsigned int usage, CK_ATTRIBUTE_PTR attr);
|
|
|
|
static CK_RV asn1_sequence_wrapper(const u8 *, size_t, CK_ATTRIBUTE_PTR);
|
2009-10-05 20:10:07 +00:00
|
|
|
static CK_RV get_gostr3410_params(const u8 *, size_t, CK_ATTRIBUTE_PTR);
|
2010-12-01 20:08:42 +00:00
|
|
|
static CK_RV get_ec_pubkey_point(struct sc_pkcs15_pubkey *, CK_ATTRIBUTE_PTR);
|
|
|
|
static CK_RV get_ec_pubkey_params(struct sc_pkcs15_pubkey *, CK_ATTRIBUTE_PTR);
|
2003-06-24 11:26:17 +00:00
|
|
|
static int lock_card(struct pkcs15_fw_data *);
|
|
|
|
static int unlock_card(struct pkcs15_fw_data *);
|
2005-02-01 19:02:15 +00:00
|
|
|
static int reselect_app_df(sc_pkcs15_card_t *p15card);
|
2002-03-12 14:36:40 +00:00
|
|
|
|
2011-05-29 18:35:34 +00:00
|
|
|
static CK_RV set_gost_params(struct sc_pkcs15init_keyarg_gost_params *,
|
|
|
|
struct sc_pkcs15init_keyarg_gost_params *,
|
|
|
|
CK_ATTRIBUTE_PTR, CK_ULONG, CK_ATTRIBUTE_PTR, CK_ULONG);
|
2002-01-16 22:49:03 +00:00
|
|
|
/* PKCS#15 Framework */
|
|
|
|
|
|
|
|
static CK_RV pkcs15_bind(struct sc_pkcs11_card *p11card)
|
|
|
|
{
|
2003-02-23 17:50:33 +00:00
|
|
|
struct pkcs15_fw_data *fw_data;
|
|
|
|
int rc;
|
2010-12-17 17:12:22 +00:00
|
|
|
CK_RV rv;
|
2003-02-23 17:50:33 +00:00
|
|
|
|
Do not cast the return value of malloc(3) and calloc(3)
From http://en.wikipedia.org/wiki/Malloc#Casting_and_type_safety
" Casting and type safety
malloc returns a void pointer (void *), which indicates that it is a
pointer to a region of unknown data type. One may "cast" (see type
conversion) this pointer to a specific type, as in
int *ptr = (int*)malloc(10 * sizeof (int));
When using C, this is considered bad practice; it is redundant under the
C standard. Moreover, putting in a cast may mask failure to include the
header stdlib.h, in which the prototype for malloc is found. In the
absence of a prototype for malloc, the C compiler will assume that
malloc returns an int, and will issue a warning in a context such as the
above, provided the error is not masked by a cast. On certain
architectures and data models (such as LP64 on 64 bit systems, where
long and pointers are 64 bit and int is 32 bit), this error can actually
result in undefined behavior, as the implicitly declared malloc returns
a 32 bit value whereas the actually defined function returns a 64 bit
value. Depending on calling conventions and memory layout, this may
result in stack smashing.
The returned pointer need not be explicitly cast to a more specific
pointer type, since ANSI C defines an implicit conversion between the
void pointer type and other pointers to objects. An explicit cast of
malloc's return value is sometimes performed because malloc originally
returned a char *, but this cast is unnecessary in standard C
code.[4][5] Omitting the cast, however, creates an incompatibility with
C++, which does require it.
The lack of a specific pointer type returned from malloc is type-unsafe
behaviour: malloc allocates based on byte count but not on type. This
distinguishes it from the C++ new operator that returns a pointer whose
type relies on the operand. (see C Type Safety). "
See also
http://www.opensc-project.org/pipermail/opensc-devel/2010-August/014586.html
git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@4636 c6295689-39f2-0310-b995-f0e70906c6a9
2010-08-18 15:08:51 +00:00
|
|
|
if (!(fw_data = calloc(1, sizeof(*fw_data))))
|
2003-02-23 17:50:33 +00:00
|
|
|
return CKR_HOST_MEMORY;
|
|
|
|
p11card->fw_data = fw_data;
|
|
|
|
|
2011-01-05 14:21:04 +00:00
|
|
|
rc = sc_pkcs15_bind(p11card->card, NULL, &fw_data->p15_card);
|
2010-12-16 03:56:49 +00:00
|
|
|
if (rc != SC_SUCCESS) {
|
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "sc_pkcs15_bind failed: %d", rc);
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rc, NULL);
|
2010-12-16 03:56:49 +00:00
|
|
|
}
|
|
|
|
|
2010-12-17 17:54:07 +00:00
|
|
|
rv = register_mechanisms(p11card);
|
|
|
|
if (rv != CKR_OK) {
|
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "register_mechanisms failed: 0x%x", rv);
|
|
|
|
return rv;
|
2010-12-16 03:56:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return CKR_OK;
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static CK_RV pkcs15_unbind(struct sc_pkcs11_card *p11card)
|
|
|
|
{
|
2005-01-19 18:15:43 +00:00
|
|
|
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) p11card->fw_data;
|
2003-02-23 17:50:33 +00:00
|
|
|
unsigned int i;
|
|
|
|
int rc;
|
|
|
|
|
2004-12-12 19:13:17 +00:00
|
|
|
for (i = 0; i < fw_data->num_objects; i++) {
|
|
|
|
struct pkcs15_any_object *obj = fw_data->objects[i];
|
|
|
|
|
|
|
|
/* use object specific release method if existing */
|
|
|
|
if (obj->base.ops && obj->base.ops->release)
|
|
|
|
obj->base.ops->release(obj);
|
|
|
|
else
|
|
|
|
__pkcs15_release_object(obj);
|
|
|
|
}
|
2003-02-23 17:50:33 +00:00
|
|
|
|
2003-06-24 11:26:17 +00:00
|
|
|
unlock_card(fw_data);
|
|
|
|
|
2003-02-23 17:50:33 +00:00
|
|
|
rc = sc_pkcs15_unbind(fw_data->p15_card);
|
2009-11-05 18:27:56 +00:00
|
|
|
free(fw_data);
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rc, NULL);
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
|
2010-03-08 12:32:35 +00:00
|
|
|
static void pkcs15_init_token_info(struct sc_pkcs15_card *p15card, CK_TOKEN_INFO_PTR pToken)
|
2002-01-16 22:49:03 +00:00
|
|
|
{
|
2010-10-05 15:44:58 +00:00
|
|
|
strcpy_bp(pToken->manufacturerID, p15card->tokeninfo->manufacturer_id, 32);
|
2010-03-08 12:32:35 +00:00
|
|
|
if (p15card->flags & SC_PKCS15_CARD_FLAG_EMULATED)
|
2009-01-29 11:50:21 +00:00
|
|
|
strcpy_bp(pToken->model, "PKCS#15 emulated", 16);
|
|
|
|
else
|
|
|
|
strcpy_bp(pToken->model, "PKCS#15", 16);
|
2004-02-02 10:24:31 +00:00
|
|
|
|
|
|
|
/* Take the last 16 chars of the serial number (if the are more
|
|
|
|
* than 16).
|
|
|
|
* _Assuming_ that the serial number is a Big Endian counter, this
|
|
|
|
* will assure that the serial within each type of card will be
|
|
|
|
* unique in pkcs11 (at least for the first 8^16 cards :-) */
|
2010-10-05 15:44:58 +00:00
|
|
|
if (p15card->tokeninfo->serial_number != NULL) {
|
|
|
|
int sn_start = strlen(p15card->tokeninfo->serial_number) - 16;
|
2004-02-02 10:24:31 +00:00
|
|
|
|
|
|
|
if (sn_start < 0)
|
|
|
|
sn_start = 0;
|
2010-10-05 15:44:58 +00:00
|
|
|
strcpy_bp(pToken->serialNumber, p15card->tokeninfo->serial_number + sn_start, 16);
|
2004-02-02 10:24:31 +00:00
|
|
|
}
|
|
|
|
|
2002-01-16 22:49:03 +00:00
|
|
|
pToken->ulMaxSessionCount = CK_EFFECTIVELY_INFINITE;
|
|
|
|
pToken->ulSessionCount = 0; /* FIXME */
|
|
|
|
pToken->ulMaxRwSessionCount = CK_EFFECTIVELY_INFINITE;
|
|
|
|
pToken->ulRwSessionCount = 0; /* FIXME */
|
|
|
|
pToken->ulTotalPublicMemory = CK_UNAVAILABLE_INFORMATION;
|
|
|
|
pToken->ulFreePublicMemory = CK_UNAVAILABLE_INFORMATION;
|
|
|
|
pToken->ulTotalPrivateMemory = CK_UNAVAILABLE_INFORMATION;
|
|
|
|
pToken->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION;
|
2009-01-19 12:06:38 +00:00
|
|
|
pToken->hardwareVersion.major = 0;
|
2002-01-16 22:49:03 +00:00
|
|
|
pToken->hardwareVersion.minor = 0;
|
2009-01-19 12:06:38 +00:00
|
|
|
pToken->firmwareVersion.major = 0;
|
2002-01-16 22:49:03 +00:00
|
|
|
pToken->firmwareVersion.minor = 0;
|
|
|
|
}
|
|
|
|
|
2010-12-17 17:54:07 +00:00
|
|
|
#ifdef USE_PKCS15_INIT
|
2010-04-15 15:37:55 +00:00
|
|
|
static char *
|
|
|
|
set_cka_label(CK_ATTRIBUTE_PTR attr, char *label)
|
|
|
|
{
|
|
|
|
char *l = (char *)attr->pValue;
|
|
|
|
int len = attr->ulValueLen;
|
|
|
|
|
|
|
|
if (len >= SC_PKCS15_MAX_LABEL_SIZE)
|
|
|
|
len = SC_PKCS15_MAX_LABEL_SIZE-1;
|
|
|
|
memcpy(label, l, len);
|
|
|
|
label[len] = '\0';
|
|
|
|
return label;
|
|
|
|
}
|
2010-12-17 17:54:07 +00:00
|
|
|
#endif
|
2010-04-15 15:37:55 +00:00
|
|
|
|
2003-02-23 17:50:33 +00:00
|
|
|
static int
|
|
|
|
__pkcs15_create_object(struct pkcs15_fw_data *fw_data,
|
|
|
|
struct pkcs15_any_object **result,
|
|
|
|
struct sc_pkcs15_object *p15_object,
|
|
|
|
struct sc_pkcs11_object_ops *ops,
|
|
|
|
size_t size)
|
|
|
|
{
|
|
|
|
struct pkcs15_any_object *obj;
|
|
|
|
|
|
|
|
if (fw_data->num_objects >= MAX_OBJECTS)
|
|
|
|
return SC_ERROR_TOO_MANY_OBJECTS;
|
|
|
|
|
Do not cast the return value of malloc(3) and calloc(3)
From http://en.wikipedia.org/wiki/Malloc#Casting_and_type_safety
" Casting and type safety
malloc returns a void pointer (void *), which indicates that it is a
pointer to a region of unknown data type. One may "cast" (see type
conversion) this pointer to a specific type, as in
int *ptr = (int*)malloc(10 * sizeof (int));
When using C, this is considered bad practice; it is redundant under the
C standard. Moreover, putting in a cast may mask failure to include the
header stdlib.h, in which the prototype for malloc is found. In the
absence of a prototype for malloc, the C compiler will assume that
malloc returns an int, and will issue a warning in a context such as the
above, provided the error is not masked by a cast. On certain
architectures and data models (such as LP64 on 64 bit systems, where
long and pointers are 64 bit and int is 32 bit), this error can actually
result in undefined behavior, as the implicitly declared malloc returns
a 32 bit value whereas the actually defined function returns a 64 bit
value. Depending on calling conventions and memory layout, this may
result in stack smashing.
The returned pointer need not be explicitly cast to a more specific
pointer type, since ANSI C defines an implicit conversion between the
void pointer type and other pointers to objects. An explicit cast of
malloc's return value is sometimes performed because malloc originally
returned a char *, but this cast is unnecessary in standard C
code.[4][5] Omitting the cast, however, creates an incompatibility with
C++, which does require it.
The lack of a specific pointer type returned from malloc is type-unsafe
behaviour: malloc allocates based on byte count but not on type. This
distinguishes it from the C++ new operator that returns a pointer whose
type relies on the operand. (see C Type Safety). "
See also
http://www.opensc-project.org/pipermail/opensc-devel/2010-August/014586.html
git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@4636 c6295689-39f2-0310-b995-f0e70906c6a9
2010-08-18 15:08:51 +00:00
|
|
|
if (!(obj = calloc(1, size)))
|
2003-02-23 17:50:33 +00:00
|
|
|
return SC_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
|
|
|
fw_data->objects[fw_data->num_objects++] = obj;
|
|
|
|
|
|
|
|
obj->base.ops = ops;
|
|
|
|
obj->p15_object = p15_object;
|
|
|
|
obj->refcount = 1;
|
|
|
|
obj->size = size;
|
|
|
|
|
|
|
|
*result = obj;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
__pkcs15_release_object(struct pkcs15_any_object *obj)
|
|
|
|
{
|
|
|
|
if (--(obj->refcount) != 0)
|
|
|
|
return obj->refcount;
|
|
|
|
|
2005-09-17 10:44:45 +00:00
|
|
|
sc_mem_clear(obj, obj->size);
|
2003-02-23 17:50:33 +00:00
|
|
|
free(obj);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-12-17 17:54:07 +00:00
|
|
|
#ifdef USE_PKCS15_INIT
|
2009-11-05 18:27:56 +00:00
|
|
|
static int
|
|
|
|
__pkcs15_delete_object(struct pkcs15_fw_data *fw_data, struct pkcs15_any_object *obj)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
if (fw_data->num_objects == 0)
|
|
|
|
return SC_ERROR_INTERNAL;
|
|
|
|
|
|
|
|
for (i = 0; i < fw_data->num_objects; ++i)
|
|
|
|
if (fw_data->objects[i] == obj) {
|
|
|
|
fw_data->objects[i] = fw_data->objects[--fw_data->num_objects];
|
|
|
|
if (__pkcs15_release_object(obj) > 0)
|
|
|
|
return SC_ERROR_INTERNAL;
|
|
|
|
return SC_SUCCESS;
|
|
|
|
}
|
|
|
|
return SC_ERROR_OBJECT_NOT_FOUND;
|
|
|
|
}
|
2010-12-17 17:54:07 +00:00
|
|
|
#endif
|
2009-11-05 18:27:56 +00:00
|
|
|
|
2010-09-05 16:53:08 +00:00
|
|
|
CK_RV C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
|
2010-09-02 09:19:27 +00:00
|
|
|
{
|
2010-09-05 16:53:08 +00:00
|
|
|
struct sc_pkcs11_slot *slot;
|
|
|
|
struct sc_pkcs15_object *auth;
|
2010-09-02 09:19:27 +00:00
|
|
|
struct sc_pkcs15_pin_info *pin_info;
|
2010-09-05 16:53:08 +00:00
|
|
|
struct sc_pin_cmd_data data;
|
|
|
|
int r;
|
|
|
|
CK_RV rv;
|
2010-09-02 09:19:27 +00:00
|
|
|
|
2010-09-05 16:53:08 +00:00
|
|
|
if (pInfo == NULL_PTR)
|
|
|
|
return CKR_ARGUMENTS_BAD;
|
2010-09-02 09:19:27 +00:00
|
|
|
|
2010-09-05 16:53:08 +00:00
|
|
|
rv = sc_pkcs11_lock();
|
|
|
|
if (rv != CKR_OK)
|
|
|
|
return rv;
|
2010-09-02 09:19:27 +00:00
|
|
|
|
2010-09-05 16:53:08 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "C_GetTokenInfo(%lx)", slotID);
|
2010-09-02 09:19:27 +00:00
|
|
|
|
2010-09-05 16:53:08 +00:00
|
|
|
rv = slot_get_token(slotID, &slot);
|
|
|
|
if (rv != CKR_OK)
|
|
|
|
goto out;
|
2010-09-02 09:19:27 +00:00
|
|
|
|
2010-09-05 16:53:08 +00:00
|
|
|
/* User PIN flags are cleared before re-calculation */
|
|
|
|
slot->token_info.flags &= ~(CKF_USER_PIN_COUNT_LOW|CKF_USER_PIN_FINAL_TRY|CKF_USER_PIN_LOCKED);
|
|
|
|
auth = slot_data_auth(slot->fw_data);
|
|
|
|
if (auth) {
|
|
|
|
pin_info = (struct sc_pkcs15_pin_info*) auth->data;
|
|
|
|
|
|
|
|
/* Try to update PIN info from card */
|
|
|
|
memset(&data, 0, sizeof(data));
|
|
|
|
data.cmd = SC_PIN_CMD_GET_INFO;
|
|
|
|
data.pin_type = SC_AC_CHV;
|
|
|
|
data.pin_reference = pin_info->reference;
|
|
|
|
|
|
|
|
r = sc_pin_cmd(slot->card->card, &data, NULL);
|
|
|
|
if (r == SC_SUCCESS) {
|
|
|
|
if (data.pin1.max_tries > 0)
|
|
|
|
pin_info->max_tries = data.pin1.max_tries;
|
|
|
|
/* tries_left must be supported or sc_pin_cmd should not return SC_SUCCESS */
|
|
|
|
pin_info->tries_left = data.pin1.tries_left;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pin_info->tries_left >= 0) {
|
|
|
|
if (pin_info->tries_left == 1 || pin_info->max_tries == 1)
|
|
|
|
slot->token_info.flags |= CKF_USER_PIN_FINAL_TRY;
|
|
|
|
else if (pin_info->tries_left == 0)
|
|
|
|
slot->token_info.flags |= CKF_USER_PIN_LOCKED;
|
|
|
|
else if (pin_info->max_tries > 1 && pin_info->tries_left < pin_info->max_tries)
|
|
|
|
slot->token_info.flags |= CKF_USER_PIN_COUNT_LOW;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
memcpy(pInfo, &slot->token_info, sizeof(CK_TOKEN_INFO));
|
|
|
|
out:
|
|
|
|
sc_pkcs11_unlock();
|
|
|
|
return rv;
|
|
|
|
}
|
2010-09-02 09:19:27 +00:00
|
|
|
|
2006-05-15 18:48:30 +00:00
|
|
|
static int public_key_created(struct pkcs15_fw_data *fw_data,
|
|
|
|
const unsigned int num_objects,
|
|
|
|
const u8 *id,
|
|
|
|
const size_t size_id,
|
|
|
|
struct pkcs15_any_object **obj2)
|
|
|
|
{
|
|
|
|
int found = 0;
|
2008-05-05 13:00:01 +00:00
|
|
|
unsigned int ii=0;
|
2006-05-15 18:48:30 +00:00
|
|
|
|
|
|
|
while(ii<num_objects && !found) {
|
|
|
|
if (!fw_data->objects[ii]->p15_object) {
|
|
|
|
ii++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if ((fw_data->objects[ii]->p15_object->type != SC_PKCS15_TYPE_PUBKEY) &&
|
|
|
|
(fw_data->objects[ii]->p15_object->type != SC_PKCS15_TYPE_PUBKEY_RSA) &&
|
2009-10-05 20:10:07 +00:00
|
|
|
(fw_data->objects[ii]->p15_object->type != SC_PKCS15_TYPE_PUBKEY_DSA) &&
|
2010-12-01 20:08:42 +00:00
|
|
|
(fw_data->objects[ii]->p15_object->type != SC_PKCS15_TYPE_PUBKEY_EC) &&
|
2009-10-05 20:10:07 +00:00
|
|
|
(fw_data->objects[ii]->p15_object->type != SC_PKCS15_TYPE_PUBKEY_GOSTR3410)) {
|
2006-05-15 18:48:30 +00:00
|
|
|
ii++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* XXX this is somewhat dirty as this assumes that the first
|
|
|
|
* member of the is the pkcs15 id */
|
|
|
|
if (memcmp(fw_data->objects[ii]->p15_object->data, id, size_id) == 0) {
|
|
|
|
*obj2 = (struct pkcs15_any_object *) fw_data->objects[ii];
|
|
|
|
found=1;
|
|
|
|
} else
|
|
|
|
ii++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (found)
|
|
|
|
return SC_SUCCESS;
|
|
|
|
else
|
|
|
|
return SC_ERROR_OBJECT_NOT_FOUND;
|
|
|
|
}
|
|
|
|
|
2003-02-23 17:50:33 +00:00
|
|
|
static int
|
2003-06-04 12:26:06 +00:00
|
|
|
__pkcs15_create_cert_object(struct pkcs15_fw_data *fw_data,
|
|
|
|
struct sc_pkcs15_object *cert, struct pkcs15_any_object **cert_object)
|
2002-01-16 22:49:03 +00:00
|
|
|
{
|
2002-12-02 14:40:30 +00:00
|
|
|
struct sc_pkcs15_cert_info *p15_info;
|
|
|
|
struct sc_pkcs15_cert *p15_cert;
|
2002-01-16 22:49:03 +00:00
|
|
|
struct pkcs15_cert_object *object;
|
2005-01-19 18:15:43 +00:00
|
|
|
struct pkcs15_pubkey_object *obj2;
|
2003-02-23 17:50:33 +00:00
|
|
|
int rv;
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2002-12-02 14:40:30 +00:00
|
|
|
p15_info = (struct sc_pkcs15_cert_info *) cert->data;
|
2006-02-09 20:05:20 +00:00
|
|
|
|
|
|
|
if (cert->flags & SC_PKCS15_CO_FLAG_PRIVATE) /* is the cert private? */
|
|
|
|
p15_cert = NULL; /* will read cert when needed */
|
|
|
|
else
|
2003-02-23 17:50:33 +00:00
|
|
|
if ((rv = sc_pkcs15_read_certificate(fw_data->p15_card, p15_info, &p15_cert) < 0))
|
|
|
|
return rv;
|
2002-12-02 14:40:30 +00:00
|
|
|
|
2005-01-19 18:15:43 +00:00
|
|
|
/* Certificate object */
|
2003-02-23 17:50:33 +00:00
|
|
|
rv = __pkcs15_create_object(fw_data, (struct pkcs15_any_object **) &object,
|
|
|
|
cert, &pkcs15_cert_ops,
|
|
|
|
sizeof(struct pkcs15_cert_object));
|
|
|
|
if (rv < 0)
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
object->cert_info = p15_info;
|
|
|
|
object->cert_data = p15_cert;
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2005-01-19 18:15:43 +00:00
|
|
|
/* Corresponding public key */
|
2006-05-15 18:48:30 +00:00
|
|
|
rv = public_key_created(fw_data, fw_data->num_objects, p15_info->id.value, p15_info->id.len, (struct pkcs15_any_object **) &obj2);
|
|
|
|
|
|
|
|
if (rv != SC_SUCCESS)
|
|
|
|
rv = __pkcs15_create_object(fw_data, (struct pkcs15_any_object **) &obj2,
|
|
|
|
NULL, &pkcs15_pubkey_ops,
|
|
|
|
sizeof(struct pkcs15_pubkey_object));
|
2003-02-23 17:50:33 +00:00
|
|
|
if (rv < 0)
|
2006-05-15 18:48:30 +00:00
|
|
|
return rv;
|
|
|
|
|
2006-02-09 20:05:20 +00:00
|
|
|
if (p15_cert) {
|
2010-10-12 15:26:45 +00:00
|
|
|
/* we take the pubkey from the cert, as it in not needed */
|
|
|
|
obj2->pub_data = p15_cert->key;
|
2006-02-09 20:05:20 +00:00
|
|
|
/* invalidate public data of the cert object so that sc_pkcs15_cert_free
|
|
|
|
* does not free the public key data as well (something like
|
|
|
|
* sc_pkcs15_pubkey_dup would have been nice here) -- Nils
|
|
|
|
*/
|
2010-10-12 15:26:45 +00:00
|
|
|
p15_cert->key = NULL;
|
|
|
|
|
2006-02-09 20:05:20 +00:00
|
|
|
} else
|
|
|
|
obj2->pub_data = NULL; /* will copy from cert when cert is read */
|
|
|
|
|
2009-10-22 09:18:16 +00:00
|
|
|
obj2->pub_genfrom = object;
|
2003-02-23 17:50:33 +00:00
|
|
|
object->cert_pubkey = obj2;
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2003-06-04 12:26:06 +00:00
|
|
|
if (cert_object != NULL)
|
|
|
|
*cert_object = (struct pkcs15_any_object *) object;
|
|
|
|
|
2003-02-23 17:50:33 +00:00
|
|
|
return 0;
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
|
2003-02-23 17:50:33 +00:00
|
|
|
static int
|
2003-06-04 12:26:06 +00:00
|
|
|
__pkcs15_create_pubkey_object(struct pkcs15_fw_data *fw_data,
|
|
|
|
struct sc_pkcs15_object *pubkey, struct pkcs15_any_object **pubkey_object)
|
2002-03-12 14:36:40 +00:00
|
|
|
{
|
|
|
|
struct pkcs15_pubkey_object *object;
|
2003-02-23 17:50:33 +00:00
|
|
|
struct sc_pkcs15_pubkey *p15_key;
|
|
|
|
int rv;
|
2002-03-12 14:36:40 +00:00
|
|
|
|
2003-02-23 17:50:33 +00:00
|
|
|
/* Read public key from card */
|
2006-02-09 20:05:20 +00:00
|
|
|
/* Attempt to read pubkey from card or file.
|
|
|
|
* During initialization process, the key may have been created
|
|
|
|
* and saved as a file before the certificate has been created.
|
|
|
|
*/
|
2006-03-24 10:55:33 +00:00
|
|
|
if (pubkey->flags & SC_PKCS15_CO_FLAG_PRIVATE) /* is the key private? */
|
2011-04-21 16:29:13 +00:00
|
|
|
p15_key = NULL; /* will read key when needed */
|
2006-03-24 10:55:33 +00:00
|
|
|
else {
|
2010-11-30 15:57:01 +00:00
|
|
|
/* if emulation already created pubkey use it */
|
|
|
|
if (pubkey->emulated && (fw_data->p15_card->flags & SC_PKCS15_CARD_FLAG_EMULATED)) {
|
|
|
|
p15_key = (struct sc_pkcs15_pubkey *) pubkey->emulated;
|
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "Using emulated pubkey %p", p15_key);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if ((rv = sc_pkcs15_read_pubkey(fw_data->p15_card, pubkey, &p15_key)) < 0)
|
|
|
|
p15_key = NULL;
|
|
|
|
}
|
2006-03-24 10:55:33 +00:00
|
|
|
}
|
2002-03-12 14:36:40 +00:00
|
|
|
|
2005-01-19 18:15:43 +00:00
|
|
|
/* Public key object */
|
2003-02-23 17:50:33 +00:00
|
|
|
rv = __pkcs15_create_object(fw_data, (struct pkcs15_any_object **) &object,
|
|
|
|
pubkey, &pkcs15_pubkey_ops,
|
|
|
|
sizeof(struct pkcs15_pubkey_object));
|
|
|
|
if (rv >= 0) {
|
|
|
|
object->pub_info = (struct sc_pkcs15_pubkey_info *) pubkey->data;
|
|
|
|
object->pub_data = p15_key;
|
2007-05-25 20:06:59 +00:00
|
|
|
if (p15_key && object->pub_info->modulus_length == 0
|
|
|
|
&& p15_key->algorithm == SC_ALGORITHM_RSA) {
|
|
|
|
object->pub_info->modulus_length =
|
|
|
|
8 * p15_key->u.rsa.modulus.len;
|
|
|
|
}
|
2003-02-23 17:50:33 +00:00
|
|
|
}
|
2002-03-12 14:36:40 +00:00
|
|
|
|
2003-06-04 12:26:06 +00:00
|
|
|
if (pubkey_object != NULL)
|
|
|
|
*pubkey_object = (struct pkcs15_any_object *) object;
|
|
|
|
|
2003-02-23 17:50:33 +00:00
|
|
|
return rv;
|
2002-03-12 14:36:40 +00:00
|
|
|
}
|
|
|
|
|
2003-02-23 17:50:33 +00:00
|
|
|
static int
|
2003-06-04 12:26:06 +00:00
|
|
|
__pkcs15_create_prkey_object(struct pkcs15_fw_data *fw_data,
|
|
|
|
struct sc_pkcs15_object *prkey, struct pkcs15_any_object **prkey_object)
|
2002-01-16 22:49:03 +00:00
|
|
|
{
|
|
|
|
struct pkcs15_prkey_object *object;
|
2003-02-23 17:50:33 +00:00
|
|
|
int rv;
|
|
|
|
|
|
|
|
rv = __pkcs15_create_object(fw_data, (struct pkcs15_any_object **) &object,
|
|
|
|
prkey, &pkcs15_prkey_ops,
|
|
|
|
sizeof(struct pkcs15_prkey_object));
|
|
|
|
if (rv >= 0)
|
|
|
|
object->prv_info = (struct sc_pkcs15_prkey_info *) prkey->data;
|
|
|
|
|
2003-06-04 12:26:06 +00:00
|
|
|
if (prkey_object != NULL)
|
|
|
|
*prkey_object = (struct pkcs15_any_object *) object;
|
|
|
|
|
2003-02-23 17:50:33 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2004-07-26 18:47:23 +00:00
|
|
|
static int
|
|
|
|
__pkcs15_create_data_object(struct pkcs15_fw_data *fw_data,
|
|
|
|
struct sc_pkcs15_object *object, struct pkcs15_any_object **data_object)
|
|
|
|
{
|
|
|
|
struct pkcs15_data_object *dobj = NULL;
|
|
|
|
int rv;
|
|
|
|
|
|
|
|
rv = __pkcs15_create_object(fw_data, (struct pkcs15_any_object **) &dobj,
|
|
|
|
object, &pkcs15_dobj_ops,
|
|
|
|
sizeof(struct pkcs15_data_object));
|
|
|
|
if (rv >= 0) {
|
|
|
|
dobj->info = (struct sc_pkcs15_data_info *) object->data;
|
|
|
|
dobj->value = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (data_object != NULL)
|
|
|
|
*data_object = (struct pkcs15_any_object *) dobj;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-23 17:50:33 +00:00
|
|
|
static int
|
|
|
|
pkcs15_create_pkcs11_objects(struct pkcs15_fw_data *fw_data,
|
|
|
|
int p15_type, const char *name,
|
|
|
|
int (*create)(struct pkcs15_fw_data *,
|
2003-06-04 12:26:06 +00:00
|
|
|
struct sc_pkcs15_object *,
|
|
|
|
struct pkcs15_any_object **any_object))
|
2003-02-23 17:50:33 +00:00
|
|
|
{
|
|
|
|
struct sc_pkcs15_object *p15_object[MAX_OBJECTS];
|
|
|
|
int i, count, rv;
|
|
|
|
|
2005-01-19 18:15:43 +00:00
|
|
|
rv = count = sc_pkcs15_get_objects(fw_data->p15_card, p15_type, p15_object, MAX_OBJECTS);
|
2003-02-23 17:50:33 +00:00
|
|
|
|
|
|
|
if (rv >= 0) {
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "Found %d %s%s\n", count,
|
2003-02-23 17:50:33 +00:00
|
|
|
name, (count == 1)? "" : "s");
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; rv >= 0 && i < count; i++) {
|
2003-06-04 12:26:06 +00:00
|
|
|
rv = create(fw_data, p15_object[i], NULL);
|
2003-02-23 17:50:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
__pkcs15_prkey_bind_related(struct pkcs15_fw_data *fw_data, struct pkcs15_prkey_object *pk)
|
|
|
|
{
|
|
|
|
sc_pkcs15_id_t *id = &pk->prv_info->id;
|
|
|
|
unsigned int i;
|
|
|
|
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "Object is a private key and has id %s",
|
2009-10-22 09:18:16 +00:00
|
|
|
sc_pkcs15_print_id(id));
|
|
|
|
|
2003-02-23 17:50:33 +00:00
|
|
|
for (i = 0; i < fw_data->num_objects; i++) {
|
|
|
|
struct pkcs15_any_object *obj = fw_data->objects[i];
|
|
|
|
|
2003-04-17 13:03:49 +00:00
|
|
|
if (obj->base.flags & SC_PKCS11_OBJECT_HIDDEN)
|
|
|
|
continue;
|
2003-04-17 12:38:08 +00:00
|
|
|
if (is_privkey(obj) && obj != (struct pkcs15_any_object *) pk) {
|
|
|
|
/* merge private keys with the same ID and
|
|
|
|
* different usage bits */
|
|
|
|
struct pkcs15_prkey_object *other, **pp;
|
|
|
|
|
|
|
|
other = (struct pkcs15_prkey_object *) obj;
|
|
|
|
if (sc_pkcs15_compare_id(&other->prv_info->id, id)) {
|
|
|
|
obj->base.flags |= SC_PKCS11_OBJECT_HIDDEN;
|
|
|
|
for (pp = &pk->prv_next; *pp; pp = &(*pp)->prv_next)
|
|
|
|
;
|
|
|
|
*pp = (struct pkcs15_prkey_object *) obj;
|
|
|
|
}
|
|
|
|
} else
|
2003-02-23 17:50:33 +00:00
|
|
|
if (is_pubkey(obj) && !pk->prv_pubkey) {
|
|
|
|
struct pkcs15_pubkey_object *pubkey;
|
|
|
|
|
|
|
|
pubkey = (struct pkcs15_pubkey_object *) obj;
|
2007-05-25 20:06:59 +00:00
|
|
|
if (sc_pkcs15_compare_id(&pubkey->pub_info->id, id)) {
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "Associating object %d as public key", i);
|
2003-02-23 17:50:33 +00:00
|
|
|
pk->prv_pubkey = pubkey;
|
2007-05-25 20:06:59 +00:00
|
|
|
if (pk->prv_info->modulus_length == 0)
|
|
|
|
pk->prv_info->modulus_length = pubkey->pub_info->modulus_length;
|
|
|
|
}
|
2003-02-23 17:50:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
__pkcs15_cert_bind_related(struct pkcs15_fw_data *fw_data, struct pkcs15_cert_object *cert)
|
|
|
|
{
|
2009-10-22 09:18:16 +00:00
|
|
|
struct sc_pkcs15_cert *c1 = cert->cert_data;
|
|
|
|
sc_pkcs15_id_t *id = &cert->cert_info->id;
|
2003-02-23 17:50:33 +00:00
|
|
|
unsigned int i;
|
|
|
|
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "Object is a certificate and has id %s",
|
2009-10-22 09:18:16 +00:00
|
|
|
sc_pkcs15_print_id(id));
|
|
|
|
|
|
|
|
/* Loop over all objects to see if we find the certificate of
|
|
|
|
* the issuer and the associated private key */
|
2003-02-23 17:50:33 +00:00
|
|
|
for (i = 0; i < fw_data->num_objects; i++) {
|
|
|
|
struct pkcs15_any_object *obj = fw_data->objects[i];
|
|
|
|
|
2009-10-22 09:18:16 +00:00
|
|
|
if (is_cert(obj) && obj != (struct pkcs15_any_object *) cert) {
|
|
|
|
struct pkcs15_cert_object *cert2;
|
|
|
|
struct sc_pkcs15_cert *c2;
|
2003-02-23 17:50:33 +00:00
|
|
|
|
2009-10-22 09:18:16 +00:00
|
|
|
cert2 = (struct pkcs15_cert_object *) obj;
|
|
|
|
c2 = cert2->cert_data;
|
2003-02-23 17:50:33 +00:00
|
|
|
|
2009-10-22 09:18:16 +00:00
|
|
|
if (!c1 || !c2 || !c1->issuer_len || !c2->subject_len)
|
|
|
|
continue;
|
|
|
|
if (c1->issuer_len == c2->subject_len
|
|
|
|
&& !memcmp(c1->issuer, c2->subject, c1->issuer_len)) {
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "Associating object %d (id %s) as issuer",
|
2009-10-22 09:18:16 +00:00
|
|
|
i, sc_pkcs15_print_id(&cert2->cert_info->id));
|
|
|
|
cert->cert_issuer = (struct pkcs15_cert_object *) obj;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
if (is_privkey(obj) && !cert->cert_prvkey) {
|
|
|
|
struct pkcs15_prkey_object *pk;
|
|
|
|
|
|
|
|
pk = (struct pkcs15_prkey_object *) obj;
|
|
|
|
if (sc_pkcs15_compare_id(&pk->prv_info->id, id)) {
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "Associating object %d as private key", i);
|
2009-10-22 09:18:16 +00:00
|
|
|
cert->cert_prvkey = pk;
|
|
|
|
}
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
}
|
2003-02-23 17:50:33 +00:00
|
|
|
}
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2003-02-23 17:50:33 +00:00
|
|
|
static void
|
|
|
|
pkcs15_bind_related_objects(struct pkcs15_fw_data *fw_data)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
/* Loop over all private keys and attached related certificate
|
|
|
|
* and/or public key
|
|
|
|
*/
|
|
|
|
for (i = 0; i < fw_data->num_objects; i++) {
|
|
|
|
struct pkcs15_any_object *obj = fw_data->objects[i];
|
|
|
|
|
2003-04-17 13:03:49 +00:00
|
|
|
if (obj->base.flags & SC_PKCS11_OBJECT_HIDDEN)
|
|
|
|
continue;
|
2009-10-22 09:18:16 +00:00
|
|
|
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "Looking for objects related to object %d", i);
|
2009-10-22 09:18:16 +00:00
|
|
|
|
2003-02-23 17:50:33 +00:00
|
|
|
if (is_privkey(obj)) {
|
|
|
|
__pkcs15_prkey_bind_related(fw_data, (struct pkcs15_prkey_object *) obj);
|
|
|
|
} else if (is_cert(obj)) {
|
|
|
|
__pkcs15_cert_bind_related(fw_data, (struct pkcs15_cert_object *) obj);
|
2002-03-12 14:36:40 +00:00
|
|
|
}
|
|
|
|
}
|
2003-02-23 17:50:33 +00:00
|
|
|
}
|
2002-03-12 14:36:40 +00:00
|
|
|
|
2006-02-09 20:05:20 +00:00
|
|
|
/* We deferred reading of the cert until needed, as it may be
|
|
|
|
* a private object, so we must wait till login to read
|
|
|
|
*/
|
|
|
|
|
|
|
|
static int
|
|
|
|
check_cert_data_read(struct pkcs15_fw_data *fw_data,
|
|
|
|
struct pkcs15_cert_object *cert)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
struct pkcs15_pubkey_object *obj2;
|
|
|
|
|
|
|
|
if (!cert)
|
|
|
|
return SC_ERROR_OBJECT_NOT_FOUND;
|
|
|
|
|
|
|
|
if (cert->cert_data)
|
|
|
|
return 0;
|
|
|
|
if ((rv = sc_pkcs15_read_certificate(fw_data->p15_card,
|
|
|
|
cert->cert_info, &cert->cert_data) < 0))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
/* update the related public key object */
|
|
|
|
obj2 = cert->cert_pubkey;
|
|
|
|
|
2010-10-25 20:58:02 +00:00
|
|
|
obj2->pub_data = cert->cert_data->key;
|
|
|
|
/* We take the pub key from the cert that we will discard below */
|
2006-02-09 20:05:20 +00:00
|
|
|
/* invalidate public data of the cert object so that sc_pkcs15_cert_free
|
|
|
|
* does not free the public key data as well (something like
|
|
|
|
* sc_pkcs15_pubkey_dup would have been nice here) -- Nils
|
|
|
|
*/
|
2010-10-25 20:58:02 +00:00
|
|
|
cert->cert_data->key = NULL;
|
2006-02-09 20:05:20 +00:00
|
|
|
|
|
|
|
/* now that we have the cert and pub key, lets see if we can bind anything else */
|
|
|
|
|
|
|
|
pkcs15_bind_related_objects(fw_data);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2003-02-23 17:50:33 +00:00
|
|
|
static void
|
|
|
|
pkcs15_add_object(struct sc_pkcs11_slot *slot,
|
|
|
|
struct pkcs15_any_object *obj,
|
|
|
|
CK_OBJECT_HANDLE_PTR pHandle)
|
|
|
|
{
|
2009-10-22 09:18:16 +00:00
|
|
|
unsigned int i;
|
|
|
|
struct pkcs15_fw_data *card_fw_data;
|
|
|
|
|
2003-04-17 12:38:08 +00:00
|
|
|
if (obj == NULL
|
|
|
|
|| (obj->base.flags & (SC_PKCS11_OBJECT_HIDDEN | SC_PKCS11_OBJECT_RECURS)))
|
2003-02-23 17:50:33 +00:00
|
|
|
return;
|
|
|
|
|
2010-01-24 20:45:02 +00:00
|
|
|
|
|
|
|
if (list_contains(&slot->objects, obj))
|
2003-03-27 16:08:10 +00:00
|
|
|
return;
|
|
|
|
|
fix: use of uninitialised value - return parameter (phObject) from C_CreateObject and C_GenerateKeyPair
(In function 'pkcs15_add_object': warning: unused parameter 'pHandle')
Example (C_CreateObject):
Breakpoint 3, C_CreateObject (hSession=134587040, pTemplate=0x8049160, ulCount=5, phObject=0xbff55560)
at pkcs11-object.c:57
57 rv = sc_pkcs11_lock();
(gdb) x/x phObject
0xbff55560: 0xffffffff
(gdb) finish
0xb7f5c6c0 17:15:09.969 [opensc-pkcs11] framework-pkcs15.c:657:pkcs15_add_object: Setting object handle of 0x0 to 0x805ab80
Run till exit from #0 C_CreateObject (hSession=134587040, pTemplate=0x8049160, ulCount=5,
phObject=0xbff55560) at pkcs11-object.c:57
0x080487a4 in main ()
Value returned is $1 = 0
(gdb) x/x 0xbff55560
0xbff55560: 0xffffffff
(gdb) c
Continuing.
Breakpoint 4, C_DestroyObject (hSession=134587040, hObject=4294967295) at pkcs11-object.c:106
106 rv = sc_pkcs11_lock();
(gdb) p/x hObject
$2 = 0xffffffff
(gdb) finish
Run till exit from #0 C_DestroyObject (hSession=134587040, hObject=4294967295) at pkcs11-object.c:106
0xb7f5c6c0 17:15:56.581 [opensc-pkcs11] pkcs11-object.c:110:C_DestroyObject: C_DestroyObject(hSession=0x805a2a0, hObject=0xffffffff)
0x080487cb in main ()
Value returned is $3 = 130
git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@3944 c6295689-39f2-0310-b995-f0e70906c6a9
2010-01-27 14:50:35 +00:00
|
|
|
if (pHandle != NULL)
|
|
|
|
*pHandle = (CK_OBJECT_HANDLE)obj; /* cast pointer to long */
|
|
|
|
|
|
|
|
list_append(&slot->objects, obj);
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "Setting object handle of 0x%lx to 0x%lx", obj->base.handle, (CK_OBJECT_HANDLE)obj);
|
fix: use of uninitialised value - return parameter (phObject) from C_CreateObject and C_GenerateKeyPair
(In function 'pkcs15_add_object': warning: unused parameter 'pHandle')
Example (C_CreateObject):
Breakpoint 3, C_CreateObject (hSession=134587040, pTemplate=0x8049160, ulCount=5, phObject=0xbff55560)
at pkcs11-object.c:57
57 rv = sc_pkcs11_lock();
(gdb) x/x phObject
0xbff55560: 0xffffffff
(gdb) finish
0xb7f5c6c0 17:15:09.969 [opensc-pkcs11] framework-pkcs15.c:657:pkcs15_add_object: Setting object handle of 0x0 to 0x805ab80
Run till exit from #0 C_CreateObject (hSession=134587040, pTemplate=0x8049160, ulCount=5,
phObject=0xbff55560) at pkcs11-object.c:57
0x080487a4 in main ()
Value returned is $1 = 0
(gdb) x/x 0xbff55560
0xbff55560: 0xffffffff
(gdb) c
Continuing.
Breakpoint 4, C_DestroyObject (hSession=134587040, hObject=4294967295) at pkcs11-object.c:106
106 rv = sc_pkcs11_lock();
(gdb) p/x hObject
$2 = 0xffffffff
(gdb) finish
Run till exit from #0 C_DestroyObject (hSession=134587040, hObject=4294967295) at pkcs11-object.c:106
0xb7f5c6c0 17:15:56.581 [opensc-pkcs11] pkcs11-object.c:110:C_DestroyObject: C_DestroyObject(hSession=0x805a2a0, hObject=0xffffffff)
0x080487cb in main ()
Value returned is $3 = 130
git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@3944 c6295689-39f2-0310-b995-f0e70906c6a9
2010-01-27 14:50:35 +00:00
|
|
|
obj->base.handle = (CK_OBJECT_HANDLE)obj; /* cast pointer to long */
|
2003-02-23 17:50:33 +00:00
|
|
|
obj->base.flags |= SC_PKCS11_OBJECT_SEEN;
|
|
|
|
obj->refcount++;
|
|
|
|
|
|
|
|
/* Add related objects
|
|
|
|
* XXX prevent infinite recursion when a card specifies two certificates
|
|
|
|
* referring to each other.
|
|
|
|
*/
|
2003-04-17 12:38:08 +00:00
|
|
|
obj->base.flags |= SC_PKCS11_OBJECT_RECURS;
|
|
|
|
|
2003-02-23 17:50:33 +00:00
|
|
|
switch (__p15_type(obj)) {
|
|
|
|
case SC_PKCS15_TYPE_PRKEY_RSA:
|
2009-10-05 20:10:07 +00:00
|
|
|
case SC_PKCS15_TYPE_PRKEY_GOSTR3410:
|
2011-04-12 11:36:40 +00:00
|
|
|
case SC_PKCS15_TYPE_PRKEY_EC:
|
2009-10-22 09:18:16 +00:00
|
|
|
pkcs15_add_object(slot, (struct pkcs15_any_object *) obj->related_pubkey, NULL);
|
|
|
|
card_fw_data = (struct pkcs15_fw_data *) slot->card->fw_data;
|
|
|
|
for (i = 0; i < card_fw_data->num_objects; i++) {
|
|
|
|
struct pkcs15_any_object *obj2 = card_fw_data->objects[i];
|
|
|
|
struct pkcs15_cert_object *cert;
|
|
|
|
|
|
|
|
if (!is_cert(obj2))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
cert = (struct pkcs15_cert_object*) obj2;
|
|
|
|
|
|
|
|
if ((struct pkcs15_any_object*)(cert->cert_prvkey) != obj)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
pkcs15_add_object(slot, obj2, NULL);
|
|
|
|
}
|
2009-10-05 20:10:07 +00:00
|
|
|
break;
|
2003-07-16 05:20:58 +00:00
|
|
|
case SC_PKCS15_TYPE_CERT_X509:
|
|
|
|
pkcs15_add_object(slot, (struct pkcs15_any_object *) obj->related_pubkey, NULL);
|
|
|
|
pkcs15_add_object(slot, (struct pkcs15_any_object *) obj->related_cert, NULL);
|
2003-02-23 17:50:33 +00:00
|
|
|
break;
|
|
|
|
}
|
2003-04-17 12:38:08 +00:00
|
|
|
|
|
|
|
obj->base.flags &= ~SC_PKCS11_OBJECT_RECURS;
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
|
2010-03-08 12:32:35 +00:00
|
|
|
static void pkcs15_init_slot(struct sc_pkcs15_card *p15card,
|
2002-04-08 15:51:19 +00:00
|
|
|
struct sc_pkcs11_slot *slot,
|
|
|
|
struct sc_pkcs15_object *auth)
|
2002-03-18 11:05:21 +00:00
|
|
|
{
|
2002-04-11 15:17:33 +00:00
|
|
|
struct pkcs15_slot_data *fw_data;
|
2002-03-18 11:05:21 +00:00
|
|
|
struct sc_pkcs15_pin_info *pin_info = NULL;
|
2002-03-20 17:17:48 +00:00
|
|
|
char tmp[64];
|
2002-03-18 11:05:21 +00:00
|
|
|
|
2010-03-08 12:32:35 +00:00
|
|
|
pkcs15_init_token_info(p15card, &slot->token_info);
|
2006-09-27 22:10:12 +00:00
|
|
|
slot->token_info.flags |= CKF_TOKEN_INITIALIZED;
|
|
|
|
if (auth != NULL)
|
|
|
|
slot->token_info.flags |= CKF_USER_PIN_INITIALIZED;
|
2010-03-08 12:32:35 +00:00
|
|
|
if (p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) {
|
2003-01-06 19:28:48 +00:00
|
|
|
slot->token_info.flags |= CKF_PROTECTED_AUTHENTICATION_PATH;
|
2003-05-15 10:34:03 +00:00
|
|
|
}
|
2010-09-01 06:23:17 +00:00
|
|
|
|
|
|
|
if (p15card->card->caps & SC_CARD_CAP_RNG && p15card->card->ops->get_challenge != NULL)
|
2003-01-16 20:10:28 +00:00
|
|
|
slot->token_info.flags |= CKF_RNG;
|
2010-09-01 06:23:17 +00:00
|
|
|
|
Do not cast the return value of malloc(3) and calloc(3)
From http://en.wikipedia.org/wiki/Malloc#Casting_and_type_safety
" Casting and type safety
malloc returns a void pointer (void *), which indicates that it is a
pointer to a region of unknown data type. One may "cast" (see type
conversion) this pointer to a specific type, as in
int *ptr = (int*)malloc(10 * sizeof (int));
When using C, this is considered bad practice; it is redundant under the
C standard. Moreover, putting in a cast may mask failure to include the
header stdlib.h, in which the prototype for malloc is found. In the
absence of a prototype for malloc, the C compiler will assume that
malloc returns an int, and will issue a warning in a context such as the
above, provided the error is not masked by a cast. On certain
architectures and data models (such as LP64 on 64 bit systems, where
long and pointers are 64 bit and int is 32 bit), this error can actually
result in undefined behavior, as the implicitly declared malloc returns
a 32 bit value whereas the actually defined function returns a 64 bit
value. Depending on calling conventions and memory layout, this may
result in stack smashing.
The returned pointer need not be explicitly cast to a more specific
pointer type, since ANSI C defines an implicit conversion between the
void pointer type and other pointers to objects. An explicit cast of
malloc's return value is sometimes performed because malloc originally
returned a char *, but this cast is unnecessary in standard C
code.[4][5] Omitting the cast, however, creates an incompatibility with
C++, which does require it.
The lack of a specific pointer type returned from malloc is type-unsafe
behaviour: malloc allocates based on byte count but not on type. This
distinguishes it from the C++ new operator that returns a pointer whose
type relies on the operand. (see C Type Safety). "
See also
http://www.opensc-project.org/pipermail/opensc-devel/2010-August/014586.html
git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@4636 c6295689-39f2-0310-b995-f0e70906c6a9
2010-08-18 15:08:51 +00:00
|
|
|
slot->fw_data = fw_data = calloc(1, sizeof(*fw_data));
|
2002-04-11 15:17:33 +00:00
|
|
|
fw_data->auth_obj = auth;
|
2002-03-18 11:05:21 +00:00
|
|
|
|
|
|
|
if (auth != NULL) {
|
|
|
|
pin_info = (struct sc_pkcs15_pin_info*) auth->data;
|
|
|
|
|
2003-01-03 11:40:11 +00:00
|
|
|
if (auth->label[0]) {
|
|
|
|
snprintf(tmp, sizeof(tmp), "%s (%s)",
|
2010-10-05 15:44:58 +00:00
|
|
|
p15card->tokeninfo->label, auth->label);
|
2003-01-03 11:40:11 +00:00
|
|
|
} else {
|
2010-10-05 15:44:58 +00:00
|
|
|
snprintf(tmp, sizeof(tmp), "%s", p15card->tokeninfo->label);
|
2003-01-03 11:40:11 +00:00
|
|
|
}
|
2002-03-18 11:05:21 +00:00
|
|
|
slot->token_info.flags |= CKF_LOGIN_REQUIRED;
|
2002-03-20 17:17:48 +00:00
|
|
|
} else
|
2010-10-05 15:44:58 +00:00
|
|
|
snprintf(tmp, sizeof(tmp), "%s", p15card->tokeninfo->label);
|
2002-03-20 17:17:48 +00:00
|
|
|
strcpy_bp(slot->token_info.label, tmp, 32);
|
2002-03-18 11:05:21 +00:00
|
|
|
|
|
|
|
if (pin_info && pin_info->magic == SC_PKCS15_PIN_MAGIC) {
|
2003-02-20 23:19:01 +00:00
|
|
|
slot->token_info.ulMaxPinLen = pin_info->max_length;
|
2002-03-18 11:05:21 +00:00
|
|
|
slot->token_info.ulMinPinLen = pin_info->min_length;
|
|
|
|
} else {
|
|
|
|
/* choose reasonable defaults */
|
|
|
|
slot->token_info.ulMaxPinLen = 8;
|
|
|
|
slot->token_info.ulMinPinLen = 4;
|
|
|
|
}
|
2010-03-08 12:32:35 +00:00
|
|
|
if (p15card->flags & SC_PKCS15_CARD_FLAG_EMULATED)
|
2009-09-14 10:05:40 +00:00
|
|
|
slot->token_info.flags |= CKF_WRITE_PROTECTED;
|
2002-03-18 11:05:21 +00:00
|
|
|
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "Initialized token '%s' in slot 0x%lx", tmp, slot->id);
|
2002-04-08 15:51:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static CK_RV pkcs15_create_slot(struct sc_pkcs11_card *p11card,
|
|
|
|
struct sc_pkcs15_object *auth,
|
|
|
|
struct sc_pkcs11_slot **out)
|
|
|
|
{
|
2005-01-19 18:15:43 +00:00
|
|
|
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) p11card->fw_data;
|
2003-01-13 21:38:43 +00:00
|
|
|
struct sc_pkcs11_slot *slot;
|
2002-04-08 15:51:19 +00:00
|
|
|
int rv;
|
|
|
|
|
2003-01-13 21:38:43 +00:00
|
|
|
rv = slot_allocate(&slot, p11card);
|
2002-04-08 15:51:19 +00:00
|
|
|
if (rv != CKR_OK)
|
|
|
|
return rv;
|
|
|
|
|
2003-01-13 21:38:43 +00:00
|
|
|
/* There's a token in this slot */
|
|
|
|
slot->slot_info.flags |= CKF_TOKEN_PRESENT;
|
|
|
|
|
|
|
|
/* Fill in the slot/token info from pkcs15 data */
|
2003-02-23 17:50:33 +00:00
|
|
|
pkcs15_init_slot(fw_data->p15_card, slot, auth);
|
2003-01-13 21:38:43 +00:00
|
|
|
|
|
|
|
*out = slot;
|
2002-03-18 11:05:21 +00:00
|
|
|
return CKR_OK;
|
|
|
|
}
|
|
|
|
|
2002-01-16 22:49:03 +00:00
|
|
|
static CK_RV pkcs15_create_tokens(struct sc_pkcs11_card *p11card)
|
|
|
|
{
|
2003-02-23 17:50:33 +00:00
|
|
|
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) p11card->fw_data;
|
2003-06-24 11:31:02 +00:00
|
|
|
struct sc_pkcs15_object *auths[MAX_OBJECTS];
|
2005-12-04 23:23:25 +00:00
|
|
|
struct sc_pkcs11_slot *slot = NULL;
|
2010-01-24 20:45:02 +00:00
|
|
|
int i, rv;
|
2005-01-19 18:15:43 +00:00
|
|
|
int auth_count;
|
Douglas E. Engert:
Looking at framework-pkcs11.c, it looks like there is a bug in the handling of
auth_count, if there is more then one pin, and one of the pins is a
SC_PKCS15_PIN_FLAG_SO_PIN.
The for loop at line 767 will add a slot for each non SO_PIN or UNBLOCKING_PIN.
But at line 812, the auth_count is still set to the number of pins, even though
the SO_PIN did not cause a new slot to be allocated and thus the test of
hide_empty_tokens will not be used.
With the attached patch, I can get the expected behavior when hide_empty_tokens
= yes in the opensc.conf from pkcs11-tool -L, pkcs11-tool -O and pkcs11-tool -O
-l
There is only 1 slot allocated, the pkcs11-tool -O shows all the public
objects, and pkcs11-tool -O -l (after PIN) shows all the objects, and Heimdal
PKINIT still runs.
I still think that if two or more slots need to be allocated for multiple auth
pins, then all the public objects should be added to each. I have an additional
mod for this too.
Since the cards I am working with only have 1 pin, the attached mods works for
me. Note it looks like the pkcs15-openpgp.c might also be affected by this
change as it defines two pins an auth pin and a SO_PIN, much like the PIV card
does.
git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@3175 c6295689-39f2-0310-b995-f0e70906c6a9
2007-06-21 07:11:21 +00:00
|
|
|
int found_auth_count = 0;
|
2003-02-23 17:50:33 +00:00
|
|
|
unsigned int j;
|
|
|
|
|
2005-01-19 18:15:43 +00:00
|
|
|
rv = sc_pkcs15_get_objects(fw_data->p15_card,
|
2003-02-23 17:50:33 +00:00
|
|
|
SC_PKCS15_TYPE_AUTH_PIN,
|
|
|
|
auths,
|
|
|
|
SC_PKCS15_MAX_PINS);
|
2002-01-16 22:49:03 +00:00
|
|
|
if (rv < 0)
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rv, NULL);
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "Found %d authentication objects\n", rv);
|
2003-02-23 17:50:33 +00:00
|
|
|
auth_count = rv;
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2005-01-19 18:15:43 +00:00
|
|
|
rv = pkcs15_create_pkcs11_objects(fw_data,
|
2003-02-23 17:50:33 +00:00
|
|
|
SC_PKCS15_TYPE_PRKEY_RSA,
|
2010-12-01 20:08:42 +00:00
|
|
|
"RSA private key",
|
2003-02-23 17:50:33 +00:00
|
|
|
__pkcs15_create_prkey_object);
|
|
|
|
if (rv < 0)
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rv, NULL);
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2005-01-19 18:15:43 +00:00
|
|
|
rv = pkcs15_create_pkcs11_objects(fw_data,
|
2003-02-23 17:50:33 +00:00
|
|
|
SC_PKCS15_TYPE_PUBKEY_RSA,
|
2010-12-01 20:08:42 +00:00
|
|
|
"RSA public key",
|
2003-02-23 17:50:33 +00:00
|
|
|
__pkcs15_create_pubkey_object);
|
2002-01-21 09:05:22 +00:00
|
|
|
if (rv < 0)
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rv, NULL);
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2010-12-01 20:08:42 +00:00
|
|
|
rv = pkcs15_create_pkcs11_objects(fw_data,
|
|
|
|
SC_PKCS15_TYPE_PRKEY_EC,
|
|
|
|
"EC private key",
|
|
|
|
__pkcs15_create_prkey_object);
|
|
|
|
if (rv < 0)
|
|
|
|
return sc_to_cryptoki_error(rv, NULL);
|
|
|
|
|
|
|
|
rv = pkcs15_create_pkcs11_objects(fw_data,
|
|
|
|
SC_PKCS15_TYPE_PUBKEY_EC,
|
|
|
|
"EC public key",
|
|
|
|
__pkcs15_create_pubkey_object);
|
|
|
|
if (rv < 0)
|
|
|
|
return sc_to_cryptoki_error(rv, NULL);
|
|
|
|
|
|
|
|
|
2009-10-05 20:10:07 +00:00
|
|
|
rv = pkcs15_create_pkcs11_objects(fw_data,
|
|
|
|
SC_PKCS15_TYPE_PRKEY_GOSTR3410,
|
2010-12-01 20:08:42 +00:00
|
|
|
"GOSTR3410 private key",
|
2009-10-05 20:10:07 +00:00
|
|
|
__pkcs15_create_prkey_object);
|
|
|
|
if (rv < 0)
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rv, NULL);
|
2009-10-05 20:10:07 +00:00
|
|
|
|
|
|
|
rv = pkcs15_create_pkcs11_objects(fw_data,
|
|
|
|
SC_PKCS15_TYPE_PUBKEY_GOSTR3410,
|
2010-12-01 20:08:42 +00:00
|
|
|
"GOSTR3410 public key",
|
2009-10-05 20:10:07 +00:00
|
|
|
__pkcs15_create_pubkey_object);
|
|
|
|
if (rv < 0)
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rv, NULL);
|
2009-10-05 20:10:07 +00:00
|
|
|
|
2003-02-23 17:50:33 +00:00
|
|
|
rv = pkcs15_create_pkcs11_objects(fw_data,
|
|
|
|
SC_PKCS15_TYPE_CERT_X509,
|
|
|
|
"certificate",
|
|
|
|
__pkcs15_create_cert_object);
|
|
|
|
if (rv < 0)
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rv, NULL);
|
2003-02-23 17:50:33 +00:00
|
|
|
|
2004-07-26 18:47:23 +00:00
|
|
|
rv = pkcs15_create_pkcs11_objects(fw_data,
|
|
|
|
SC_PKCS15_TYPE_DATA_OBJECT,
|
|
|
|
"data object",
|
|
|
|
__pkcs15_create_data_object);
|
|
|
|
if (rv < 0)
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rv, NULL);
|
2004-07-26 18:47:23 +00:00
|
|
|
|
2003-02-23 17:50:33 +00:00
|
|
|
/* Match up related keys and certificates */
|
|
|
|
pkcs15_bind_related_objects(fw_data);
|
2002-03-12 14:36:40 +00:00
|
|
|
|
2007-03-29 10:25:16 +00:00
|
|
|
if (hack_enabled)
|
|
|
|
auth_count = 1;
|
|
|
|
|
2002-03-03 17:36:23 +00:00
|
|
|
for (i = 0; i < auth_count; i++) {
|
2002-03-18 11:05:21 +00:00
|
|
|
struct sc_pkcs15_pin_info *pin_info = NULL;
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2002-03-18 11:05:21 +00:00
|
|
|
pin_info = (struct sc_pkcs15_pin_info*) auths[i]->data;
|
2002-04-08 15:51:19 +00:00
|
|
|
|
|
|
|
/* Ignore any non-authentication PINs */
|
2006-02-14 22:46:54 +00:00
|
|
|
if ((pin_info->flags & SC_PKCS15_PIN_FLAG_SO_PIN) != 0)
|
2002-04-08 15:51:19 +00:00
|
|
|
continue;
|
|
|
|
|
2010-01-28 12:14:48 +00:00
|
|
|
/* Ignore unblocking pins for hacked module */
|
|
|
|
if (hack_enabled && (pin_info->flags & SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN) != 0)
|
2007-03-29 10:25:16 +00:00
|
|
|
continue;
|
|
|
|
|
2010-01-28 12:14:48 +00:00
|
|
|
/* Ignore unblocking pins */
|
2010-01-28 14:15:13 +00:00
|
|
|
if (!sc_pkcs11_conf.create_puk_slot)
|
2010-01-28 12:14:48 +00:00
|
|
|
if (pin_info->flags & SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN)
|
|
|
|
continue;
|
|
|
|
|
Douglas E. Engert:
Looking at framework-pkcs11.c, it looks like there is a bug in the handling of
auth_count, if there is more then one pin, and one of the pins is a
SC_PKCS15_PIN_FLAG_SO_PIN.
The for loop at line 767 will add a slot for each non SO_PIN or UNBLOCKING_PIN.
But at line 812, the auth_count is still set to the number of pins, even though
the SO_PIN did not cause a new slot to be allocated and thus the test of
hide_empty_tokens will not be used.
With the attached patch, I can get the expected behavior when hide_empty_tokens
= yes in the opensc.conf from pkcs11-tool -L, pkcs11-tool -O and pkcs11-tool -O
-l
There is only 1 slot allocated, the pkcs11-tool -O shows all the public
objects, and pkcs11-tool -O -l (after PIN) shows all the objects, and Heimdal
PKINIT still runs.
I still think that if two or more slots need to be allocated for multiple auth
pins, then all the public objects should be added to each. I have an additional
mod for this too.
Since the cards I am working with only have 1 pin, the attached mods works for
me. Note it looks like the pkcs15-openpgp.c might also be affected by this
change as it defines two pins an auth pin and a SO_PIN, much like the PIV card
does.
git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@3175 c6295689-39f2-0310-b995-f0e70906c6a9
2007-06-21 07:11:21 +00:00
|
|
|
found_auth_count++;
|
|
|
|
|
2002-04-08 15:51:19 +00:00
|
|
|
rv = pkcs15_create_slot(p11card, auths[i], &slot);
|
|
|
|
if (rv != CKR_OK)
|
2004-01-08 09:47:23 +00:00
|
|
|
return CKR_OK; /* no more slots available for this card */
|
2007-03-29 10:25:16 +00:00
|
|
|
|
|
|
|
/* Add all objects related to this pin */
|
2003-02-23 17:50:33 +00:00
|
|
|
for (j=0; j < fw_data->num_objects; j++) {
|
|
|
|
struct pkcs15_any_object *obj = fw_data->objects[j];
|
|
|
|
|
2009-10-22 09:18:16 +00:00
|
|
|
/* "Fake" objects we've generated */
|
2005-09-07 09:32:52 +00:00
|
|
|
if (__p15_type(obj) == (unsigned int)-1)
|
2004-07-26 18:47:23 +00:00
|
|
|
continue;
|
2009-10-22 09:18:16 +00:00
|
|
|
/* Some objects have an auth_id even though they are
|
|
|
|
* not private. Just ignore those... */
|
|
|
|
if (!(obj->p15_object->flags & SC_PKCS15_CO_FLAG_PRIVATE))
|
|
|
|
continue;
|
|
|
|
if (!sc_pkcs15_compare_id(&pin_info->auth_id, &obj->p15_object->auth_id))
|
2003-02-23 17:50:33 +00:00
|
|
|
continue;
|
|
|
|
|
2005-08-21 18:39:43 +00:00
|
|
|
if (is_privkey(obj)) {
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "Adding private key %d to PIN %d\n", j, i);
|
2005-07-24 14:06:02 +00:00
|
|
|
pkcs15_add_object(slot, obj, NULL);
|
2005-08-21 18:39:43 +00:00
|
|
|
}
|
|
|
|
else if (is_data(obj)) {
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "Adding data object %d to PIN %d\n", j, i);
|
2004-07-26 18:47:23 +00:00
|
|
|
pkcs15_add_object(slot, obj, NULL);
|
|
|
|
}
|
2006-02-09 20:05:20 +00:00
|
|
|
else if (is_cert(obj)) {
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "Adding cert object %d to PIN %d\n", j, i);
|
2006-02-09 20:05:20 +00:00
|
|
|
pkcs15_add_object(slot, obj, NULL);
|
|
|
|
}
|
2004-07-26 18:47:23 +00:00
|
|
|
}
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
|
Douglas E. Engert:
Looking at framework-pkcs11.c, it looks like there is a bug in the handling of
auth_count, if there is more then one pin, and one of the pins is a
SC_PKCS15_PIN_FLAG_SO_PIN.
The for loop at line 767 will add a slot for each non SO_PIN or UNBLOCKING_PIN.
But at line 812, the auth_count is still set to the number of pins, even though
the SO_PIN did not cause a new slot to be allocated and thus the test of
hide_empty_tokens will not be used.
With the attached patch, I can get the expected behavior when hide_empty_tokens
= yes in the opensc.conf from pkcs11-tool -L, pkcs11-tool -O and pkcs11-tool -O
-l
There is only 1 slot allocated, the pkcs11-tool -O shows all the public
objects, and pkcs11-tool -O -l (after PIN) shows all the objects, and Heimdal
PKINIT still runs.
I still think that if two or more slots need to be allocated for multiple auth
pins, then all the public objects should be added to each. I have an additional
mod for this too.
Since the cards I am working with only have 1 pin, the attached mods works for
me. Note it looks like the pkcs15-openpgp.c might also be affected by this
change as it defines two pins an auth pin and a SO_PIN, much like the PIV card
does.
git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@3175 c6295689-39f2-0310-b995-f0e70906c6a9
2007-06-21 07:11:21 +00:00
|
|
|
auth_count = found_auth_count;
|
|
|
|
|
2005-07-24 14:06:02 +00:00
|
|
|
/* Add all public objects to a virtual slot without pin protection.
|
|
|
|
* If there's only 1 pin and the hide_empty_tokens option is set,
|
|
|
|
* add the public objects to the slot that corresponds to that pin.
|
|
|
|
*/
|
2009-01-30 11:59:12 +00:00
|
|
|
if (!(auth_count == 1 && (sc_pkcs11_conf.hide_empty_tokens || (fw_data->p15_card->flags & SC_PKCS15_CARD_FLAG_EMULATED))))
|
2005-07-24 14:06:02 +00:00
|
|
|
slot = NULL;
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2003-02-23 17:50:33 +00:00
|
|
|
/* Add all the remaining objects */
|
|
|
|
for (j = 0; j < fw_data->num_objects; j++) {
|
|
|
|
struct pkcs15_any_object *obj = fw_data->objects[j];
|
2007-03-29 10:25:16 +00:00
|
|
|
/* We only have one pin and only the things related to it. */
|
|
|
|
if (hack_enabled)
|
|
|
|
break;
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2003-02-23 17:50:33 +00:00
|
|
|
if (!(obj->base.flags & SC_PKCS11_OBJECT_SEEN)) {
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "%d: Object ('%s',type:%X) was not seen previously\n", j,
|
2010-03-09 17:38:08 +00:00
|
|
|
obj->p15_object->label, obj->p15_object->type);
|
2002-03-18 11:05:21 +00:00
|
|
|
if (!slot) {
|
|
|
|
rv = pkcs15_create_slot(p11card, NULL, &slot);
|
|
|
|
if (rv != CKR_OK)
|
2004-01-08 09:47:23 +00:00
|
|
|
return CKR_OK; /* no more slots available for this card */
|
2002-03-18 11:05:21 +00:00
|
|
|
}
|
2003-02-23 17:50:33 +00:00
|
|
|
pkcs15_add_object(slot, obj, NULL);
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-24 20:45:02 +00:00
|
|
|
/* FIXME Create read/write slots
|
2003-01-03 11:40:11 +00:00
|
|
|
while (slot_allocate(&slot, p11card) == CKR_OK) {
|
2009-01-29 11:50:21 +00:00
|
|
|
if (!sc_pkcs11_conf.hide_empty_tokens && !(fw_data->p15_card->flags & SC_PKCS15_CARD_FLAG_EMULATED)) {
|
2003-01-13 21:38:43 +00:00
|
|
|
slot->slot_info.flags |= CKF_TOKEN_PRESENT;
|
2003-02-23 17:50:33 +00:00
|
|
|
pkcs15_init_token_info(fw_data->p15_card, &slot->token_info);
|
2003-04-14 17:29:19 +00:00
|
|
|
strcpy_bp(slot->token_info.label, fw_data->p15_card->label, 32);
|
2003-01-13 21:38:43 +00:00
|
|
|
slot->token_info.flags |= CKF_TOKEN_INITIALIZED;
|
|
|
|
}
|
2002-04-05 15:01:43 +00:00
|
|
|
}
|
2010-01-24 20:45:02 +00:00
|
|
|
*/
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "All tokens created\n");
|
2002-01-16 22:49:03 +00:00
|
|
|
return CKR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static CK_RV pkcs15_release_token(struct sc_pkcs11_card *p11card, void *fw_token)
|
|
|
|
{
|
2003-06-24 11:26:17 +00:00
|
|
|
unlock_card((struct pkcs15_fw_data *) p11card->fw_data);
|
2009-11-05 18:27:56 +00:00
|
|
|
free(fw_token);
|
2005-02-11 20:09:34 +00:00
|
|
|
return CKR_OK;
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
|
2010-03-09 15:05:29 +00:00
|
|
|
static CK_RV pkcs15_login(struct sc_pkcs11_slot *slot,
|
2002-04-08 15:51:19 +00:00
|
|
|
CK_USER_TYPE userType,
|
2002-01-16 22:49:03 +00:00
|
|
|
CK_CHAR_PTR pPin,
|
|
|
|
CK_ULONG ulPinLen)
|
|
|
|
{
|
2002-01-21 12:49:00 +00:00
|
|
|
int rc;
|
2010-03-09 15:05:29 +00:00
|
|
|
struct sc_pkcs11_card *p11card = slot->card;
|
2003-02-23 17:50:33 +00:00
|
|
|
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) p11card->fw_data;
|
2010-03-08 12:32:35 +00:00
|
|
|
struct sc_pkcs15_card *p15card = fw_data->p15_card;
|
2005-01-19 18:15:43 +00:00
|
|
|
struct sc_pkcs15_object *auth_object;
|
2010-02-20 22:16:19 +00:00
|
|
|
struct sc_pkcs15_pin_info *pin_info;
|
2002-04-08 15:51:19 +00:00
|
|
|
|
|
|
|
switch (userType) {
|
|
|
|
case CKU_USER:
|
2010-03-09 15:05:29 +00:00
|
|
|
auth_object = slot_data_auth(slot->fw_data);
|
2002-04-08 15:51:19 +00:00
|
|
|
if (auth_object == NULL)
|
|
|
|
return CKR_USER_PIN_NOT_INITIALIZED;
|
|
|
|
break;
|
|
|
|
case CKU_SO:
|
|
|
|
/* A card with no SO PIN is treated as if no SO login
|
|
|
|
* is required */
|
2010-03-08 12:32:35 +00:00
|
|
|
rc = sc_pkcs15_find_so_pin(p15card, &auth_object);
|
2003-06-24 11:26:17 +00:00
|
|
|
|
|
|
|
/* If there's no SO PIN on the card, silently
|
|
|
|
* accept any PIN, and lock the card if required */
|
2010-01-08 15:41:07 +00:00
|
|
|
if (rc == SC_ERROR_OBJECT_NOT_FOUND) {
|
|
|
|
rc = 0;
|
|
|
|
if (sc_pkcs11_conf.lock_login)
|
|
|
|
rc = lock_card(fw_data);
|
|
|
|
|
|
|
|
if (sc_pkcs11_conf.pin_unblock_style == SC_PKCS11_PIN_UNBLOCK_SO_LOGGED_INITPIN) {
|
|
|
|
if (ulPinLen && ulPinLen < sizeof(fw_data->user_puk)) {
|
|
|
|
memcpy(fw_data->user_puk, pPin, ulPinLen);
|
|
|
|
fw_data->user_puk_len = ulPinLen;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-02 09:19:27 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "No SOPIN found; returns %d", rc);
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rc, "C_Login");
|
2010-01-08 15:41:07 +00:00
|
|
|
}
|
|
|
|
else if (rc < 0) {
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rc, "C_Login");
|
2010-01-08 15:41:07 +00:00
|
|
|
}
|
|
|
|
|
2002-04-08 15:51:19 +00:00
|
|
|
break;
|
2010-01-08 15:41:07 +00:00
|
|
|
case CKU_CONTEXT_SPECIFIC:
|
2010-11-24 20:28:30 +00:00
|
|
|
/*
|
|
|
|
* A session should already be open for user or SO
|
|
|
|
* All we need to do is authenticate to the card
|
|
|
|
* using the correct auth_object.
|
|
|
|
* TODO: handle the CK_SO case
|
|
|
|
*/
|
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "context specific login %d",
|
|
|
|
slot->login_user);
|
|
|
|
if (slot->login_user == CKU_USER) {
|
|
|
|
auth_object = slot_data_auth(slot->fw_data);
|
|
|
|
if (auth_object == NULL)
|
|
|
|
return CKR_USER_PIN_NOT_INITIALIZED;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* TODO looks like this was never executed,
|
|
|
|
* And even if it was, why the lock as a session
|
|
|
|
* should already be open and the card locked.
|
|
|
|
*/
|
2010-01-08 15:41:07 +00:00
|
|
|
/* For a while, used only to unblock User PIN. */
|
|
|
|
rc = 0;
|
|
|
|
if (sc_pkcs11_conf.lock_login)
|
|
|
|
rc = lock_card(fw_data);
|
|
|
|
#if 0
|
|
|
|
/* TODO: Look for pkcs15 auth object with 'unblockingPin' flag activated.
|
|
|
|
* If exists, do verification of PIN (in fact PUK). */
|
|
|
|
if (sc_pkcs11_conf.pin_unblock_style == SC_PKCS11_PIN_UNBLOCK_SCONTEXT_SETPIN) {
|
|
|
|
if (ulPinLen && ulPinLen < sizeof(fw_data->user_puk)) {
|
|
|
|
memcpy(fw_data->user_puk, pPin, ulPinLen);
|
|
|
|
fw_data->user_puk_len = ulPinLen;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2010-09-02 09:19:27 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "context specific login returns %d", rc);
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rc, "C_Login");
|
2002-04-08 15:51:19 +00:00
|
|
|
default:
|
|
|
|
return CKR_USER_TYPE_INVALID;
|
|
|
|
}
|
2010-02-20 22:16:19 +00:00
|
|
|
pin_info = (struct sc_pkcs15_pin_info *) auth_object->data;
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2010-01-24 20:45:02 +00:00
|
|
|
if (p11card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) {
|
2003-01-06 19:28:48 +00:00
|
|
|
/* pPin should be NULL in case of a pin pad reader, but
|
|
|
|
* some apps (e.g. older Netscapes) don't know about it.
|
|
|
|
* So we don't require that pPin == NULL, but set it to
|
|
|
|
* NULL ourselves. This way, you can supply an empty (if
|
|
|
|
* possible) or fake PIN if an application asks a PIN).
|
|
|
|
*/
|
2003-10-18 12:40:22 +00:00
|
|
|
/* But we want to be able to specify a PIN on the command
|
|
|
|
* line (e.g. for the test scripts). So we don't do anything
|
|
|
|
* here - this gives the user the choice of entering
|
|
|
|
* an empty pin (which makes us use the pin pad) or
|
|
|
|
* a valid pin (which is processed normally). --okir */
|
|
|
|
if (ulPinLen == 0)
|
|
|
|
pPin = NULL;
|
2008-02-29 10:18:51 +00:00
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* If PIN is out of range,
|
|
|
|
* it cannot be correct.
|
|
|
|
*/
|
2010-02-20 22:16:19 +00:00
|
|
|
if (ulPinLen < pin_info->min_length ||
|
|
|
|
ulPinLen > pin_info->max_length)
|
2008-02-29 10:18:51 +00:00
|
|
|
return CKR_PIN_INCORRECT;
|
|
|
|
}
|
2002-03-07 11:57:49 +00:00
|
|
|
|
2010-12-01 20:08:42 +00:00
|
|
|
|
2003-12-10 14:52:58 +00:00
|
|
|
/* By default, we make the reader resource manager keep other
|
|
|
|
* processes from accessing the card while we're logged in.
|
|
|
|
* Otherwise an attacker could perform some crypto operation
|
|
|
|
* after we've authenticated with the card */
|
2010-11-24 20:28:30 +00:00
|
|
|
|
|
|
|
/* Context specific login is not real login but only a
|
|
|
|
* reassertion of the PIN to the card.
|
|
|
|
* And we don't want to do any extra operations to the card
|
|
|
|
* that could invalidate the assertion of the pin
|
|
|
|
* before the crypto operation that requires the assertion
|
|
|
|
*/
|
|
|
|
if (userType != CKU_CONTEXT_SPECIFIC) {
|
2003-06-24 11:26:17 +00:00
|
|
|
if (sc_pkcs11_conf.lock_login && (rc = lock_card(fw_data)) < 0)
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rc, "C_Login");
|
2010-11-24 20:28:30 +00:00
|
|
|
}
|
2002-03-12 14:36:40 +00:00
|
|
|
|
2010-03-10 09:23:01 +00:00
|
|
|
rc = sc_pkcs15_verify_pin(p15card, auth_object, pPin, ulPinLen);
|
2010-09-05 16:53:08 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "PKCS15 verify PIN returned %d", rc);
|
|
|
|
|
|
|
|
if (rc != SC_SUCCESS)
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rc, "C_Login");
|
2010-03-09 17:38:08 +00:00
|
|
|
|
|
|
|
if (userType == CKU_USER) {
|
2010-11-18 23:31:08 +00:00
|
|
|
sc_pkcs15_object_t *p15_obj = p15card->obj_list;
|
|
|
|
sc_pkcs15_search_key_t sk;
|
2010-03-09 17:38:08 +00:00
|
|
|
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "Check if pkcs15 object list can be completed.");
|
2010-03-09 17:38:08 +00:00
|
|
|
|
2010-11-18 23:31:08 +00:00
|
|
|
/* Ensure non empty list */
|
|
|
|
if (p15_obj == NULL)
|
|
|
|
return CKR_OK;
|
2010-03-09 17:38:08 +00:00
|
|
|
|
2010-11-18 23:31:08 +00:00
|
|
|
/* Select last object in list */
|
|
|
|
while(p15_obj->next)
|
|
|
|
p15_obj = p15_obj->next;
|
2010-03-09 17:38:08 +00:00
|
|
|
|
2010-11-18 23:31:08 +00:00
|
|
|
/* Trigger enumeration of EF.XXX files */
|
|
|
|
memset(&sk, 0, sizeof(sk));
|
|
|
|
sk.class_mask = SC_PKCS15_SEARCH_CLASS_PRKEY | SC_PKCS15_SEARCH_CLASS_PUBKEY |
|
|
|
|
SC_PKCS15_SEARCH_CLASS_CERT | SC_PKCS15_SEARCH_CLASS_DATA;
|
|
|
|
sc_pkcs15_search_objects(p15card, &sk, NULL, 0);
|
2010-03-09 17:38:08 +00:00
|
|
|
|
2010-11-18 23:31:08 +00:00
|
|
|
/* Iterate over newly discovered objects */
|
|
|
|
while(p15_obj->next) {
|
|
|
|
struct pkcs15_any_object *fw_obj;
|
2010-03-09 17:38:08 +00:00
|
|
|
|
2010-11-18 23:31:08 +00:00
|
|
|
p15_obj = p15_obj->next;
|
|
|
|
|
|
|
|
if (!sc_pkcs15_compare_id(&pin_info->auth_id, &p15_obj->auth_id))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
switch (p15_obj->type & SC_PKCS15_TYPE_CLASS_MASK) {
|
|
|
|
case SC_PKCS15_TYPE_PRKEY:
|
|
|
|
__pkcs15_create_prkey_object(fw_data, p15_obj, &fw_obj); break;
|
|
|
|
case SC_PKCS15_TYPE_PUBKEY:
|
|
|
|
__pkcs15_create_pubkey_object(fw_data, p15_obj, &fw_obj); break;
|
|
|
|
case SC_PKCS15_TYPE_CERT:
|
|
|
|
__pkcs15_create_cert_object(fw_data, p15_obj, &fw_obj); break;
|
|
|
|
case SC_PKCS15_TYPE_DATA_OBJECT:
|
|
|
|
__pkcs15_create_data_object(fw_data, p15_obj, &fw_obj); break;
|
|
|
|
default: continue;
|
2010-03-09 17:38:08 +00:00
|
|
|
}
|
2010-11-18 23:31:08 +00:00
|
|
|
|
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "new object found: type=0x%03X", p15_obj->type);
|
|
|
|
pkcs15_add_object(slot, fw_obj, NULL);
|
2010-03-09 17:38:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-18 23:31:08 +00:00
|
|
|
return CKR_OK;
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static CK_RV pkcs15_logout(struct sc_pkcs11_card *p11card, void *fw_token)
|
|
|
|
{
|
2003-02-23 17:50:33 +00:00
|
|
|
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) p11card->fw_data;
|
2010-12-08 03:31:07 +00:00
|
|
|
CK_RV ret = CKR_OK;
|
|
|
|
int rc;
|
2010-01-08 15:41:07 +00:00
|
|
|
|
|
|
|
memset(fw_data->user_puk, 0, sizeof(fw_data->user_puk));
|
|
|
|
fw_data->user_puk_len = 0;
|
|
|
|
|
2009-10-22 08:59:59 +00:00
|
|
|
sc_pkcs15_pincache_clear(fw_data->p15_card);
|
2003-05-20 08:30:46 +00:00
|
|
|
|
2010-12-08 03:31:07 +00:00
|
|
|
rc = sc_logout(fw_data->p15_card->card);
|
2010-12-29 10:45:01 +00:00
|
|
|
|
|
|
|
/* Ignore missing card specific logout functions. #302 */
|
|
|
|
if (rc == SC_ERROR_NOT_SUPPORTED)
|
|
|
|
rc = SC_SUCCESS;
|
|
|
|
|
2010-12-08 03:31:07 +00:00
|
|
|
if (rc != SC_SUCCESS)
|
|
|
|
ret = sc_to_cryptoki_error(rc, "C_Logout");
|
|
|
|
|
|
|
|
if (sc_pkcs11_conf.lock_login) {
|
2003-06-24 11:26:17 +00:00
|
|
|
rc = unlock_card(fw_data);
|
2010-12-08 03:31:07 +00:00
|
|
|
if (rc != SC_SUCCESS)
|
|
|
|
ret = sc_to_cryptoki_error(rc, "C_Logout");
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
|
2002-03-20 15:04:14 +00:00
|
|
|
static CK_RV pkcs15_change_pin(struct sc_pkcs11_card *p11card,
|
2010-01-08 15:41:07 +00:00
|
|
|
void *fw_token, int login_user,
|
2002-03-20 15:04:14 +00:00
|
|
|
CK_CHAR_PTR pOldPin, CK_ULONG ulOldLen,
|
|
|
|
CK_CHAR_PTR pNewPin, CK_ULONG ulNewLen)
|
|
|
|
{
|
|
|
|
int rc;
|
2003-02-23 17:50:33 +00:00
|
|
|
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) p11card->fw_data;
|
2010-03-10 09:23:01 +00:00
|
|
|
struct sc_pkcs15_pin_info *pin_info;
|
2010-03-10 15:03:20 +00:00
|
|
|
struct sc_pkcs15_object *pin_obj;
|
2010-03-10 09:23:01 +00:00
|
|
|
|
|
|
|
if (!(pin_obj = slot_data_auth(fw_token)))
|
|
|
|
return CKR_USER_PIN_NOT_INITIALIZED;
|
2002-04-11 15:17:33 +00:00
|
|
|
|
2010-03-10 09:23:01 +00:00
|
|
|
if (!(pin_info = slot_data_pin_info(fw_token)))
|
2002-04-11 15:17:33 +00:00
|
|
|
return CKR_USER_PIN_NOT_INITIALIZED;
|
2002-03-20 15:04:14 +00:00
|
|
|
|
2010-01-24 20:45:02 +00:00
|
|
|
if (p11card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) {
|
2003-01-06 19:28:48 +00:00
|
|
|
/* pPin should be NULL in case of a pin pad reader, but
|
|
|
|
* some apps (e.g. older Netscapes) don't know about it.
|
|
|
|
* So we don't require that pPin == NULL, but set it to
|
|
|
|
* NULL ourselves. This way, you can supply an empty (if
|
|
|
|
* possible) or fake PIN if an application asks a PIN).
|
|
|
|
*/
|
|
|
|
pOldPin = pNewPin = NULL;
|
|
|
|
ulOldLen = ulNewLen = 0;
|
2010-01-08 15:41:07 +00:00
|
|
|
}
|
2010-03-10 09:23:01 +00:00
|
|
|
else if (ulNewLen < pin_info->min_length || ulNewLen > pin_info->max_length) {
|
2002-03-20 15:04:14 +00:00
|
|
|
return CKR_PIN_LEN_RANGE;
|
2010-01-08 15:41:07 +00:00
|
|
|
}
|
2002-03-20 15:04:14 +00:00
|
|
|
|
2010-01-08 15:41:07 +00:00
|
|
|
if (login_user < 0) {
|
|
|
|
if (sc_pkcs11_conf.pin_unblock_style != SC_PKCS11_PIN_UNBLOCK_UNLOGGED_SETPIN) {
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "PIN unlock is not allowed in unlogged session");
|
2010-01-08 15:41:07 +00:00
|
|
|
return CKR_FUNCTION_NOT_SUPPORTED;
|
|
|
|
}
|
2010-03-10 09:23:01 +00:00
|
|
|
rc = sc_pkcs15_unblock_pin(fw_data->p15_card, pin_obj, pOldPin, ulOldLen, pNewPin, ulNewLen);
|
2010-01-08 15:41:07 +00:00
|
|
|
}
|
|
|
|
else if (login_user == CKU_CONTEXT_SPECIFIC) {
|
|
|
|
if (sc_pkcs11_conf.pin_unblock_style != SC_PKCS11_PIN_UNBLOCK_SCONTEXT_SETPIN) {
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "PIN unlock is not allowed with CKU_CONTEXT_SPECIFIC login");
|
2010-01-08 15:41:07 +00:00
|
|
|
return CKR_FUNCTION_NOT_SUPPORTED;
|
|
|
|
}
|
2010-03-10 09:23:01 +00:00
|
|
|
rc = sc_pkcs15_unblock_pin(fw_data->p15_card, pin_obj, pOldPin, ulOldLen, pNewPin, ulNewLen);
|
2010-01-08 15:41:07 +00:00
|
|
|
}
|
|
|
|
else if (login_user == CKU_USER) {
|
2010-03-10 09:23:01 +00:00
|
|
|
rc = sc_pkcs15_change_pin(fw_data->p15_card, pin_obj, pOldPin, ulOldLen, pNewPin, ulNewLen);
|
2010-01-08 15:41:07 +00:00
|
|
|
}
|
|
|
|
else {
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "cannot change PIN: non supported login type: %i", login_user);
|
2010-01-08 15:41:07 +00:00
|
|
|
return CKR_FUNCTION_NOT_SUPPORTED;
|
|
|
|
}
|
|
|
|
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "PIN change returns %d\n", rc);
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rc, "C_SetPIN");
|
2002-03-20 15:04:14 +00:00
|
|
|
}
|
|
|
|
|
2002-06-20 13:16:22 +00:00
|
|
|
#ifdef USE_PKCS15_INIT
|
2002-04-08 15:51:19 +00:00
|
|
|
static CK_RV pkcs15_init_pin(struct sc_pkcs11_card *p11card,
|
|
|
|
struct sc_pkcs11_slot *slot,
|
|
|
|
CK_CHAR_PTR pPin, CK_ULONG ulPinLen)
|
|
|
|
{
|
2003-02-23 17:50:33 +00:00
|
|
|
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) p11card->fw_data;
|
2002-04-08 15:51:19 +00:00
|
|
|
struct sc_pkcs15init_pinargs args;
|
|
|
|
struct sc_profile *profile;
|
|
|
|
struct sc_pkcs15_object *auth_obj;
|
2010-01-08 15:41:07 +00:00
|
|
|
struct sc_pkcs15_pin_info *pin_info;
|
2002-04-08 15:51:19 +00:00
|
|
|
int rc;
|
|
|
|
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "pkcs15 init PIN: pin %p:%d\n", pPin, ulPinLen);
|
2010-03-10 09:23:01 +00:00
|
|
|
|
2010-01-08 15:41:07 +00:00
|
|
|
pin_info = slot_data_pin_info(slot->fw_data);
|
|
|
|
if (pin_info && sc_pkcs11_conf.pin_unblock_style == SC_PKCS11_PIN_UNBLOCK_SO_LOGGED_INITPIN) {
|
2010-03-10 09:23:01 +00:00
|
|
|
auth_obj = slot_data_auth(slot->fw_data);
|
2010-01-08 15:41:07 +00:00
|
|
|
if (fw_data->user_puk_len) {
|
2010-03-10 09:23:01 +00:00
|
|
|
rc = sc_pkcs15_unblock_pin(fw_data->p15_card, auth_obj,
|
2010-01-08 15:41:07 +00:00
|
|
|
fw_data->user_puk, fw_data->user_puk_len, pPin, ulPinLen);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
#if 0
|
|
|
|
/* TODO: Actually sc_pkcs15_unblock_pin() do not accepts zero length value as a PUK argument.
|
|
|
|
* It's usefull for the cards that do not supports modes 00 and 01
|
|
|
|
* of ISO 'RESET RETRY COUNTER' command. */
|
2010-03-10 09:23:01 +00:00
|
|
|
rc = sc_pkcs15_unblock_pin(fw_data->p15_card, auth_obj, NULL, 0, pPin, ulPinLen);
|
2010-01-08 15:41:07 +00:00
|
|
|
#else
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(SC_ERROR_NOT_SUPPORTED, "C_InitPIN");
|
2010-01-08 15:41:07 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rc, "C_InitPIN");
|
2010-01-08 15:41:07 +00:00
|
|
|
}
|
|
|
|
|
2005-10-01 18:51:34 +00:00
|
|
|
rc = sc_lock(p11card->card);
|
2002-04-08 15:51:19 +00:00
|
|
|
if (rc < 0)
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rc, "C_InitPIN");
|
2002-04-08 15:51:19 +00:00
|
|
|
|
2005-10-01 18:51:34 +00:00
|
|
|
rc = sc_pkcs15init_bind(p11card->card, "pkcs15", NULL, &profile);
|
|
|
|
if (rc < 0) {
|
2009-10-22 09:18:16 +00:00
|
|
|
sc_unlock(p11card->card);
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rc, "C_InitPIN");
|
2005-10-01 18:51:34 +00:00
|
|
|
}
|
|
|
|
|
2002-04-08 15:51:19 +00:00
|
|
|
memset(&args, 0, sizeof(args));
|
|
|
|
args.label = "User PIN";
|
|
|
|
args.pin = pPin;
|
|
|
|
args.pin_len = ulPinLen;
|
2003-02-23 17:50:33 +00:00
|
|
|
rc = sc_pkcs15init_store_pin(fw_data->p15_card, profile, &args);
|
2002-04-08 15:51:19 +00:00
|
|
|
|
|
|
|
sc_pkcs15init_unbind(profile);
|
2009-10-22 09:18:16 +00:00
|
|
|
sc_unlock(p11card->card);
|
2002-04-08 15:51:19 +00:00
|
|
|
if (rc < 0)
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rc, "C_InitPIN");
|
2002-04-08 15:51:19 +00:00
|
|
|
|
2003-02-23 17:50:33 +00:00
|
|
|
rc = sc_pkcs15_find_pin_by_auth_id(fw_data->p15_card, &args.auth_id, &auth_obj);
|
2002-04-08 15:51:19 +00:00
|
|
|
if (rc < 0)
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rc, "C_InitPIN");
|
2002-04-08 15:51:19 +00:00
|
|
|
|
|
|
|
/* Re-initialize the slot */
|
2002-04-11 15:17:33 +00:00
|
|
|
free(slot->fw_data);
|
2003-02-23 17:50:33 +00:00
|
|
|
pkcs15_init_slot(fw_data->p15_card, slot, auth_obj);
|
2002-04-08 15:51:19 +00:00
|
|
|
|
2003-10-14 08:33:20 +00:00
|
|
|
pin_info = (sc_pkcs15_pin_info_t *) auth_obj->data;
|
2002-04-08 15:51:19 +00:00
|
|
|
return CKR_OK;
|
|
|
|
}
|
|
|
|
|
2002-04-11 15:17:33 +00:00
|
|
|
static CK_RV pkcs15_create_private_key(struct sc_pkcs11_card *p11card,
|
|
|
|
struct sc_pkcs11_slot *slot,
|
|
|
|
struct sc_profile *profile,
|
|
|
|
CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
|
|
|
|
CK_OBJECT_HANDLE_PTR phObject)
|
|
|
|
{
|
2003-02-23 17:50:33 +00:00
|
|
|
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) p11card->fw_data;
|
2002-04-15 13:42:10 +00:00
|
|
|
struct sc_pkcs15init_prkeyargs args;
|
2003-06-04 12:26:06 +00:00
|
|
|
struct pkcs15_any_object *key_any_obj;
|
2002-04-11 15:17:33 +00:00
|
|
|
struct sc_pkcs15_object *key_obj;
|
|
|
|
struct sc_pkcs15_pin_info *pin;
|
|
|
|
CK_KEY_TYPE key_type;
|
2002-04-15 13:42:10 +00:00
|
|
|
struct sc_pkcs15_prkey_rsa *rsa;
|
2010-12-01 20:08:42 +00:00
|
|
|
struct sc_pkcs15_prkey_ec *ec;
|
2011-05-29 18:35:34 +00:00
|
|
|
struct sc_pkcs15_prkey_gostr3410 *gost;
|
2002-04-11 15:17:33 +00:00
|
|
|
int rc, rv;
|
2010-04-15 15:37:55 +00:00
|
|
|
char label[SC_PKCS15_MAX_LABEL_SIZE];
|
2002-04-11 15:17:33 +00:00
|
|
|
|
|
|
|
memset(&args, 0, sizeof(args));
|
|
|
|
|
|
|
|
/* See if the "slot" is pin protected. If so, get the
|
|
|
|
* PIN id */
|
|
|
|
if ((pin = slot_data_pin_info(slot->fw_data)) != NULL)
|
|
|
|
args.auth_id = pin->auth_id;
|
|
|
|
|
|
|
|
/* Get the key type */
|
|
|
|
rv = attr_find(pTemplate, ulCount, CKA_KEY_TYPE, &key_type, NULL);
|
|
|
|
if (rv != CKR_OK)
|
|
|
|
return rv;
|
2010-12-01 20:08:42 +00:00
|
|
|
switch (key_type) {
|
|
|
|
case CKK_RSA:
|
|
|
|
args.key.algorithm = SC_ALGORITHM_RSA;
|
|
|
|
rsa = &args.key.u.rsa;
|
|
|
|
break;
|
|
|
|
case CKK_EC:
|
|
|
|
args.key.algorithm = SC_ALGORITHM_EC;
|
|
|
|
ec = &args.key.u.ec;
|
|
|
|
/* TODO: -DEE Do not have PKCS15 card with EC to test this */
|
|
|
|
/* fall through */
|
2011-05-29 18:35:34 +00:00
|
|
|
case CKK_GOSTR3410:
|
|
|
|
set_gost_params(&args.params.gost, NULL, pTemplate, ulCount, NULL, 0);
|
|
|
|
args.key.algorithm = SC_ALGORITHM_GOSTR3410;
|
|
|
|
gost = &args.key.u.gostr3410;
|
|
|
|
break;
|
2010-12-01 20:08:42 +00:00
|
|
|
default:
|
|
|
|
return CKR_ATTRIBUTE_VALUE_INVALID;
|
|
|
|
}
|
|
|
|
|
2002-04-11 15:17:33 +00:00
|
|
|
while (ulCount--) {
|
|
|
|
CK_ATTRIBUTE_PTR attr = pTemplate++;
|
2002-04-15 13:42:10 +00:00
|
|
|
sc_pkcs15_bignum_t *bn = NULL;
|
2002-04-11 15:17:33 +00:00
|
|
|
|
|
|
|
switch (attr->type) {
|
|
|
|
/* Skip attrs we already know or don't care for */
|
|
|
|
case CKA_CLASS:
|
|
|
|
case CKA_KEY_TYPE:
|
|
|
|
case CKA_MODULUS_BITS:
|
|
|
|
case CKA_PRIVATE:
|
2005-02-11 20:09:34 +00:00
|
|
|
break;
|
2002-04-11 15:17:33 +00:00
|
|
|
case CKA_LABEL:
|
2010-04-15 15:37:55 +00:00
|
|
|
args.label = set_cka_label(attr, label);
|
2002-04-11 15:17:33 +00:00
|
|
|
break;
|
|
|
|
case CKA_ID:
|
|
|
|
args.id.len = sizeof(args.id.value);
|
|
|
|
rv = attr_extract(attr, args.id.value, &args.id.len);
|
|
|
|
if (rv != CKR_OK)
|
|
|
|
goto out;
|
|
|
|
break;
|
|
|
|
case CKA_MODULUS:
|
2002-04-15 13:42:10 +00:00
|
|
|
bn = &rsa->modulus; break;
|
2002-04-11 15:17:33 +00:00
|
|
|
case CKA_PUBLIC_EXPONENT:
|
2002-04-15 13:42:10 +00:00
|
|
|
bn = &rsa->exponent; break;
|
2002-04-11 15:17:33 +00:00
|
|
|
case CKA_PRIVATE_EXPONENT:
|
2002-04-15 13:42:10 +00:00
|
|
|
bn = &rsa->d; break;
|
2002-04-11 15:17:33 +00:00
|
|
|
case CKA_PRIME_1:
|
2002-04-15 13:42:10 +00:00
|
|
|
bn = &rsa->p; break;
|
2002-04-11 15:17:33 +00:00
|
|
|
case CKA_PRIME_2:
|
2002-04-15 13:42:10 +00:00
|
|
|
bn = &rsa->q; break;
|
2011-05-29 18:35:34 +00:00
|
|
|
case CKA_VALUE:
|
|
|
|
if (key_type == CKK_GOSTR3410)
|
|
|
|
bn = &gost->d;
|
|
|
|
break;
|
|
|
|
|
2002-04-11 15:17:33 +00:00
|
|
|
default:
|
|
|
|
/* ignore unknown attrs, or flag error? */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bn) {
|
2011-05-29 18:35:34 +00:00
|
|
|
if (attr->ulValueLen > 1024) {
|
2002-04-11 15:17:33 +00:00
|
|
|
return CKR_ATTRIBUTE_VALUE_INVALID;
|
2011-05-29 18:35:34 +00:00
|
|
|
}
|
2002-04-15 13:42:10 +00:00
|
|
|
bn->len = attr->ulValueLen;
|
2002-04-19 14:23:31 +00:00
|
|
|
bn->data = (u8 *) attr->pValue;
|
2002-04-11 15:17:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-29 18:35:34 +00:00
|
|
|
if (key_type == CKK_RSA) {
|
|
|
|
if (!rsa->modulus.len || !rsa->exponent.len || !rsa->d.len || !rsa->p.len || !rsa->q.len) {
|
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "Template to store the RSA key is incomplete");
|
|
|
|
rv = CKR_TEMPLATE_INCOMPLETE;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (key_type == CKK_GOSTR3410) {
|
|
|
|
if (!gost->d.len) {
|
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "Template to store the GOST key is incomplete");
|
|
|
|
return CKR_ATTRIBUTE_VALUE_INVALID;
|
|
|
|
}
|
|
|
|
/* CKA_VALUE arrives in little endian form. pkcs15init framework expects it in a big endian one. */
|
|
|
|
rc = sc_mem_reverse(gost->d.data, gost->d.len);
|
|
|
|
if (rv) {
|
|
|
|
rv = sc_to_cryptoki_error(rc, "C_CreateObject");
|
|
|
|
goto out;
|
|
|
|
}
|
2002-04-11 15:17:33 +00:00
|
|
|
}
|
|
|
|
|
2003-02-23 17:50:33 +00:00
|
|
|
rc = sc_pkcs15init_store_private_key(fw_data->p15_card, profile, &args, &key_obj);
|
2002-04-11 15:17:33 +00:00
|
|
|
if (rc < 0) {
|
2010-04-21 10:51:13 +00:00
|
|
|
rv = sc_to_cryptoki_error(rc, "C_CreateObject");
|
2002-04-11 15:17:33 +00:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create a new pkcs11 object for it */
|
2003-06-04 12:26:06 +00:00
|
|
|
__pkcs15_create_prkey_object(fw_data, key_obj, &key_any_obj);
|
|
|
|
pkcs15_add_object(slot, key_any_obj, phObject);
|
2002-04-11 15:17:33 +00:00
|
|
|
|
|
|
|
rv = CKR_OK;
|
|
|
|
|
2002-04-15 13:42:10 +00:00
|
|
|
out: return rv;
|
2002-04-11 15:17:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static CK_RV pkcs15_create_public_key(struct sc_pkcs11_card *p11card,
|
|
|
|
struct sc_pkcs11_slot *slot,
|
|
|
|
struct sc_profile *profile,
|
|
|
|
CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
|
|
|
|
CK_OBJECT_HANDLE_PTR phObject)
|
|
|
|
{
|
2003-02-23 17:50:33 +00:00
|
|
|
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) p11card->fw_data;
|
2002-04-15 13:42:10 +00:00
|
|
|
struct sc_pkcs15init_pubkeyargs args;
|
2003-06-04 12:26:06 +00:00
|
|
|
struct pkcs15_any_object *key_any_obj;
|
2002-04-11 15:17:33 +00:00
|
|
|
struct sc_pkcs15_object *key_obj;
|
|
|
|
struct sc_pkcs15_pin_info *pin;
|
2005-02-11 20:09:34 +00:00
|
|
|
CK_KEY_TYPE key_type;
|
2002-04-15 13:42:10 +00:00
|
|
|
struct sc_pkcs15_pubkey_rsa *rsa;
|
2005-02-11 20:09:34 +00:00
|
|
|
int rc, rv;
|
2010-04-15 15:37:55 +00:00
|
|
|
char label[SC_PKCS15_MAX_LABEL_SIZE];
|
2002-04-11 15:17:33 +00:00
|
|
|
|
|
|
|
memset(&args, 0, sizeof(args));
|
|
|
|
|
|
|
|
/* See if the "slot" is pin protected. If so, get the
|
|
|
|
* PIN id */
|
|
|
|
if ((pin = slot_data_pin_info(slot->fw_data)) != NULL)
|
|
|
|
args.auth_id = pin->auth_id;
|
|
|
|
|
|
|
|
/* Get the key type */
|
|
|
|
rv = attr_find(pTemplate, ulCount, CKA_KEY_TYPE, &key_type, NULL);
|
|
|
|
if (rv != CKR_OK)
|
|
|
|
return rv;
|
2010-12-01 20:08:42 +00:00
|
|
|
switch (key_type) {
|
|
|
|
case CKK_RSA:
|
|
|
|
args.key.algorithm = SC_ALGORITHM_RSA;
|
|
|
|
rsa = &args.key.u.rsa;
|
|
|
|
break;
|
|
|
|
case CKK_EC:
|
|
|
|
/* TODO: -DEE Do not have real pkcs15 card with EC */
|
|
|
|
/* fall through */
|
|
|
|
default:
|
|
|
|
return CKR_ATTRIBUTE_VALUE_INVALID;
|
|
|
|
}
|
2002-04-11 15:17:33 +00:00
|
|
|
|
|
|
|
rv = CKR_OK;
|
|
|
|
while (ulCount--) {
|
|
|
|
CK_ATTRIBUTE_PTR attr = pTemplate++;
|
2002-04-15 13:42:10 +00:00
|
|
|
sc_pkcs15_bignum_t *bn = NULL;
|
2002-04-11 15:17:33 +00:00
|
|
|
|
|
|
|
switch (attr->type) {
|
|
|
|
/* Skip attrs we already know or don't care for */
|
|
|
|
case CKA_CLASS:
|
|
|
|
case CKA_KEY_TYPE:
|
|
|
|
case CKA_MODULUS_BITS:
|
|
|
|
case CKA_PRIVATE:
|
2005-02-11 20:09:34 +00:00
|
|
|
break;
|
2002-04-11 15:17:33 +00:00
|
|
|
case CKA_LABEL:
|
2010-04-15 15:37:55 +00:00
|
|
|
args.label = set_cka_label(attr, label);
|
2002-04-11 15:17:33 +00:00
|
|
|
break;
|
|
|
|
case CKA_ID:
|
|
|
|
args.id.len = sizeof(args.id.value);
|
|
|
|
rv = attr_extract(attr, args.id.value, &args.id.len);
|
|
|
|
if (rv != CKR_OK)
|
|
|
|
goto out;
|
|
|
|
break;
|
|
|
|
case CKA_MODULUS:
|
2002-04-15 13:42:10 +00:00
|
|
|
bn = &rsa->modulus; break;
|
2002-04-11 15:17:33 +00:00
|
|
|
case CKA_PUBLIC_EXPONENT:
|
2002-04-15 13:42:10 +00:00
|
|
|
bn = &rsa->exponent; break;
|
2002-04-11 15:17:33 +00:00
|
|
|
default:
|
|
|
|
/* ignore unknown attrs, or flag error? */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bn) {
|
|
|
|
if (attr->ulValueLen > 1024)
|
|
|
|
return CKR_ATTRIBUTE_VALUE_INVALID;
|
2002-04-15 13:42:10 +00:00
|
|
|
bn->len = attr->ulValueLen;
|
2002-04-19 14:23:31 +00:00
|
|
|
bn->data = (u8 *) attr->pValue;
|
2002-04-11 15:17:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-04-15 13:42:10 +00:00
|
|
|
if (!rsa->modulus.len || !rsa->exponent.len) {
|
2002-04-11 15:17:33 +00:00
|
|
|
rv = CKR_TEMPLATE_INCOMPLETE;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2003-02-23 17:50:33 +00:00
|
|
|
rc = sc_pkcs15init_store_public_key(fw_data->p15_card, profile, &args, &key_obj);
|
2002-04-11 15:17:33 +00:00
|
|
|
if (rc < 0) {
|
2010-04-21 10:51:13 +00:00
|
|
|
rv = sc_to_cryptoki_error(rc, "C_CreateObject");
|
2002-04-11 15:17:33 +00:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create a new pkcs11 object for it */
|
2003-06-04 12:26:06 +00:00
|
|
|
__pkcs15_create_pubkey_object(fw_data, key_obj, &key_any_obj);
|
|
|
|
pkcs15_add_object(slot, key_any_obj, phObject);
|
2002-04-11 15:17:33 +00:00
|
|
|
|
|
|
|
rv = CKR_OK;
|
|
|
|
|
2002-04-15 13:42:10 +00:00
|
|
|
out: return rv;
|
2002-04-11 15:17:33 +00:00
|
|
|
}
|
|
|
|
|
2002-04-13 19:00:37 +00:00
|
|
|
static CK_RV pkcs15_create_certificate(struct sc_pkcs11_card *p11card,
|
|
|
|
struct sc_pkcs11_slot *slot,
|
|
|
|
struct sc_profile *profile,
|
|
|
|
CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
|
|
|
|
CK_OBJECT_HANDLE_PTR phObject)
|
|
|
|
{
|
2003-02-23 17:50:33 +00:00
|
|
|
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) p11card->fw_data;
|
2002-04-13 19:00:37 +00:00
|
|
|
struct sc_pkcs15init_certargs args;
|
2003-06-04 12:26:06 +00:00
|
|
|
struct pkcs15_any_object *cert_any_obj;
|
|
|
|
struct sc_pkcs15_object *cert_obj;
|
2002-04-13 19:00:37 +00:00
|
|
|
CK_CERTIFICATE_TYPE cert_type;
|
|
|
|
CK_BBOOL bValue;
|
|
|
|
int rc, rv;
|
2010-04-15 15:37:55 +00:00
|
|
|
char label[SC_PKCS15_MAX_LABEL_SIZE];
|
2002-04-13 19:00:37 +00:00
|
|
|
|
|
|
|
memset(&args, 0, sizeof(args));
|
|
|
|
|
|
|
|
/* Get the key type */
|
|
|
|
rv = attr_find(pTemplate, ulCount, CKA_CERTIFICATE_TYPE,
|
|
|
|
&cert_type, NULL);
|
|
|
|
if (rv != CKR_OK)
|
|
|
|
return rv;
|
|
|
|
if (cert_type != CKC_X_509)
|
2003-06-03 13:57:52 +00:00
|
|
|
return CKR_ATTRIBUTE_VALUE_INVALID;
|
2002-04-13 19:00:37 +00:00
|
|
|
|
|
|
|
rv = CKR_OK;
|
|
|
|
while (ulCount--) {
|
|
|
|
CK_ATTRIBUTE_PTR attr = pTemplate++;
|
|
|
|
|
|
|
|
switch (attr->type) {
|
|
|
|
/* Skip attrs we already know or don't care for */
|
|
|
|
case CKA_CLASS:
|
2005-02-11 20:09:34 +00:00
|
|
|
break;
|
2002-04-13 19:00:37 +00:00
|
|
|
case CKA_PRIVATE:
|
|
|
|
rv = attr_extract(attr, &bValue, NULL);
|
|
|
|
if (bValue) {
|
|
|
|
rv = CKR_TEMPLATE_INCONSISTENT;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CKA_LABEL:
|
2010-04-15 15:37:55 +00:00
|
|
|
args.label = set_cka_label(attr, label);
|
2002-04-13 19:00:37 +00:00
|
|
|
break;
|
|
|
|
case CKA_ID:
|
|
|
|
args.id.len = sizeof(args.id.value);
|
|
|
|
rv = attr_extract(attr, args.id.value, &args.id.len);
|
|
|
|
if (rv != CKR_OK)
|
|
|
|
goto out;
|
|
|
|
break;
|
|
|
|
case CKA_VALUE:
|
2002-04-15 13:42:10 +00:00
|
|
|
args.der_encoded.len = attr->ulValueLen;
|
2002-04-19 14:23:31 +00:00
|
|
|
args.der_encoded.value = (u8 *) attr->pValue;
|
2002-04-13 19:00:37 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* ignore unknown attrs, or flag error? */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-04-15 13:42:10 +00:00
|
|
|
if (args.der_encoded.len == 0) {
|
2002-04-13 19:00:37 +00:00
|
|
|
rv = CKR_TEMPLATE_INCOMPLETE;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2003-06-04 12:26:06 +00:00
|
|
|
rc = sc_pkcs15init_store_certificate(fw_data->p15_card, profile, &args, &cert_obj);
|
2002-04-13 19:00:37 +00:00
|
|
|
if (rc < 0) {
|
2010-04-21 10:51:13 +00:00
|
|
|
rv = sc_to_cryptoki_error(rc, "C_CreateObject");
|
2002-04-13 19:00:37 +00:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
/* Create a new pkcs11 object for it */
|
2003-06-04 12:26:06 +00:00
|
|
|
__pkcs15_create_cert_object(fw_data, cert_obj, &cert_any_obj);
|
|
|
|
pkcs15_add_object(slot, cert_any_obj, phObject);
|
2002-04-13 19:00:37 +00:00
|
|
|
|
|
|
|
rv = CKR_OK;
|
|
|
|
|
2002-04-15 13:42:10 +00:00
|
|
|
out: return rv;
|
2002-04-13 19:00:37 +00:00
|
|
|
}
|
|
|
|
|
2007-06-21 09:37:18 +00:00
|
|
|
static CK_RV pkcs15_create_data(struct sc_pkcs11_card *p11card,
|
|
|
|
struct sc_pkcs11_slot *slot,
|
|
|
|
struct sc_profile *profile,
|
|
|
|
CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
|
|
|
|
CK_OBJECT_HANDLE_PTR phObject)
|
|
|
|
{
|
|
|
|
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) p11card->fw_data;
|
|
|
|
struct sc_pkcs15init_dataargs args;
|
|
|
|
struct pkcs15_any_object *data_any_obj;
|
|
|
|
struct sc_pkcs15_object *data_obj;
|
|
|
|
struct sc_pkcs15_pin_info *pin;
|
|
|
|
CK_BBOOL bValue;
|
|
|
|
int rc, rv;
|
2010-04-15 15:37:55 +00:00
|
|
|
char label[SC_PKCS15_MAX_LABEL_SIZE];
|
2007-06-21 09:37:18 +00:00
|
|
|
|
|
|
|
memset(&args, 0, sizeof(args));
|
|
|
|
args.app_oid.value[0] = -1;
|
|
|
|
|
|
|
|
rv = CKR_OK;
|
|
|
|
while (ulCount--) {
|
|
|
|
CK_ATTRIBUTE_PTR attr = pTemplate++;
|
|
|
|
|
|
|
|
switch (attr->type) {
|
|
|
|
/* Skip attrs we already know or don't care for */
|
|
|
|
case CKA_CLASS:
|
|
|
|
break;
|
|
|
|
case CKA_PRIVATE:
|
|
|
|
rv = attr_extract(attr, &bValue, NULL);
|
|
|
|
if (bValue) {
|
|
|
|
pin = slot_data_pin_info(slot->fw_data);
|
|
|
|
if (pin == NULL) {
|
|
|
|
rv = CKR_TEMPLATE_INCOMPLETE;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
args.auth_id = pin->auth_id;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CKA_LABEL:
|
2010-04-15 15:37:55 +00:00
|
|
|
args.label = set_cka_label(attr, label);
|
2007-06-21 09:37:18 +00:00
|
|
|
break;
|
|
|
|
case CKA_ID:
|
|
|
|
args.id.len = sizeof(args.id.value);
|
|
|
|
rv = attr_extract(attr, args.id.value, &args.id.len);
|
|
|
|
if (rv != CKR_OK)
|
|
|
|
goto out;
|
|
|
|
break;
|
|
|
|
case CKA_APPLICATION:
|
|
|
|
args.app_label = (char *) attr->pValue;
|
|
|
|
break;
|
|
|
|
case CKA_OBJECT_ID:
|
|
|
|
rv = attr_extract(attr, args.app_oid.value, NULL);
|
|
|
|
if (rv != CKR_OK)
|
|
|
|
goto out;
|
|
|
|
break;
|
|
|
|
case CKA_VALUE:
|
|
|
|
args.der_encoded.len = attr->ulValueLen;
|
|
|
|
args.der_encoded.value = (u8 *) attr->pValue;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* ignore unknown attrs, or flag error? */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (args.der_encoded.len == 0) {
|
|
|
|
rv = CKR_TEMPLATE_INCOMPLETE;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = sc_pkcs15init_store_data_object(fw_data->p15_card, profile, &args, &data_obj);
|
|
|
|
if (rc < 0) {
|
2010-04-21 10:51:13 +00:00
|
|
|
rv = sc_to_cryptoki_error(rc, "C_CreateObject");
|
2007-06-21 09:37:18 +00:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
/* Create a new pkcs11 object for it */
|
|
|
|
__pkcs15_create_data_object(fw_data, data_obj, &data_any_obj);
|
|
|
|
pkcs15_add_object(slot, data_any_obj, phObject);
|
|
|
|
|
|
|
|
rv = CKR_OK;
|
|
|
|
|
|
|
|
out: return rv;
|
|
|
|
}
|
|
|
|
|
2002-04-11 15:17:33 +00:00
|
|
|
static CK_RV pkcs15_create_object(struct sc_pkcs11_card *p11card,
|
|
|
|
struct sc_pkcs11_slot *slot,
|
|
|
|
CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
|
|
|
|
CK_OBJECT_HANDLE_PTR phObject)
|
|
|
|
{
|
|
|
|
struct sc_profile *profile = NULL;
|
2002-04-19 14:23:31 +00:00
|
|
|
CK_OBJECT_CLASS _class;
|
2005-02-11 20:09:34 +00:00
|
|
|
int rv, rc;
|
2002-04-11 15:17:33 +00:00
|
|
|
|
2002-04-19 14:23:31 +00:00
|
|
|
rv = attr_find(pTemplate, ulCount, CKA_CLASS, &_class, NULL);
|
2002-04-11 15:17:33 +00:00
|
|
|
if (rv != CKR_OK)
|
|
|
|
return rv;
|
|
|
|
|
2005-10-01 18:51:34 +00:00
|
|
|
rc = sc_lock(p11card->card);
|
2002-04-11 15:17:33 +00:00
|
|
|
if (rc < 0)
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rc, "C_CreateObject");
|
2002-04-11 15:17:33 +00:00
|
|
|
|
2005-10-01 18:51:34 +00:00
|
|
|
/* Bind the profile */
|
|
|
|
rc = sc_pkcs15init_bind(p11card->card, "pkcs15", NULL, &profile);
|
2003-09-11 12:11:52 +00:00
|
|
|
if (rc < 0) {
|
2005-10-01 18:51:34 +00:00
|
|
|
sc_unlock(p11card->card);
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rc, "C_CreateObject");
|
2003-09-11 12:11:52 +00:00
|
|
|
}
|
|
|
|
|
2002-04-19 14:23:31 +00:00
|
|
|
switch (_class) {
|
2002-04-11 15:17:33 +00:00
|
|
|
case CKO_PRIVATE_KEY:
|
|
|
|
rv = pkcs15_create_private_key(p11card, slot, profile,
|
|
|
|
pTemplate, ulCount, phObject);
|
|
|
|
break;
|
|
|
|
case CKO_PUBLIC_KEY:
|
|
|
|
rv = pkcs15_create_public_key(p11card, slot, profile,
|
|
|
|
pTemplate, ulCount, phObject);
|
|
|
|
break;
|
2002-04-13 19:00:37 +00:00
|
|
|
case CKO_CERTIFICATE:
|
|
|
|
rv = pkcs15_create_certificate(p11card, slot, profile,
|
|
|
|
pTemplate, ulCount, phObject);
|
|
|
|
break;
|
2007-06-21 09:37:18 +00:00
|
|
|
case CKO_DATA:
|
|
|
|
rv = pkcs15_create_data(p11card, slot, profile,
|
|
|
|
pTemplate, ulCount, phObject);
|
|
|
|
break;
|
2002-04-11 15:17:33 +00:00
|
|
|
default:
|
|
|
|
rv = CKR_FUNCTION_NOT_SUPPORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
sc_pkcs15init_unbind(profile);
|
2005-10-01 18:51:34 +00:00
|
|
|
sc_unlock(p11card->card);
|
|
|
|
|
2002-04-11 15:17:33 +00:00
|
|
|
return rv;
|
|
|
|
}
|
2003-06-03 13:57:52 +00:00
|
|
|
|
|
|
|
static CK_RV
|
|
|
|
get_X509_usage_privk(CK_ATTRIBUTE_PTR pTempl, CK_ULONG ulCount, unsigned long *x509_usage)
|
|
|
|
{
|
|
|
|
CK_ULONG i;
|
|
|
|
for (i = 0; i < ulCount; i++) {
|
|
|
|
CK_ATTRIBUTE_TYPE typ = pTempl[i].type;
|
|
|
|
CK_BBOOL *val = (CK_BBOOL *) pTempl[i].pValue;
|
|
|
|
if (val == NULL)
|
|
|
|
continue;
|
|
|
|
if (typ == CKA_SIGN && *val)
|
2005-09-07 09:32:52 +00:00
|
|
|
*x509_usage |= SC_PKCS15INIT_X509_DIGITAL_SIGNATURE;
|
2003-06-03 13:57:52 +00:00
|
|
|
if (typ == CKA_UNWRAP && *val)
|
2005-09-07 09:32:52 +00:00
|
|
|
*x509_usage |= SC_PKCS15INIT_X509_KEY_ENCIPHERMENT;
|
2003-06-03 13:57:52 +00:00
|
|
|
if (typ == CKA_DECRYPT && *val)
|
2005-09-07 09:32:52 +00:00
|
|
|
*x509_usage |= SC_PKCS15INIT_X509_DATA_ENCIPHERMENT;
|
2003-06-03 13:57:52 +00:00
|
|
|
if (typ == CKA_DERIVE && *val)
|
2005-09-07 09:32:52 +00:00
|
|
|
*x509_usage |= SC_PKCS15INIT_X509_KEY_AGREEMENT;
|
2003-06-03 13:57:52 +00:00
|
|
|
if (typ == CKA_VERIFY || typ == CKA_WRAP || typ == CKA_ENCRYPT) {
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "get_X509_usage_privk(): invalid typ = 0x%0x\n", typ);
|
2003-06-03 13:57:52 +00:00
|
|
|
return CKR_ATTRIBUTE_TYPE_INVALID;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static CK_RV
|
|
|
|
get_X509_usage_pubk(CK_ATTRIBUTE_PTR pTempl, CK_ULONG ulCount, unsigned long *x509_usage)
|
|
|
|
{
|
|
|
|
CK_ULONG i;
|
|
|
|
for (i = 0; i < ulCount; i++) {
|
|
|
|
CK_ATTRIBUTE_TYPE typ = pTempl[i].type;
|
|
|
|
CK_BBOOL *val = (CK_BBOOL *) pTempl[i].pValue;
|
|
|
|
if (val == NULL)
|
|
|
|
continue;
|
|
|
|
if (typ == CKA_VERIFY && *val)
|
2005-09-07 09:32:52 +00:00
|
|
|
*x509_usage |= SC_PKCS15INIT_X509_DIGITAL_SIGNATURE;
|
2003-06-03 13:57:52 +00:00
|
|
|
if (typ == CKA_WRAP && *val)
|
2005-09-07 09:32:52 +00:00
|
|
|
*x509_usage |= SC_PKCS15INIT_X509_KEY_ENCIPHERMENT;
|
2003-06-03 13:57:52 +00:00
|
|
|
if (typ == CKA_ENCRYPT && *val)
|
2005-09-07 09:32:52 +00:00
|
|
|
*x509_usage |= SC_PKCS15INIT_X509_DATA_ENCIPHERMENT;
|
2003-06-03 13:57:52 +00:00
|
|
|
if (typ == CKA_DERIVE && *val)
|
2005-09-07 09:32:52 +00:00
|
|
|
*x509_usage |= SC_PKCS15INIT_X509_KEY_AGREEMENT;
|
2003-06-03 13:57:52 +00:00
|
|
|
if (typ == CKA_SIGN || typ == CKA_UNWRAP || typ == CKA_DECRYPT) {
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "get_X509_usage_pubk(): invalid typ = 0x%0x\n", typ);
|
2003-06-03 13:57:52 +00:00
|
|
|
return CKR_ATTRIBUTE_TYPE_INVALID;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
|
|
|
|
2011-05-29 18:35:34 +00:00
|
|
|
|
2009-10-05 20:10:07 +00:00
|
|
|
static CK_RV
|
2011-05-29 18:35:34 +00:00
|
|
|
set_gost_params(struct sc_pkcs15init_keyarg_gost_params *first_params,
|
|
|
|
struct sc_pkcs15init_keyarg_gost_params *second_params,
|
2009-10-05 20:10:07 +00:00
|
|
|
CK_ATTRIBUTE_PTR pPubTpl, CK_ULONG ulPubCnt,
|
|
|
|
CK_ATTRIBUTE_PTR pPrivTpl, CK_ULONG ulPrivCnt)
|
|
|
|
{
|
|
|
|
CK_BYTE gost_params_oid[GOST_PARAMS_OID_SIZE];
|
|
|
|
size_t len, i;
|
|
|
|
CK_RV rv;
|
|
|
|
|
|
|
|
len = GOST_PARAMS_OID_SIZE;
|
2011-05-29 18:35:34 +00:00
|
|
|
if (pPrivTpl && ulPrivCnt)
|
|
|
|
rv = attr_find2(pPubTpl, ulPubCnt, pPrivTpl, ulPrivCnt, CKA_GOSTR3410_PARAMS, &gost_params_oid, &len);
|
|
|
|
else
|
|
|
|
rv = attr_find(pPubTpl, ulPubCnt, CKA_GOSTR3410_PARAMS, &gost_params_oid, &len);
|
2009-10-05 20:10:07 +00:00
|
|
|
if (rv == CKR_OK) {
|
2011-05-29 18:35:34 +00:00
|
|
|
int nn = sizeof(gostr3410_param_oid)/sizeof(gostr3410_param_oid[0]);
|
|
|
|
|
2009-10-05 20:10:07 +00:00
|
|
|
if (len != GOST_PARAMS_OID_SIZE)
|
|
|
|
return CKR_ATTRIBUTE_VALUE_INVALID;
|
2011-05-29 18:35:34 +00:00
|
|
|
|
|
|
|
for (i = 0; i < nn; ++i) {
|
2009-10-05 20:10:07 +00:00
|
|
|
if (!memcmp(gost_params_oid, gostr3410_param_oid[i].oid, len)) {
|
2011-05-29 18:35:34 +00:00
|
|
|
if (first_params)
|
|
|
|
first_params->gostr3410 = gostr3410_param_oid[i].param;
|
|
|
|
if (second_params)
|
|
|
|
second_params->gostr3410 = gostr3410_param_oid[i].param;
|
2009-10-05 20:10:07 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2011-05-29 18:35:34 +00:00
|
|
|
|
|
|
|
if (i == nn)
|
|
|
|
return CKR_ATTRIBUTE_VALUE_INVALID;
|
2009-10-05 20:10:07 +00:00
|
|
|
}
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
|
|
|
|
2003-06-03 13:57:52 +00:00
|
|
|
/* FIXME: check for the public exponent in public key template and use this value */
|
2004-12-22 10:17:00 +00:00
|
|
|
static CK_RV pkcs15_gen_keypair(struct sc_pkcs11_card *p11card,
|
|
|
|
struct sc_pkcs11_slot *slot,
|
2003-06-03 13:57:52 +00:00
|
|
|
CK_MECHANISM_PTR pMechanism,
|
|
|
|
CK_ATTRIBUTE_PTR pPubTpl, CK_ULONG ulPubCnt,
|
|
|
|
CK_ATTRIBUTE_PTR pPrivTpl, CK_ULONG ulPrivCnt,
|
|
|
|
CK_OBJECT_HANDLE_PTR phPubKey, CK_OBJECT_HANDLE_PTR phPrivKey) /* gets priv. key handle */
|
|
|
|
{
|
|
|
|
struct sc_profile *profile = NULL;
|
|
|
|
struct sc_pkcs15_pin_info *pin;
|
|
|
|
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) p11card->fw_data;
|
2003-12-08 12:02:28 +00:00
|
|
|
struct sc_pkcs15init_keygen_args keygen_args;
|
2003-06-03 13:57:52 +00:00
|
|
|
struct sc_pkcs15init_pubkeyargs pub_args;
|
2003-06-04 12:26:06 +00:00
|
|
|
struct sc_pkcs15_object *priv_key_obj;
|
|
|
|
struct sc_pkcs15_object *pub_key_obj;
|
|
|
|
struct pkcs15_any_object *priv_any_obj;
|
|
|
|
struct pkcs15_any_object *pub_any_obj;
|
2003-06-03 13:57:52 +00:00
|
|
|
struct sc_pkcs15_id id;
|
|
|
|
size_t len;
|
2009-10-05 20:10:07 +00:00
|
|
|
CK_KEY_TYPE keytype;
|
2003-06-03 13:57:52 +00:00
|
|
|
CK_ULONG keybits;
|
|
|
|
char pub_label[SC_PKCS15_MAX_LABEL_SIZE];
|
|
|
|
char priv_label[SC_PKCS15_MAX_LABEL_SIZE];
|
2003-10-18 12:40:22 +00:00
|
|
|
int rc, rv = CKR_OK;
|
2003-06-03 13:57:52 +00:00
|
|
|
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "Keypair generation, mech = 0x%0x\n", pMechanism->mechanism);
|
2003-06-03 13:57:52 +00:00
|
|
|
|
2009-10-05 20:10:07 +00:00
|
|
|
if (pMechanism->mechanism != CKM_RSA_PKCS_KEY_PAIR_GEN
|
2011-04-17 18:45:27 +00:00
|
|
|
&& pMechanism->mechanism != CKM_GOSTR3410_KEY_PAIR_GEN
|
|
|
|
&& pMechanism->mechanism != CKM_EC_KEY_PAIR_GEN)
|
2003-06-03 13:57:52 +00:00
|
|
|
return CKR_MECHANISM_INVALID;
|
|
|
|
|
2005-10-01 18:51:34 +00:00
|
|
|
rc = sc_lock(p11card->card);
|
2003-06-03 13:57:52 +00:00
|
|
|
if (rc < 0)
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rc, "C_GenerateKeyPair");
|
2003-06-03 13:57:52 +00:00
|
|
|
|
2005-10-01 18:51:34 +00:00
|
|
|
rc = sc_pkcs15init_bind(p11card->card, "pkcs15", NULL, &profile);
|
2003-09-11 12:11:52 +00:00
|
|
|
if (rc < 0) {
|
2005-10-01 18:51:34 +00:00
|
|
|
sc_unlock(p11card->card);
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rc, "C_GenerateKeyPair");
|
2003-09-11 12:11:52 +00:00
|
|
|
}
|
|
|
|
|
2005-10-01 18:51:34 +00:00
|
|
|
memset(&keygen_args, 0, sizeof(keygen_args));
|
|
|
|
memset(&pub_args, 0, sizeof(pub_args));
|
|
|
|
|
2003-06-03 13:57:52 +00:00
|
|
|
/* 1. Convert the pkcs11 attributes to pkcs15init args */
|
|
|
|
|
|
|
|
if ((pin = slot_data_pin_info(slot->fw_data)) != NULL)
|
2003-12-08 12:02:28 +00:00
|
|
|
keygen_args.prkey_args.auth_id = pub_args.auth_id = pin->auth_id;
|
2003-06-03 13:57:52 +00:00
|
|
|
|
|
|
|
rv = attr_find2(pPubTpl, ulPubCnt, pPrivTpl, ulPrivCnt, CKA_KEY_TYPE,
|
|
|
|
&keytype, NULL);
|
2009-12-08 18:28:22 +00:00
|
|
|
if (rv != CKR_OK && pMechanism->mechanism == CKM_RSA_PKCS_KEY_PAIR_GEN)
|
2009-10-05 20:10:07 +00:00
|
|
|
keytype = CKK_RSA;
|
2011-04-21 16:14:36 +00:00
|
|
|
else if (rv != CKR_OK && pMechanism->mechanism == CKM_EC_KEY_PAIR_GEN)
|
2011-04-17 18:45:27 +00:00
|
|
|
keytype = CKK_EC;
|
2009-12-08 18:34:55 +00:00
|
|
|
else if (rv != CKR_OK)
|
2009-12-08 18:28:22 +00:00
|
|
|
goto kpgen_done;
|
2011-04-21 16:14:36 +00:00
|
|
|
|
2011-04-17 18:45:27 +00:00
|
|
|
if (keytype == CKK_GOSTR3410) {
|
2009-10-05 20:10:07 +00:00
|
|
|
keygen_args.prkey_args.key.algorithm = SC_ALGORITHM_GOSTR3410;
|
|
|
|
pub_args.key.algorithm = SC_ALGORITHM_GOSTR3410;
|
2011-05-29 18:35:34 +00:00
|
|
|
set_gost_params(&keygen_args.prkey_args.params.gost, &pub_args.params.gost,
|
2009-10-05 20:10:07 +00:00
|
|
|
pPubTpl, ulPubCnt, pPrivTpl, ulPrivCnt);
|
|
|
|
}
|
2011-04-17 18:45:27 +00:00
|
|
|
else if (keytype == CKK_RSA) {
|
2009-10-05 20:10:07 +00:00
|
|
|
/* default value (CKA_KEY_TYPE isn't set) or CKK_RSA is set */
|
|
|
|
keygen_args.prkey_args.key.algorithm = SC_ALGORITHM_RSA;
|
|
|
|
pub_args.key.algorithm = SC_ALGORITHM_RSA;
|
|
|
|
}
|
2011-04-17 18:45:27 +00:00
|
|
|
else if (keytype == CKK_EC) {
|
|
|
|
struct sc_pkcs15_der *der = &keygen_args.prkey_args.params.ec.der;
|
|
|
|
|
|
|
|
der->len = sizeof(struct sc_object_id);
|
|
|
|
rv = attr_find_ptr(pPubTpl, ulPubCnt, CKA_EC_PARAMS, (void **)&der->value, &der->len);
|
|
|
|
if (rv != CKR_OK) {
|
|
|
|
sc_unlock(p11card->card);
|
|
|
|
return sc_to_cryptoki_error(rc, "C_GenerateKeyPair");
|
|
|
|
}
|
|
|
|
|
|
|
|
keygen_args.prkey_args.key.algorithm = SC_ALGORITHM_EC;
|
|
|
|
pub_args.key.algorithm = SC_ALGORITHM_EC;
|
|
|
|
}
|
|
|
|
else {
|
2009-10-05 20:10:07 +00:00
|
|
|
/* CKA_KEY_TYPE is set, but keytype isn't correct */
|
2003-06-03 13:57:52 +00:00
|
|
|
rv = CKR_ATTRIBUTE_VALUE_INVALID;
|
|
|
|
goto kpgen_done;
|
|
|
|
}
|
2009-10-05 20:10:07 +00:00
|
|
|
if (keytype == CKK_GOSTR3410)
|
|
|
|
keybits = SC_PKCS15_GOSTR3410_KEYSIZE;
|
|
|
|
else if (keytype == CKK_RSA)
|
|
|
|
{
|
|
|
|
rv = attr_find2(pPubTpl, ulPubCnt, pPrivTpl, ulPrivCnt, CKA_MODULUS_BITS,
|
|
|
|
&keybits, NULL);
|
|
|
|
if (rv != CKR_OK)
|
2003-06-03 13:57:52 +00:00
|
|
|
keybits = 1024; /* Default key size */
|
2009-10-05 20:10:07 +00:00
|
|
|
/* TODO: check allowed values of keybits */
|
|
|
|
}
|
2003-06-03 13:57:52 +00:00
|
|
|
|
|
|
|
id.len = SC_PKCS15_MAX_ID_SIZE;
|
|
|
|
rv = attr_find2(pPubTpl, ulPubCnt, pPrivTpl, ulPrivCnt, CKA_ID,
|
|
|
|
&id.value, &id.len);
|
|
|
|
if (rv == CKR_OK)
|
2003-12-08 12:02:28 +00:00
|
|
|
keygen_args.prkey_args.id = pub_args.id = id;
|
2003-06-03 13:57:52 +00:00
|
|
|
|
2003-11-12 19:06:33 +00:00
|
|
|
len = sizeof(priv_label) - 1;
|
2003-06-03 13:57:52 +00:00
|
|
|
rv = attr_find(pPrivTpl, ulPrivCnt, CKA_LABEL, priv_label, &len);
|
2003-06-04 19:17:51 +00:00
|
|
|
if (rv == CKR_OK) {
|
2003-11-12 19:06:33 +00:00
|
|
|
priv_label[len] = '\0';
|
2003-12-08 12:02:28 +00:00
|
|
|
keygen_args.prkey_args.label = priv_label;
|
2003-06-03 13:57:52 +00:00
|
|
|
}
|
2003-11-12 19:06:33 +00:00
|
|
|
len = sizeof(pub_label) - 1;
|
2003-06-03 13:57:52 +00:00
|
|
|
rv = attr_find(pPubTpl, ulPubCnt, CKA_LABEL, pub_label, &len);
|
2003-06-04 19:17:51 +00:00
|
|
|
if (rv == CKR_OK) {
|
2003-11-12 19:06:33 +00:00
|
|
|
pub_label[len] = '\0';
|
2003-12-30 08:20:52 +00:00
|
|
|
keygen_args.pubkey_label = pub_label;
|
2003-06-03 13:57:52 +00:00
|
|
|
pub_args.label = pub_label;
|
|
|
|
}
|
|
|
|
|
2003-12-08 12:02:28 +00:00
|
|
|
rv = get_X509_usage_privk(pPrivTpl, ulPrivCnt,
|
|
|
|
&keygen_args.prkey_args.x509_usage);
|
2003-06-03 13:57:52 +00:00
|
|
|
if (rv == CKR_OK)
|
2003-12-08 12:02:28 +00:00
|
|
|
rv = get_X509_usage_pubk(pPubTpl, ulPubCnt,
|
|
|
|
&keygen_args.prkey_args.x509_usage);
|
2003-06-03 13:57:52 +00:00
|
|
|
if (rv != CKR_OK)
|
|
|
|
goto kpgen_done;
|
2003-12-08 12:02:28 +00:00
|
|
|
pub_args.x509_usage = keygen_args.prkey_args.x509_usage;
|
2003-06-03 13:57:52 +00:00
|
|
|
|
|
|
|
/* 3.a Try on-card key pair generation */
|
2003-06-04 19:17:51 +00:00
|
|
|
|
2010-01-08 15:41:07 +00:00
|
|
|
sc_pkcs15init_set_p15card(profile, fw_data->p15_card);
|
|
|
|
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "Try on-card key pair generation");
|
2003-06-03 13:57:52 +00:00
|
|
|
rc = sc_pkcs15init_generate_key(fw_data->p15_card, profile,
|
2003-12-08 12:02:28 +00:00
|
|
|
&keygen_args, keybits, &priv_key_obj);
|
2003-06-03 13:57:52 +00:00
|
|
|
if (rc >= 0) {
|
2003-06-04 12:26:06 +00:00
|
|
|
id = ((struct sc_pkcs15_prkey_info *) priv_key_obj->data)->id;
|
2003-06-03 13:57:52 +00:00
|
|
|
rc = sc_pkcs15_find_pubkey_by_id(fw_data->p15_card, &id, &pub_key_obj);
|
|
|
|
if (rc != 0) {
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "sc_pkcs15_find_pubkey_by_id returned %d\n", rc);
|
2010-04-21 10:51:13 +00:00
|
|
|
rv = sc_to_cryptoki_error(rc, "C_GenerateKeyPair");
|
2003-06-03 13:57:52 +00:00
|
|
|
goto kpgen_done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (rc != SC_ERROR_NOT_SUPPORTED) {
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "sc_pkcs15init_generate_key returned %d\n", rc);
|
2010-04-21 10:51:13 +00:00
|
|
|
rv = sc_to_cryptoki_error(rc, "C_GenerateKeyPair");
|
2003-06-03 13:57:52 +00:00
|
|
|
goto kpgen_done;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 4. Create new pkcs11 public and private key object */
|
|
|
|
|
2003-06-04 12:26:06 +00:00
|
|
|
rc = __pkcs15_create_prkey_object(fw_data, priv_key_obj, &priv_any_obj);
|
2003-06-03 13:57:52 +00:00
|
|
|
if (rc == 0)
|
2004-07-26 18:47:23 +00:00
|
|
|
rc = __pkcs15_create_pubkey_object(fw_data, pub_key_obj, &pub_any_obj);
|
2003-06-03 13:57:52 +00:00
|
|
|
if (rc != 0) {
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "__pkcs15_create_pr/pubkey_object returned %d\n", rc);
|
2010-04-21 10:51:13 +00:00
|
|
|
rv = sc_to_cryptoki_error(rc, "C_GenerateKeyPair");
|
2003-06-03 13:57:52 +00:00
|
|
|
goto kpgen_done;
|
|
|
|
}
|
2003-06-04 12:26:06 +00:00
|
|
|
pkcs15_add_object(slot, priv_any_obj, phPrivKey);
|
|
|
|
pkcs15_add_object(slot, pub_any_obj, phPubKey);
|
2003-12-04 16:42:03 +00:00
|
|
|
((struct pkcs15_prkey_object *) priv_any_obj)->prv_pubkey =
|
|
|
|
(struct pkcs15_pubkey_object *)pub_any_obj;
|
2003-06-03 13:57:52 +00:00
|
|
|
|
|
|
|
kpgen_done:
|
|
|
|
sc_pkcs15init_unbind(profile);
|
2005-10-01 18:51:34 +00:00
|
|
|
sc_unlock(p11card->card);
|
2003-06-03 13:57:52 +00:00
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
2002-06-20 13:16:22 +00:00
|
|
|
#endif
|
2002-04-11 15:17:33 +00:00
|
|
|
|
2010-04-20 15:11:58 +00:00
|
|
|
static CK_RV pkcs15_any_destroy(struct sc_pkcs11_session *session, void *object)
|
|
|
|
{
|
2010-12-17 17:54:07 +00:00
|
|
|
#ifndef USE_PKCS15_INIT
|
|
|
|
return CKR_FUNCTION_NOT_SUPPORTED;
|
|
|
|
#else
|
2010-04-20 15:11:58 +00:00
|
|
|
struct pkcs15_data_object *obj = (struct pkcs15_data_object*) object;
|
|
|
|
struct pkcs15_any_object *any_obj = (struct pkcs15_any_object*) object;
|
|
|
|
struct sc_pkcs11_card *card = session->slot->card;
|
|
|
|
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) card->fw_data;
|
|
|
|
struct sc_profile *profile = NULL;
|
|
|
|
int rv;
|
|
|
|
|
|
|
|
rv = sc_lock(card->card);
|
|
|
|
if (rv < 0)
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rv, "C_DestroyObject");
|
2010-04-20 15:11:58 +00:00
|
|
|
|
|
|
|
/* Bind the profile */
|
|
|
|
rv = sc_pkcs15init_bind(card->card, "pkcs15", NULL, &profile);
|
|
|
|
if (rv < 0) {
|
|
|
|
sc_unlock(card->card);
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rv, "C_DestroyObject");
|
2010-04-20 15:11:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Delete object in smartcard */
|
|
|
|
rv = sc_pkcs15init_delete_object(fw_data->p15_card, profile, obj->base.p15_object);
|
|
|
|
if (rv >= 0) {
|
|
|
|
/* Oppose to pkcs15_add_object */
|
|
|
|
--any_obj->refcount; /* correct refcont */
|
|
|
|
list_delete(&session->slot->objects, any_obj);
|
|
|
|
/* Delete object in pkcs15 */
|
|
|
|
rv = __pkcs15_delete_object(fw_data, any_obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
sc_pkcs15init_unbind(profile);
|
|
|
|
sc_unlock(card->card);
|
|
|
|
|
|
|
|
if (rv < 0)
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rv, "C_DestroyObject");
|
2010-04-20 15:11:58 +00:00
|
|
|
|
|
|
|
return CKR_OK;
|
2010-12-17 17:54:07 +00:00
|
|
|
#endif
|
2010-04-20 15:11:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-18 20:20:22 +00:00
|
|
|
static CK_RV pkcs15_get_random(struct sc_pkcs11_card *p11card,
|
|
|
|
CK_BYTE_PTR p, CK_ULONG len)
|
|
|
|
{
|
|
|
|
int rc;
|
2010-09-01 06:23:32 +00:00
|
|
|
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) p11card->fw_data;
|
|
|
|
struct sc_card *card = fw_data->p15_card->card;
|
2005-07-18 20:20:22 +00:00
|
|
|
|
|
|
|
rc = sc_get_challenge(card, p, (size_t)len);
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rc, "C_GenerateRandom");
|
2005-07-18 20:20:22 +00:00
|
|
|
}
|
|
|
|
|
2002-01-16 22:49:03 +00:00
|
|
|
struct sc_pkcs11_framework_ops framework_pkcs15 = {
|
|
|
|
pkcs15_bind,
|
|
|
|
pkcs15_unbind,
|
|
|
|
pkcs15_create_tokens,
|
|
|
|
pkcs15_release_token,
|
|
|
|
pkcs15_login,
|
2005-01-19 18:15:43 +00:00
|
|
|
pkcs15_logout,
|
2002-04-08 15:51:19 +00:00
|
|
|
pkcs15_change_pin,
|
2005-01-19 18:15:43 +00:00
|
|
|
NULL, /* init_token */
|
2002-06-20 13:16:22 +00:00
|
|
|
#ifdef USE_PKCS15_INIT
|
2002-04-11 15:17:33 +00:00
|
|
|
pkcs15_init_pin,
|
2005-01-19 18:15:43 +00:00
|
|
|
pkcs15_create_object,
|
|
|
|
pkcs15_gen_keypair,
|
2002-06-20 13:16:22 +00:00
|
|
|
#else
|
2005-07-18 20:20:22 +00:00
|
|
|
NULL,
|
2005-01-19 18:15:43 +00:00
|
|
|
NULL,
|
2005-07-21 21:05:40 +00:00
|
|
|
NULL,
|
2002-06-20 13:16:22 +00:00
|
|
|
#endif
|
2005-07-18 20:20:22 +00:00
|
|
|
pkcs15_get_random
|
2002-01-16 22:49:03 +00:00
|
|
|
};
|
|
|
|
|
2004-12-22 10:17:00 +00:00
|
|
|
static CK_RV pkcs15_set_attrib(struct sc_pkcs11_session *session,
|
2003-06-27 12:00:43 +00:00
|
|
|
struct sc_pkcs15_object *p15_object,
|
|
|
|
CK_ATTRIBUTE_PTR attr)
|
|
|
|
{
|
|
|
|
#ifndef USE_PKCS15_INIT
|
2005-01-19 18:15:43 +00:00
|
|
|
return CKR_FUNCTION_NOT_SUPPORTED;
|
2003-06-27 12:00:43 +00:00
|
|
|
#else
|
2005-01-19 18:15:43 +00:00
|
|
|
struct sc_profile *profile = NULL;
|
|
|
|
struct sc_pkcs11_card *p11card = session->slot->card;
|
|
|
|
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) p11card->fw_data;
|
|
|
|
struct sc_pkcs15_id id;
|
|
|
|
int rc = 0;
|
|
|
|
CK_RV rv = CKR_OK;
|
2003-06-27 12:00:43 +00:00
|
|
|
|
2005-10-01 18:51:34 +00:00
|
|
|
rc = sc_lock(p11card->card);
|
2005-01-19 18:15:43 +00:00
|
|
|
if (rc < 0)
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rc, "C_SetAttributeValue");
|
2003-06-27 12:00:43 +00:00
|
|
|
|
2005-10-01 18:51:34 +00:00
|
|
|
rc = sc_pkcs15init_bind(p11card->card, "pkcs15", NULL, &profile);
|
2003-09-11 12:11:52 +00:00
|
|
|
if (rc < 0) {
|
2009-10-22 09:18:16 +00:00
|
|
|
sc_unlock(p11card->card);
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rc, "C_SetAttributeValue");
|
2003-09-11 12:11:52 +00:00
|
|
|
}
|
|
|
|
|
2005-01-19 18:15:43 +00:00
|
|
|
switch(attr->type) {
|
|
|
|
case CKA_LABEL:
|
|
|
|
rc = sc_pkcs15init_change_attrib(fw_data->p15_card, profile, p15_object,
|
|
|
|
P15_ATTR_TYPE_LABEL, attr->pValue, attr->ulValueLen);
|
|
|
|
break;
|
|
|
|
case CKA_ID:
|
|
|
|
if (attr->ulValueLen > SC_PKCS15_MAX_ID_SIZE) {
|
|
|
|
rc = SC_ERROR_INVALID_ARGUMENTS;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
memcpy(id.value, attr->pValue, attr->ulValueLen);
|
|
|
|
id.len = attr->ulValueLen;
|
|
|
|
rc = sc_pkcs15init_change_attrib(fw_data->p15_card, profile, p15_object,
|
|
|
|
P15_ATTR_TYPE_ID, &id, sizeof(id));
|
|
|
|
break;
|
2003-07-11 20:14:48 +00:00
|
|
|
case CKA_SUBJECT:
|
|
|
|
rc = SC_SUCCESS;
|
|
|
|
break;
|
2005-01-19 18:15:43 +00:00
|
|
|
default:
|
|
|
|
rv = CKR_ATTRIBUTE_READ_ONLY;
|
|
|
|
goto set_attr_done;
|
|
|
|
}
|
2003-06-27 12:00:43 +00:00
|
|
|
|
2010-04-21 10:51:13 +00:00
|
|
|
rv = sc_to_cryptoki_error(rc, "C_SetAttributeValue");
|
2003-06-27 12:00:43 +00:00
|
|
|
|
|
|
|
set_attr_done:
|
2005-01-19 18:15:43 +00:00
|
|
|
sc_pkcs15init_unbind(profile);
|
2005-10-01 18:51:34 +00:00
|
|
|
sc_unlock(p11card->card);
|
2005-01-19 18:15:43 +00:00
|
|
|
|
|
|
|
return rv;
|
2003-06-27 12:00:43 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2002-01-16 22:49:03 +00:00
|
|
|
/*
|
|
|
|
* PKCS#15 Certificate Object
|
|
|
|
*/
|
|
|
|
|
2004-12-22 10:17:00 +00:00
|
|
|
static void pkcs15_cert_release(void *obj)
|
2002-01-16 22:49:03 +00:00
|
|
|
{
|
|
|
|
struct pkcs15_cert_object *cert = (struct pkcs15_cert_object *) obj;
|
2004-12-12 19:13:17 +00:00
|
|
|
struct sc_pkcs15_cert *cert_data = cert->cert_data;
|
2003-02-23 17:50:33 +00:00
|
|
|
|
2006-02-09 20:05:20 +00:00
|
|
|
if (__pkcs15_release_object((struct pkcs15_any_object *) obj) == 0) {
|
|
|
|
if (cert_data) /* may never have been read */
|
|
|
|
sc_pkcs15_free_certificate(cert_data);
|
|
|
|
}
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
|
2004-12-22 10:17:00 +00:00
|
|
|
static CK_RV pkcs15_cert_set_attribute(struct sc_pkcs11_session *session,
|
2003-06-27 12:00:43 +00:00
|
|
|
void *object,
|
|
|
|
CK_ATTRIBUTE_PTR attr)
|
|
|
|
{
|
2005-01-19 18:15:43 +00:00
|
|
|
struct pkcs15_cert_object *cert = (struct pkcs15_cert_object*) object;
|
|
|
|
return pkcs15_set_attrib(session, cert->base.p15_object, attr);
|
2003-06-27 12:00:43 +00:00
|
|
|
}
|
|
|
|
|
2004-12-22 10:17:00 +00:00
|
|
|
static CK_RV pkcs15_cert_get_attribute(struct sc_pkcs11_session *session,
|
2002-01-16 22:49:03 +00:00
|
|
|
void *object,
|
|
|
|
CK_ATTRIBUTE_PTR attr)
|
|
|
|
{
|
|
|
|
struct pkcs15_cert_object *cert = (struct pkcs15_cert_object*) object;
|
2006-02-09 20:05:20 +00:00
|
|
|
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) session->slot->card->fw_data;
|
2002-12-23 17:02:05 +00:00
|
|
|
size_t len;
|
2002-01-16 22:49:03 +00:00
|
|
|
|
|
|
|
switch (attr->type) {
|
|
|
|
case CKA_CLASS:
|
|
|
|
check_attribute_buffer(attr, sizeof(CK_OBJECT_CLASS));
|
|
|
|
*(CK_OBJECT_CLASS*)attr->pValue = CKO_CERTIFICATE;
|
2005-01-19 18:15:43 +00:00
|
|
|
break;
|
2002-01-16 22:49:03 +00:00
|
|
|
case CKA_TOKEN:
|
|
|
|
check_attribute_buffer(attr, sizeof(CK_BBOOL));
|
|
|
|
*(CK_BBOOL*)attr->pValue = TRUE;
|
2005-01-19 18:15:43 +00:00
|
|
|
break;
|
2002-01-16 22:49:03 +00:00
|
|
|
case CKA_PRIVATE:
|
2006-02-09 20:05:20 +00:00
|
|
|
check_attribute_buffer(attr, sizeof(CK_BBOOL));
|
|
|
|
*(CK_BBOOL*)attr->pValue =
|
|
|
|
(cert->base.p15_object->flags & SC_PKCS15_CO_FLAG_PRIVATE) != 0;
|
|
|
|
break;
|
2002-01-16 22:49:03 +00:00
|
|
|
case CKA_MODIFIABLE:
|
|
|
|
check_attribute_buffer(attr, sizeof(CK_BBOOL));
|
|
|
|
*(CK_BBOOL*)attr->pValue = FALSE;
|
2005-01-19 18:15:43 +00:00
|
|
|
break;
|
2002-01-16 22:49:03 +00:00
|
|
|
case CKA_LABEL:
|
2003-04-16 14:17:02 +00:00
|
|
|
len = strlen(cert->cert_p15obj->label);
|
2002-12-23 17:02:05 +00:00
|
|
|
check_attribute_buffer(attr, len);
|
2005-01-19 18:15:43 +00:00
|
|
|
memcpy(attr->pValue, cert->cert_p15obj->label, len);
|
|
|
|
break;
|
2002-01-16 22:49:03 +00:00
|
|
|
case CKA_CERTIFICATE_TYPE:
|
|
|
|
check_attribute_buffer(attr, sizeof(CK_CERTIFICATE_TYPE));
|
2005-01-19 18:15:43 +00:00
|
|
|
*(CK_CERTIFICATE_TYPE*)attr->pValue = CKC_X_509;
|
2002-01-16 22:49:03 +00:00
|
|
|
break;
|
|
|
|
case CKA_ID:
|
2010-03-09 15:43:16 +00:00
|
|
|
if (cert->cert_info->authority
|
|
|
|
&& sc_pkcs11_conf.zero_ckaid_for_ca_certs) {
|
2002-01-24 16:27:09 +00:00
|
|
|
check_attribute_buffer(attr, 1);
|
|
|
|
*(unsigned char*)attr->pValue = 0;
|
|
|
|
} else {
|
2003-02-23 17:50:33 +00:00
|
|
|
check_attribute_buffer(attr, cert->cert_info->id.len);
|
|
|
|
memcpy(attr->pValue, cert->cert_info->id.value, cert->cert_info->id.len);
|
2005-01-19 18:15:43 +00:00
|
|
|
}
|
|
|
|
break;
|
2002-01-16 22:49:03 +00:00
|
|
|
case CKA_TRUSTED:
|
|
|
|
check_attribute_buffer(attr, sizeof(CK_BBOOL));
|
2005-01-19 18:15:43 +00:00
|
|
|
*(CK_BBOOL*)attr->pValue = cert->cert_info->authority ? TRUE : FALSE;
|
|
|
|
break;
|
2002-01-16 22:49:03 +00:00
|
|
|
case CKA_VALUE:
|
2006-02-09 20:05:20 +00:00
|
|
|
if (check_cert_data_read(fw_data, cert) != 0) {
|
|
|
|
attr->ulValueLen = 0;
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
2003-02-23 17:50:33 +00:00
|
|
|
check_attribute_buffer(attr, cert->cert_data->data_len);
|
|
|
|
memcpy(attr->pValue, cert->cert_data->data, cert->cert_data->data_len);
|
2002-01-16 22:49:03 +00:00
|
|
|
break;
|
2002-03-15 15:22:41 +00:00
|
|
|
case CKA_SERIAL_NUMBER:
|
2006-02-09 20:05:20 +00:00
|
|
|
if (check_cert_data_read(fw_data, cert) != 0) {
|
|
|
|
attr->ulValueLen = 0;
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
2005-02-11 20:09:34 +00:00
|
|
|
check_attribute_buffer(attr, cert->cert_data->serial_len);
|
|
|
|
memcpy(attr->pValue, cert->cert_data->serial, cert->cert_data->serial_len);
|
|
|
|
break;
|
2002-03-20 13:08:51 +00:00
|
|
|
case CKA_SUBJECT:
|
2006-02-09 20:05:20 +00:00
|
|
|
if (check_cert_data_read(fw_data, cert) != 0) {
|
|
|
|
attr->ulValueLen = 0;
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
2005-02-11 20:09:34 +00:00
|
|
|
return asn1_sequence_wrapper(cert->cert_data->subject,
|
|
|
|
cert->cert_data->subject_len, attr);
|
2002-03-15 15:22:41 +00:00
|
|
|
case CKA_ISSUER:
|
2006-02-09 20:05:20 +00:00
|
|
|
if (check_cert_data_read(fw_data, cert) != 0) {
|
|
|
|
attr->ulValueLen = 0;
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
2005-02-11 20:09:34 +00:00
|
|
|
return asn1_sequence_wrapper(cert->cert_data->issuer,
|
|
|
|
cert->cert_data->issuer_len, attr);
|
2002-01-16 22:49:03 +00:00
|
|
|
default:
|
2005-01-19 18:15:43 +00:00
|
|
|
return CKR_ATTRIBUTE_TYPE_INVALID;
|
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-03-18 11:05:21 +00:00
|
|
|
static int
|
|
|
|
pkcs15_cert_cmp_attribute(struct sc_pkcs11_session *session,
|
|
|
|
void *object,
|
|
|
|
CK_ATTRIBUTE_PTR attr)
|
|
|
|
{
|
|
|
|
struct pkcs15_cert_object *cert = (struct pkcs15_cert_object*) object;
|
2006-02-09 20:05:20 +00:00
|
|
|
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) session->slot->card->fw_data;
|
2002-03-18 11:05:21 +00:00
|
|
|
u8 *data;
|
|
|
|
size_t len;
|
|
|
|
|
|
|
|
switch (attr->type) {
|
|
|
|
/* Check the issuer. Some pkcs11 callers (i.e. netscape) will pass
|
|
|
|
* in the ASN.1 encoded SEQUENCE OF SET ... while OpenSC just
|
|
|
|
* keeps the SET in the issuer field. */
|
|
|
|
case CKA_ISSUER:
|
2006-02-09 20:05:20 +00:00
|
|
|
if (check_cert_data_read(fw_data, cert) != 0)
|
|
|
|
break;
|
2003-02-23 17:50:33 +00:00
|
|
|
if (cert->cert_data->issuer_len == 0)
|
2002-03-18 11:05:21 +00:00
|
|
|
break;
|
2002-04-19 14:23:31 +00:00
|
|
|
data = (u8 *) attr->pValue;
|
2002-03-18 11:05:21 +00:00
|
|
|
len = attr->ulValueLen;
|
|
|
|
/* SEQUENCE is tag 0x30, SET is 0x31
|
|
|
|
* I know this code is icky, but hey... this is netscape
|
|
|
|
* we're dealing with :-) */
|
2003-02-23 17:50:33 +00:00
|
|
|
if (cert->cert_data->issuer[0] == 0x31
|
2002-03-18 11:05:21 +00:00
|
|
|
&& data[0] == 0x30 && len >= 2) {
|
|
|
|
/* skip the length byte(s) */
|
|
|
|
len = (data[1] & 0x80)? (data[1] & 0x7F) : 0;
|
|
|
|
if (attr->ulValueLen < len + 2)
|
|
|
|
break;
|
|
|
|
data += len + 2;
|
|
|
|
len = attr->ulValueLen - len - 2;
|
|
|
|
}
|
2003-02-23 17:50:33 +00:00
|
|
|
if (len == cert->cert_data->issuer_len
|
|
|
|
&& !memcmp(cert->cert_data->issuer, data, len))
|
2002-03-18 11:05:21 +00:00
|
|
|
return 1;
|
|
|
|
break;
|
|
|
|
default:
|
2005-01-19 18:15:43 +00:00
|
|
|
return sc_pkcs11_any_cmp_attribute(session, object, attr);
|
2002-03-18 11:05:21 +00:00
|
|
|
}
|
2005-01-19 18:15:43 +00:00
|
|
|
return 0;
|
2002-03-18 11:05:21 +00:00
|
|
|
}
|
|
|
|
|
2002-01-16 22:49:03 +00:00
|
|
|
struct sc_pkcs11_object_ops pkcs15_cert_ops = {
|
|
|
|
pkcs15_cert_release,
|
2005-01-19 18:15:43 +00:00
|
|
|
pkcs15_cert_set_attribute,
|
2002-01-16 22:49:03 +00:00
|
|
|
pkcs15_cert_get_attribute,
|
2002-03-18 11:05:21 +00:00
|
|
|
pkcs15_cert_cmp_attribute,
|
2010-04-20 15:11:58 +00:00
|
|
|
pkcs15_any_destroy,
|
2002-01-16 22:49:03 +00:00
|
|
|
NULL,
|
2005-09-07 09:32:52 +00:00
|
|
|
NULL,
|
|
|
|
NULL,
|
2005-01-19 18:15:43 +00:00
|
|
|
NULL
|
2002-01-16 22:49:03 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* PKCS#15 Private Key Object
|
|
|
|
*/
|
2004-12-22 10:17:00 +00:00
|
|
|
static void pkcs15_prkey_release(void *object)
|
2003-02-23 17:50:33 +00:00
|
|
|
{
|
|
|
|
__pkcs15_release_object((struct pkcs15_any_object *) object);
|
|
|
|
}
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2004-12-22 10:17:00 +00:00
|
|
|
static CK_RV pkcs15_prkey_set_attribute(struct sc_pkcs11_session *session,
|
2003-06-27 12:00:43 +00:00
|
|
|
void *object,
|
|
|
|
CK_ATTRIBUTE_PTR attr)
|
|
|
|
{
|
2005-01-19 18:15:43 +00:00
|
|
|
struct pkcs15_prkey_object *prkey = (struct pkcs15_prkey_object*) object;
|
|
|
|
return pkcs15_set_attrib(session, prkey->base.p15_object, attr);
|
2003-06-27 12:00:43 +00:00
|
|
|
}
|
|
|
|
|
2004-12-22 10:17:00 +00:00
|
|
|
static CK_RV pkcs15_prkey_get_attribute(struct sc_pkcs11_session *session,
|
2002-01-16 22:49:03 +00:00
|
|
|
void *object,
|
|
|
|
CK_ATTRIBUTE_PTR attr)
|
|
|
|
{
|
|
|
|
struct pkcs15_prkey_object *prkey = (struct pkcs15_prkey_object*) object;
|
2006-02-09 20:05:20 +00:00
|
|
|
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) session->slot->card->fw_data;
|
2002-04-17 18:34:32 +00:00
|
|
|
struct sc_pkcs15_pubkey *key = NULL;
|
2003-04-17 13:13:48 +00:00
|
|
|
unsigned int usage;
|
2002-12-23 17:02:05 +00:00
|
|
|
size_t len;
|
2002-03-12 14:36:40 +00:00
|
|
|
|
2009-10-22 09:18:16 +00:00
|
|
|
/* PKCS#11 requires us to supply CKA_MODULUS for private keys,
|
|
|
|
* although that is not generally available from a smart card
|
|
|
|
* (the key is supposed to be safely locked away after all).
|
|
|
|
*
|
|
|
|
* To work around this, we hope that we either have an associated
|
|
|
|
* public key, or we try to find a certificate with the
|
|
|
|
* corresponding public key.
|
|
|
|
*
|
|
|
|
* Note: We do the same thing for CKA_PUBLIC_EXPONENT as some
|
|
|
|
* applications assume they can get that from the private
|
|
|
|
* key, something PKCS#11 doesn't guarantee.
|
|
|
|
*/
|
2010-12-01 20:08:42 +00:00
|
|
|
if ((attr->type == CKA_MODULUS) || (attr->type == CKA_PUBLIC_EXPONENT) ||
|
|
|
|
((attr->type == CKA_MODULUS_BITS) && (prkey->prv_p15obj->type == SC_PKCS15_TYPE_PRKEY_EC)) ||
|
|
|
|
(attr->type == CKA_ECDSA_PARAMS)) {
|
2009-10-22 09:18:16 +00:00
|
|
|
/* First see if we have a associated public key */
|
2010-12-01 20:08:42 +00:00
|
|
|
if (prkey->prv_pubkey && prkey->prv_pubkey->pub_data)
|
2009-10-22 09:18:16 +00:00
|
|
|
key = prkey->prv_pubkey->pub_data;
|
|
|
|
else {
|
|
|
|
/* Try to find a certificate with the public key */
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0; i < fw_data->num_objects; i++) {
|
|
|
|
struct pkcs15_any_object *obj = fw_data->objects[i];
|
|
|
|
struct pkcs15_cert_object *cert;
|
|
|
|
|
|
|
|
if (!is_cert(obj))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
cert = (struct pkcs15_cert_object*) obj;
|
|
|
|
|
|
|
|
if (cert->cert_prvkey != prkey)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (check_cert_data_read(fw_data, cert) == 0)
|
|
|
|
key = cert->cert_pubkey->pub_data;
|
|
|
|
}
|
2006-02-09 20:05:20 +00:00
|
|
|
}
|
2009-10-22 09:18:16 +00:00
|
|
|
}
|
2002-01-16 22:49:03 +00:00
|
|
|
|
|
|
|
switch (attr->type) {
|
|
|
|
case CKA_CLASS:
|
|
|
|
check_attribute_buffer(attr, sizeof(CK_OBJECT_CLASS));
|
|
|
|
*(CK_OBJECT_CLASS*)attr->pValue = CKO_PRIVATE_KEY;
|
2005-02-03 22:44:19 +00:00
|
|
|
break;
|
2002-01-16 22:49:03 +00:00
|
|
|
case CKA_TOKEN:
|
|
|
|
case CKA_LOCAL:
|
|
|
|
case CKA_SENSITIVE:
|
|
|
|
case CKA_ALWAYS_SENSITIVE:
|
|
|
|
case CKA_NEVER_EXTRACTABLE:
|
|
|
|
check_attribute_buffer(attr, sizeof(CK_BBOOL));
|
|
|
|
*(CK_BBOOL*)attr->pValue = TRUE;
|
2005-02-03 22:44:19 +00:00
|
|
|
break;
|
2009-09-14 08:51:53 +00:00
|
|
|
case CKA_ALWAYS_AUTHENTICATE:
|
|
|
|
check_attribute_buffer(attr, sizeof(CK_BBOOL));
|
|
|
|
*(CK_BBOOL*)attr->pValue = prkey->prv_p15obj->user_consent;
|
|
|
|
break;
|
2006-05-20 16:06:42 +00:00
|
|
|
case CKA_PRIVATE:
|
|
|
|
check_attribute_buffer(attr, sizeof(CK_BBOOL));
|
|
|
|
*(CK_BBOOL*)attr->pValue = (prkey->prv_p15obj->flags & SC_PKCS15_CO_FLAG_PRIVATE) != 0;
|
|
|
|
break;
|
2002-01-16 22:49:03 +00:00
|
|
|
case CKA_MODIFIABLE:
|
|
|
|
case CKA_EXTRACTABLE:
|
|
|
|
check_attribute_buffer(attr, sizeof(CK_BBOOL));
|
|
|
|
*(CK_BBOOL*)attr->pValue = FALSE;
|
2005-02-03 22:44:19 +00:00
|
|
|
break;
|
2002-01-16 22:49:03 +00:00
|
|
|
case CKA_LABEL:
|
2003-04-16 14:17:02 +00:00
|
|
|
len = strlen(prkey->prv_p15obj->label);
|
2002-12-23 17:02:05 +00:00
|
|
|
check_attribute_buffer(attr, len);
|
2005-02-03 22:44:19 +00:00
|
|
|
memcpy(attr->pValue, prkey->prv_p15obj->label, len);
|
2002-01-16 22:49:03 +00:00
|
|
|
break;
|
|
|
|
case CKA_KEY_TYPE:
|
|
|
|
check_attribute_buffer(attr, sizeof(CK_KEY_TYPE));
|
2010-12-01 20:08:42 +00:00
|
|
|
switch (prkey->prv_p15obj->type) {
|
|
|
|
case SC_PKCS15_TYPE_PRKEY_RSA:
|
|
|
|
*(CK_KEY_TYPE*)attr->pValue = CKK_RSA;
|
|
|
|
break;
|
|
|
|
case SC_PKCS15_TYPE_PRKEY_GOSTR3410:
|
|
|
|
*(CK_KEY_TYPE*)attr->pValue = CKK_GOSTR3410;
|
|
|
|
break;
|
|
|
|
case SC_PKCS15_TYPE_PRKEY_EC:
|
|
|
|
*(CK_KEY_TYPE*)attr->pValue = CKK_EC;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return CKR_GENERAL_ERROR; /* Internal error*/
|
|
|
|
}
|
2005-02-03 22:44:19 +00:00
|
|
|
break;
|
2002-01-16 22:49:03 +00:00
|
|
|
case CKA_ID:
|
2003-02-23 17:50:33 +00:00
|
|
|
check_attribute_buffer(attr, prkey->prv_info->id.len);
|
|
|
|
memcpy(attr->pValue, prkey->prv_info->id.value, prkey->prv_info->id.len);
|
2005-02-03 22:44:19 +00:00
|
|
|
break;
|
2002-01-16 22:49:03 +00:00
|
|
|
case CKA_KEY_GEN_MECHANISM:
|
|
|
|
check_attribute_buffer(attr, sizeof(CK_MECHANISM_TYPE));
|
2005-02-03 22:44:19 +00:00
|
|
|
*(CK_MECHANISM_TYPE*)attr->pValue = CK_UNAVAILABLE_INFORMATION;
|
2002-01-16 22:49:03 +00:00
|
|
|
break;
|
2002-12-18 19:26:18 +00:00
|
|
|
case CKA_ENCRYPT:
|
|
|
|
case CKA_DECRYPT:
|
|
|
|
case CKA_SIGN:
|
|
|
|
case CKA_SIGN_RECOVER:
|
|
|
|
case CKA_WRAP:
|
|
|
|
case CKA_UNWRAP:
|
|
|
|
case CKA_VERIFY:
|
|
|
|
case CKA_VERIFY_RECOVER:
|
|
|
|
case CKA_DERIVE:
|
2003-04-17 13:13:48 +00:00
|
|
|
/* Combine the usage bits of all split keys */
|
|
|
|
for (usage = 0; prkey; prkey = prkey->prv_next)
|
|
|
|
usage |= prkey->prv_info->usage;
|
|
|
|
return get_usage_bit(usage, attr);
|
2002-01-16 22:49:03 +00:00
|
|
|
case CKA_MODULUS:
|
2002-03-12 14:36:40 +00:00
|
|
|
return get_modulus(key, attr);
|
2004-12-20 19:44:38 +00:00
|
|
|
/* XXX: this should be removed sometimes as a private key has no
|
|
|
|
* CKA_MODULUS_BITS attribute, but unfortunately other parts depend
|
|
|
|
* on this -- Nils */
|
2002-03-12 14:36:40 +00:00
|
|
|
case CKA_MODULUS_BITS:
|
2003-01-02 15:23:08 +00:00
|
|
|
check_attribute_buffer(attr, sizeof(CK_ULONG));
|
2010-12-01 20:08:42 +00:00
|
|
|
switch (prkey->prv_p15obj->type) {
|
|
|
|
case SC_PKCS15_TYPE_PRKEY_EC:
|
|
|
|
if (key)
|
2011-04-22 13:08:45 +00:00
|
|
|
*(CK_ULONG *) attr->pValue = key->u.ec.params.field_length;
|
2010-12-01 20:08:42 +00:00
|
|
|
else
|
|
|
|
*(CK_ULONG *) attr->pValue = 384; /* TODO -DEE needs work */
|
|
|
|
return CKR_OK;
|
|
|
|
default:
|
|
|
|
*(CK_ULONG *) attr->pValue = prkey->prv_info->modulus_length;
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
2002-01-16 22:49:03 +00:00
|
|
|
case CKA_PUBLIC_EXPONENT:
|
2002-03-12 14:36:40 +00:00
|
|
|
return get_public_exponent(key, attr);
|
2002-01-16 22:49:03 +00:00
|
|
|
case CKA_PRIVATE_EXPONENT:
|
|
|
|
case CKA_PRIME_1:
|
|
|
|
case CKA_PRIME_2:
|
|
|
|
case CKA_EXPONENT_1:
|
|
|
|
case CKA_EXPONENT_2:
|
|
|
|
case CKA_COEFFICIENT:
|
|
|
|
return CKR_ATTRIBUTE_SENSITIVE;
|
2003-07-30 14:46:27 +00:00
|
|
|
case CKA_SUBJECT:
|
|
|
|
case CKA_START_DATE:
|
|
|
|
case CKA_END_DATE:
|
2003-07-31 08:10:23 +00:00
|
|
|
attr->ulValueLen = 0;
|
2003-07-30 14:46:27 +00:00
|
|
|
return CKR_OK;
|
2009-11-27 11:07:23 +00:00
|
|
|
case CKA_GOSTR3410_PARAMS:
|
2011-05-01 19:18:14 +00:00
|
|
|
if (prkey->prv_info && prkey->prv_info->params.len)
|
|
|
|
return get_gostr3410_params(prkey->prv_info->params.data,
|
|
|
|
prkey->prv_info->params.len, attr);
|
2009-11-27 11:07:23 +00:00
|
|
|
else
|
|
|
|
return CKR_ATTRIBUTE_TYPE_INVALID;
|
2010-12-01 20:08:42 +00:00
|
|
|
case CKA_EC_PARAMS:
|
|
|
|
return get_ec_pubkey_params(key, attr); /* get from pubkey for now */
|
2002-01-16 22:49:03 +00:00
|
|
|
default:
|
2005-01-19 18:15:43 +00:00
|
|
|
return CKR_ATTRIBUTE_TYPE_INVALID;
|
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
|
|
|
}
|
|
|
|
|
2004-12-22 10:17:00 +00:00
|
|
|
static CK_RV pkcs15_prkey_sign(struct sc_pkcs11_session *ses, void *obj,
|
2002-01-16 22:49:03 +00:00
|
|
|
CK_MECHANISM_PTR pMechanism, CK_BYTE_PTR pData,
|
|
|
|
CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
|
|
|
|
CK_ULONG_PTR pulDataLen)
|
|
|
|
{
|
|
|
|
struct pkcs15_prkey_object *prkey = (struct pkcs15_prkey_object *) obj;
|
2003-02-23 17:50:33 +00:00
|
|
|
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) ses->slot->card->fw_data;
|
2002-01-21 09:05:22 +00:00
|
|
|
int rv, flags = 0;
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "Initiating signing operation, mechanism 0x%x.\n",
|
2002-12-19 09:27:08 +00:00
|
|
|
pMechanism->mechanism);
|
2002-01-16 22:49:03 +00:00
|
|
|
|
2003-04-17 13:13:48 +00:00
|
|
|
/* See which of the alternative keys supports signing */
|
|
|
|
while (prkey
|
|
|
|
&& !(prkey->prv_info->usage
|
2003-04-18 15:42:04 +00:00
|
|
|
& (SC_PKCS15_PRKEY_USAGE_SIGN|SC_PKCS15_PRKEY_USAGE_SIGNRECOVER|
|
2005-02-11 20:09:34 +00:00
|
|
|
SC_PKCS15_PRKEY_USAGE_NONREPUDIATION)))
|
2003-04-17 13:13:48 +00:00
|
|
|
prkey = prkey->prv_next;
|
|
|
|
|
|
|
|
if (prkey == NULL)
|
|
|
|
return CKR_KEY_FUNCTION_NOT_PERMITTED;
|
|
|
|
|
2002-01-16 22:49:03 +00:00
|
|
|
switch (pMechanism->mechanism) {
|
|
|
|
case CKM_RSA_PKCS:
|
2003-11-23 16:11:32 +00:00
|
|
|
flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE;
|
2002-01-16 22:49:03 +00:00
|
|
|
break;
|
2002-12-19 09:27:08 +00:00
|
|
|
case CKM_MD5_RSA_PKCS:
|
|
|
|
flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_MD5;
|
|
|
|
break;
|
|
|
|
case CKM_SHA1_RSA_PKCS:
|
|
|
|
flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_SHA1;
|
|
|
|
break;
|
2007-02-02 22:15:14 +00:00
|
|
|
case CKM_SHA256_RSA_PKCS:
|
|
|
|
flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_SHA256;
|
|
|
|
break;
|
|
|
|
case CKM_SHA384_RSA_PKCS:
|
|
|
|
flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_SHA384;
|
|
|
|
break;
|
|
|
|
case CKM_SHA512_RSA_PKCS:
|
|
|
|
flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_SHA512;
|
|
|
|
break;
|
2002-12-19 09:27:08 +00:00
|
|
|
case CKM_RIPEMD160_RSA_PKCS:
|
|
|
|
flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_RIPEMD160;
|
|
|
|
break;
|
2002-12-10 17:47:10 +00:00
|
|
|
case CKM_RSA_X_509:
|
|
|
|
flags = SC_ALGORITHM_RSA_RAW;
|
|
|
|
break;
|
2009-10-05 20:10:07 +00:00
|
|
|
case CKM_GOSTR3410:
|
|
|
|
flags = SC_ALGORITHM_GOSTR3410_HASH_NONE;
|
|
|
|
break;
|
|
|
|
case CKM_GOSTR3410_WITH_GOSTR3411:
|
|
|
|
flags = SC_ALGORITHM_GOSTR3410_HASH_GOSTR3411;
|
|
|
|
break;
|
2010-12-01 20:08:42 +00:00
|
|
|
case CKM_ECDSA:
|
|
|
|
flags = SC_ALGORITHM_ECDSA_HASH_NONE;
|
|
|
|
break;
|
|
|
|
case CKM_ECDSA_SHA1:
|
|
|
|
flags = SC_ALGORITHM_ECDSA_HASH_SHA1;
|
|
|
|
break;
|
|
|
|
#if 0
|
|
|
|
case CKM_ECDSA_SHA224:
|
|
|
|
flags = SC_ALGORITHM_ECDSA_HASH_SHA224;
|
|
|
|
break;
|
|
|
|
case CKM_ECDSA_SHA256:
|
|
|
|
flags = SC_ALGORITHM_ECDSA_HASH_SHA256;
|
|
|
|
break;
|
|
|
|
case CKM_ECDSA_SHA384:
|
|
|
|
flags = SC_ALGORITHM_ECDSA_HASH_SHA384;
|
|
|
|
break;
|
|
|
|
case CKM_ECDSA_SHA512:
|
|
|
|
flags = SC_ALGORITHM_ECDSA_HASH_SHA512;
|
|
|
|
break;
|
|
|
|
#endif
|
2002-01-16 22:49:03 +00:00
|
|
|
default:
|
2010-12-01 20:08:42 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "DEE - need EC for %d",pMechanism->mechanism);
|
2005-01-19 18:15:43 +00:00
|
|
|
return CKR_MECHANISM_INVALID;
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
|
2005-02-01 19:02:15 +00:00
|
|
|
rv = sc_lock(ses->slot->card->card);
|
|
|
|
if (rv < 0)
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rv, "C_Sign");
|
2005-02-01 19:02:15 +00:00
|
|
|
|
|
|
|
if (!sc_pkcs11_conf.lock_login) {
|
|
|
|
rv = reselect_app_df(fw_data->p15_card);
|
|
|
|
if (rv < 0) {
|
|
|
|
sc_unlock(ses->slot->card->card);
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rv, "C_Sign");
|
2005-02-01 19:02:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "Selected flags %X. Now computing signature for %d bytes. %d bytes reserved.\n", flags, ulDataLen, *pulDataLen);
|
2003-02-23 17:50:33 +00:00
|
|
|
rv = sc_pkcs15_compute_signature(fw_data->p15_card,
|
|
|
|
prkey->prv_p15obj,
|
2002-01-21 09:05:22 +00:00
|
|
|
flags,
|
2002-01-16 22:49:03 +00:00
|
|
|
pData,
|
|
|
|
ulDataLen,
|
|
|
|
pSignature,
|
|
|
|
*pulDataLen);
|
2003-05-15 10:34:03 +00:00
|
|
|
|
2005-02-01 19:02:15 +00:00
|
|
|
sc_unlock(ses->slot->card->card);
|
|
|
|
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "Sign complete. Result %d.\n", rv);
|
2002-01-16 22:49:03 +00:00
|
|
|
|
|
|
|
if (rv > 0) {
|
2005-01-19 18:15:43 +00:00
|
|
|
*pulDataLen = rv;
|
|
|
|
return CKR_OK;
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rv, "C_Sign");
|
2002-01-16 22:49:03 +00:00
|
|
|
}
|
|
|
|
|
2002-03-15 15:22:41 +00:00
|
|
|
static CK_RV
|
2003-10-01 06:51:49 +00:00
|
|
|
pkcs15_prkey_decrypt(struct sc_pkcs11_session *ses, void *obj,
|
2002-03-15 15:22:41 +00:00
|
|
|
CK_MECHANISM_PTR pMechanism,
|
2003-10-01 06:51:49 +00:00
|
|
|
CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen,
|
|
|
|
CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
|
2002-03-15 15:22:41 +00:00
|
|
|
{
|
2003-02-23 17:50:33 +00:00
|
|
|
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) ses->slot->card->fw_data;
|
2002-03-15 15:22:41 +00:00
|
|
|
struct pkcs15_prkey_object *prkey;
|
2010-09-01 11:46:37 +00:00
|
|
|
u8 decrypted[256]; /* FIXME: Will not work for keys above 2048 bits */
|
2003-11-26 13:12:26 +00:00
|
|
|
int buff_too_small, rv, flags = 0;
|
2002-03-15 15:22:41 +00:00
|
|
|
|
2010-08-23 14:47:07 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "Initiating decryption.\n");
|
2002-03-15 15:22:41 +00:00
|
|
|
|
2010-08-23 14:47:07 +00:00
|
|
|
/* See which of the alternative keys supports decrypt */
|
2003-04-17 14:38:00 +00:00
|
|
|
prkey = (struct pkcs15_prkey_object *) obj;
|
2003-04-17 13:13:48 +00:00
|
|
|
while (prkey
|
|
|
|
&& !(prkey->prv_info->usage
|
|
|
|
& (SC_PKCS15_PRKEY_USAGE_DECRYPT|SC_PKCS15_PRKEY_USAGE_UNWRAP)))
|
|
|
|
prkey = prkey->prv_next;
|
|
|
|
|
|
|
|
if (prkey == NULL)
|
|
|
|
return CKR_KEY_FUNCTION_NOT_PERMITTED;
|
|
|
|
|
2003-11-26 13:12:26 +00:00
|
|
|
/* Select the proper padding mechanism */
|
|
|
|
switch (pMechanism->mechanism) {
|
|
|
|
case CKM_RSA_PKCS:
|
2005-02-11 20:09:34 +00:00
|
|
|
flags |= SC_ALGORITHM_RSA_PAD_PKCS1;
|
2003-11-26 13:12:26 +00:00
|
|
|
break;
|
|
|
|
case CKM_RSA_X_509:
|
|
|
|
flags |= SC_ALGORITHM_RSA_RAW;
|
|
|
|
break;
|
|
|
|
default:
|
2009-10-22 09:18:16 +00:00
|
|
|
return CKR_MECHANISM_INVALID;
|
2003-11-26 13:12:26 +00:00
|
|
|
}
|
2002-03-15 15:22:41 +00:00
|
|
|
|
2005-02-01 19:02:15 +00:00
|
|
|
rv = sc_lock(ses->slot->card->card);
|
|
|
|
if (rv < 0)
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rv, "C_Decrypt");
|
2005-02-01 19:02:15 +00:00
|
|
|
|
|
|
|
if (!sc_pkcs11_conf.lock_login) {
|
|
|
|
rv = reselect_app_df(fw_data->p15_card);
|
|
|
|
if (rv < 0) {
|
|
|
|
sc_unlock(ses->slot->card->card);
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rv, "C_Decrypt");
|
2005-02-01 19:02:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-02-23 17:50:33 +00:00
|
|
|
rv = sc_pkcs15_decipher(fw_data->p15_card, prkey->prv_p15obj,
|
2005-02-11 20:09:34 +00:00
|
|
|
flags, pEncryptedData, ulEncryptedDataLen,
|
2003-10-01 06:51:49 +00:00
|
|
|
decrypted, sizeof(decrypted));
|
2003-05-15 10:34:03 +00:00
|
|
|
|
2005-02-01 19:02:15 +00:00
|
|
|
sc_unlock(ses->slot->card->card);
|
2003-05-15 10:34:03 +00:00
|
|
|
|
2010-09-01 11:46:37 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "Decryption complete. Result %d.\n", rv);
|
2003-10-01 06:51:49 +00:00
|
|
|
|
|
|
|
if (rv < 0)
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rv, "C_Decrypt");
|
2003-10-01 06:51:49 +00:00
|
|
|
|
2004-12-22 10:17:00 +00:00
|
|
|
buff_too_small = (*pulDataLen < (CK_ULONG)rv);
|
2003-10-01 06:51:49 +00:00
|
|
|
*pulDataLen = rv;
|
|
|
|
if (pData == NULL_PTR)
|
|
|
|
return CKR_OK;
|
|
|
|
if (buff_too_small)
|
|
|
|
return CKR_BUFFER_TOO_SMALL;
|
|
|
|
memcpy(pData, decrypted, *pulDataLen);
|
|
|
|
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
|
|
|
|
2002-01-16 22:49:03 +00:00
|
|
|
struct sc_pkcs11_object_ops pkcs15_prkey_ops = {
|
2003-02-23 17:50:33 +00:00
|
|
|
pkcs15_prkey_release,
|
2003-06-27 12:00:43 +00:00
|
|
|
pkcs15_prkey_set_attribute,
|
2002-01-16 22:49:03 +00:00
|
|
|
pkcs15_prkey_get_attribute,
|
2002-03-18 11:05:21 +00:00
|
|
|
sc_pkcs11_any_cmp_attribute,
|
2010-04-20 15:11:58 +00:00
|
|
|
pkcs15_any_destroy,
|
2002-01-16 22:49:03 +00:00
|
|
|
NULL,
|
2005-01-19 18:15:43 +00:00
|
|
|
pkcs15_prkey_sign,
|
2010-08-23 14:47:07 +00:00
|
|
|
NULL, /* unwrap */
|
2003-10-01 06:51:49 +00:00
|
|
|
pkcs15_prkey_decrypt
|
2002-01-16 22:49:03 +00:00
|
|
|
};
|
|
|
|
|
2002-01-24 16:27:09 +00:00
|
|
|
/*
|
2003-02-23 17:50:33 +00:00
|
|
|
* PKCS#15 RSA Public Key Object
|
2002-01-24 16:27:09 +00:00
|
|
|
*/
|
2004-12-22 10:17:00 +00:00
|
|
|
static void pkcs15_pubkey_release(void *object)
|
2002-01-24 16:27:09 +00:00
|
|
|
{
|
2003-02-23 17:50:33 +00:00
|
|
|
struct pkcs15_pubkey_object *pubkey = (struct pkcs15_pubkey_object*) object;
|
|
|
|
struct sc_pkcs15_pubkey *key_data = pubkey->pub_data;
|
2002-03-12 14:36:40 +00:00
|
|
|
|
2006-02-09 20:05:20 +00:00
|
|
|
if (__pkcs15_release_object((struct pkcs15_any_object *) object) == 0) {
|
|
|
|
if (key_data)
|
|
|
|
sc_pkcs15_free_pubkey(key_data);
|
|
|
|
}
|
2002-03-12 14:36:40 +00:00
|
|
|
}
|
|
|
|
|
2004-12-22 10:17:00 +00:00
|
|
|
static CK_RV pkcs15_pubkey_set_attribute(struct sc_pkcs11_session *session,
|
2003-06-27 12:00:43 +00:00
|
|
|
void *object,
|
|
|
|
CK_ATTRIBUTE_PTR attr)
|
|
|
|
{
|
2005-01-19 18:15:43 +00:00
|
|
|
struct pkcs15_pubkey_object *pubkey = (struct pkcs15_pubkey_object*) object;
|
|
|
|
return pkcs15_set_attrib(session, pubkey->base.p15_object, attr);
|
2003-06-27 12:00:43 +00:00
|
|
|
}
|
|
|
|
|
2004-12-22 10:17:00 +00:00
|
|
|
static CK_RV pkcs15_pubkey_get_attribute(struct sc_pkcs11_session *session,
|
2002-03-12 14:36:40 +00:00
|
|
|
void *object,
|
|
|
|
CK_ATTRIBUTE_PTR attr)
|
|
|
|
{
|
|
|
|
struct pkcs15_pubkey_object *pubkey = (struct pkcs15_pubkey_object*) object;
|
2009-10-22 09:18:16 +00:00
|
|
|
struct pkcs15_cert_object *cert = pubkey->pub_genfrom;
|
2006-02-09 20:05:20 +00:00
|
|
|
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) session->slot->card->fw_data;
|
2002-12-23 17:02:05 +00:00
|
|
|
size_t len;
|
2002-03-12 14:36:40 +00:00
|
|
|
|
2006-02-09 20:05:20 +00:00
|
|
|
/* We may need to get these from cert */
|
|
|
|
switch (attr->type) {
|
|
|
|
case CKA_MODULUS:
|
|
|
|
case CKA_MODULUS_BITS:
|
|
|
|
case CKA_VALUE:
|
|
|
|
case CKA_PUBLIC_EXPONENT:
|
2010-12-01 20:08:42 +00:00
|
|
|
case CKA_EC_PARAMS:
|
|
|
|
case CKA_EC_POINT:
|
2006-02-09 20:05:20 +00:00
|
|
|
if (pubkey->pub_data == NULL)
|
2006-04-26 10:00:23 +00:00
|
|
|
/* FIXME: check the return value? */
|
2006-02-09 20:05:20 +00:00
|
|
|
check_cert_data_read(fw_data, cert);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2002-03-12 14:36:40 +00:00
|
|
|
switch (attr->type) {
|
|
|
|
case CKA_CLASS:
|
|
|
|
check_attribute_buffer(attr, sizeof(CK_OBJECT_CLASS));
|
|
|
|
*(CK_OBJECT_CLASS*)attr->pValue = CKO_PUBLIC_KEY;
|
2005-02-11 20:09:34 +00:00
|
|
|
break;
|
2002-03-12 14:36:40 +00:00
|
|
|
case CKA_TOKEN:
|
|
|
|
case CKA_LOCAL:
|
|
|
|
case CKA_SENSITIVE:
|
|
|
|
case CKA_ALWAYS_SENSITIVE:
|
|
|
|
case CKA_NEVER_EXTRACTABLE:
|
|
|
|
check_attribute_buffer(attr, sizeof(CK_BBOOL));
|
|
|
|
*(CK_BBOOL*)attr->pValue = TRUE;
|
2005-02-11 20:09:34 +00:00
|
|
|
break;
|
2002-03-12 14:36:40 +00:00
|
|
|
case CKA_PRIVATE:
|
2006-02-09 20:05:20 +00:00
|
|
|
check_attribute_buffer(attr, sizeof(CK_BBOOL));
|
|
|
|
if (pubkey->pub_p15obj) {
|
|
|
|
*(CK_BBOOL*)attr->pValue =
|
|
|
|
(pubkey->pub_p15obj->flags & SC_PKCS15_CO_FLAG_PRIVATE) != 0;
|
|
|
|
} else if (cert && cert->cert_p15obj) {
|
|
|
|
*(CK_BBOOL*)attr->pValue =
|
|
|
|
(cert->pub_p15obj->flags & SC_PKCS15_CO_FLAG_PRIVATE) != 0;
|
|
|
|
} else {
|
|
|
|
return CKR_ATTRIBUTE_TYPE_INVALID;
|
|
|
|
}
|
|
|
|
break;
|
2002-03-12 14:36:40 +00:00
|
|
|
case CKA_MODIFIABLE:
|
|
|
|
case CKA_EXTRACTABLE:
|
|
|
|
check_attribute_buffer(attr, sizeof(CK_BBOOL));
|
|
|
|
*(CK_BBOOL*)attr->pValue = FALSE;
|
2005-02-11 20:09:34 +00:00
|
|
|
break;
|
2002-03-12 14:36:40 +00:00
|
|
|
case CKA_LABEL:
|
2003-02-23 17:50:33 +00:00
|
|
|
if (pubkey->pub_p15obj) {
|
2003-04-16 14:17:02 +00:00
|
|
|
len = strlen(pubkey->pub_p15obj->label);
|
2003-02-23 17:50:33 +00:00
|
|
|
check_attribute_buffer(attr, len);
|
|
|
|
memcpy(attr->pValue, pubkey->pub_p15obj->label, len);
|
|
|
|
} else if (cert && cert->cert_p15obj) {
|
2003-04-16 14:17:02 +00:00
|
|
|
len = strlen(cert->cert_p15obj->label);
|
2003-02-23 17:50:33 +00:00
|
|
|
check_attribute_buffer(attr, len);
|
|
|
|
memcpy(attr->pValue, cert->cert_p15obj->label, len);
|
|
|
|
} else {
|
|
|
|
return CKR_ATTRIBUTE_TYPE_INVALID;
|
|
|
|
}
|
2002-03-07 11:57:49 +00:00
|
|
|
break;
|
2002-03-12 14:36:40 +00:00
|
|
|
case CKA_KEY_TYPE:
|
|
|
|
check_attribute_buffer(attr, sizeof(CK_KEY_TYPE));
|
2010-12-01 20:08:42 +00:00
|
|
|
/* TODO: -DEE why would we not have a pubkey->pub_data? */
|
|
|
|
/* even if we do not, we should not assume RSA */
|
2009-10-05 20:10:07 +00:00
|
|
|
if (pubkey->pub_data && pubkey->pub_data->algorithm == SC_ALGORITHM_GOSTR3410)
|
|
|
|
*(CK_KEY_TYPE*)attr->pValue = CKK_GOSTR3410;
|
2010-12-01 20:08:42 +00:00
|
|
|
else if (pubkey->pub_data && pubkey->pub_data->algorithm == SC_ALGORITHM_EC)
|
|
|
|
*(CK_KEY_TYPE*)attr->pValue = CKK_EC;
|
2009-10-05 20:10:07 +00:00
|
|
|
else
|
|
|
|
*(CK_KEY_TYPE*)attr->pValue = CKK_RSA;
|
2005-02-11 20:09:34 +00:00
|
|
|
break;
|
2002-03-12 14:36:40 +00:00
|
|
|
case CKA_ID:
|
2003-02-23 17:50:33 +00:00
|
|
|
if (pubkey->pub_info) {
|
|
|
|
check_attribute_buffer(attr, pubkey->pub_info->id.len);
|
|
|
|
memcpy(attr->pValue, pubkey->pub_info->id.value, pubkey->pub_info->id.len);
|
|
|
|
} else if (cert && cert->cert_info) {
|
|
|
|
check_attribute_buffer(attr, cert->cert_info->id.len);
|
|
|
|
memcpy(attr->pValue, cert->cert_info->id.value, cert->cert_info->id.len);
|
|
|
|
} else {
|
|
|
|
return CKR_ATTRIBUTE_TYPE_INVALID;
|
|
|
|
}
|
2005-02-11 20:09:34 +00:00
|
|
|
break;
|
2002-03-12 14:36:40 +00:00
|
|
|
case CKA_KEY_GEN_MECHANISM:
|
|
|
|
check_attribute_buffer(attr, sizeof(CK_MECHANISM_TYPE));
|
2005-02-11 20:09:34 +00:00
|
|
|
*(CK_MECHANISM_TYPE*)attr->pValue = CK_UNAVAILABLE_INFORMATION;
|
2002-03-12 14:36:40 +00:00
|
|
|
break;
|
2002-12-18 19:26:18 +00:00
|
|
|
case CKA_ENCRYPT:
|
|
|
|
case CKA_DECRYPT:
|
|
|
|
case CKA_SIGN:
|
|
|
|
case CKA_SIGN_RECOVER:
|
|
|
|
case CKA_WRAP:
|
|
|
|
case CKA_UNWRAP:
|
|
|
|
case CKA_VERIFY:
|
|
|
|
case CKA_VERIFY_RECOVER:
|
|
|
|
case CKA_DERIVE:
|
2003-02-23 17:50:33 +00:00
|
|
|
if (pubkey->pub_info) {
|
|
|
|
return get_usage_bit(pubkey->pub_info->usage, attr);
|
|
|
|
} else {
|
|
|
|
return get_usage_bit(SC_PKCS15_PRKEY_USAGE_ENCRYPT
|
|
|
|
|SC_PKCS15_PRKEY_USAGE_VERIFY
|
|
|
|
|SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER,
|
|
|
|
attr);
|
|
|
|
}
|
2002-03-12 14:36:40 +00:00
|
|
|
case CKA_MODULUS:
|
2003-02-23 17:50:33 +00:00
|
|
|
return get_modulus(pubkey->pub_data, attr);
|
2002-03-12 14:36:40 +00:00
|
|
|
case CKA_MODULUS_BITS:
|
2003-02-23 17:50:33 +00:00
|
|
|
return get_modulus_bits(pubkey->pub_data, attr);
|
2002-03-12 14:36:40 +00:00
|
|
|
case CKA_PUBLIC_EXPONENT:
|
2003-02-23 17:50:33 +00:00
|
|
|
return get_public_exponent(pubkey->pub_data, attr);
|
2003-04-17 14:38:00 +00:00
|
|
|
case CKA_VALUE:
|
|
|
|
if (pubkey->pub_data) {
|
2010-12-01 20:08:42 +00:00
|
|
|
/* TODO: -DEE Not all pubkeys have CKA_VALUE attribute. RSA and EC
|
|
|
|
* for example don't. So why is this here?
|
|
|
|
* Why checking for cert in this pkcs15_pubkey_get_attribute?
|
|
|
|
*/
|
2003-04-17 14:38:00 +00:00
|
|
|
check_attribute_buffer(attr, pubkey->pub_data->data.len);
|
|
|
|
memcpy(attr->pValue, pubkey->pub_data->data.value,
|
|
|
|
pubkey->pub_data->data.len);
|
|
|
|
} else if (cert && cert->cert_data) {
|
|
|
|
check_attribute_buffer(attr, cert->cert_data->data_len);
|
|
|
|
memcpy(attr->pValue, cert->cert_data->data, cert->cert_data->data_len);
|
|
|
|
}
|
|
|
|
break;
|
2009-10-05 20:10:07 +00:00
|
|
|
case CKA_GOSTR3410_PARAMS:
|
2011-05-01 19:18:14 +00:00
|
|
|
if (pubkey->pub_info && pubkey->pub_info->params.len)
|
|
|
|
return get_gostr3410_params(pubkey->pub_info->params.data,
|
|
|
|
pubkey->pub_info->params.len, attr);
|
2009-10-05 20:10:07 +00:00
|
|
|
else
|
|
|
|
return CKR_ATTRIBUTE_TYPE_INVALID;
|
2010-12-01 20:08:42 +00:00
|
|
|
case CKA_EC_PARAMS:
|
|
|
|
return get_ec_pubkey_params(pubkey->pub_data, attr);
|
|
|
|
case CKA_EC_POINT:
|
|
|
|
return get_ec_pubkey_point(pubkey->pub_data, attr);
|
|
|
|
|
2002-01-24 16:27:09 +00:00
|
|
|
default:
|
2005-01-19 18:15:43 +00:00
|
|
|
return CKR_ATTRIBUTE_TYPE_INVALID;
|
2002-01-24 16:27:09 +00:00
|
|
|
}
|
|
|
|
|
2005-01-19 18:15:43 +00:00
|
|
|
return CKR_OK;
|
2002-01-24 16:27:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct sc_pkcs11_object_ops pkcs15_pubkey_ops = {
|
2003-02-23 17:50:33 +00:00
|
|
|
pkcs15_pubkey_release,
|
2003-06-27 12:00:43 +00:00
|
|
|
pkcs15_pubkey_set_attribute,
|
2002-01-24 16:27:09 +00:00
|
|
|
pkcs15_pubkey_get_attribute,
|
2002-03-18 11:05:21 +00:00
|
|
|
sc_pkcs11_any_cmp_attribute,
|
2010-04-20 15:11:58 +00:00
|
|
|
pkcs15_any_destroy,
|
2002-01-24 16:27:09 +00:00
|
|
|
NULL,
|
2005-09-07 09:32:52 +00:00
|
|
|
NULL,
|
|
|
|
NULL,
|
2005-01-19 18:15:43 +00:00
|
|
|
NULL
|
2002-01-24 16:27:09 +00:00
|
|
|
};
|
|
|
|
|
2004-07-26 18:47:23 +00:00
|
|
|
|
|
|
|
/* PKCS#15 Data Object*/
|
|
|
|
|
2004-12-22 10:17:00 +00:00
|
|
|
static void pkcs15_dobj_release(void *object)
|
2004-07-26 18:47:23 +00:00
|
|
|
{
|
|
|
|
__pkcs15_release_object((struct pkcs15_any_object *) object);
|
|
|
|
}
|
|
|
|
|
2004-12-22 10:17:00 +00:00
|
|
|
static CK_RV pkcs15_dobj_set_attribute(struct sc_pkcs11_session *session,
|
2004-07-26 18:47:23 +00:00
|
|
|
void *object, CK_ATTRIBUTE_PTR attr)
|
|
|
|
{
|
|
|
|
struct pkcs15_data_object *dobj = (struct pkcs15_data_object*) object;
|
|
|
|
|
|
|
|
return pkcs15_set_attrib(session, dobj->base.p15_object, attr);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-12-22 10:17:00 +00:00
|
|
|
static int pkcs15_dobj_get_value(struct sc_pkcs11_session *session,
|
2004-07-26 18:47:23 +00:00
|
|
|
struct pkcs15_data_object *dobj,
|
2005-02-11 20:09:34 +00:00
|
|
|
struct sc_pkcs15_data **out_data)
|
2004-07-26 18:47:23 +00:00
|
|
|
{
|
|
|
|
int rv;
|
2005-02-11 20:09:34 +00:00
|
|
|
struct pkcs15_fw_data *fw_data =
|
2004-07-26 18:47:23 +00:00
|
|
|
(struct pkcs15_fw_data *) session->slot->card->fw_data;
|
2005-03-09 00:04:44 +00:00
|
|
|
sc_card_t *card = session->slot->card->card;
|
2004-07-26 18:47:23 +00:00
|
|
|
|
|
|
|
if (!out_data)
|
|
|
|
return SC_ERROR_INVALID_ARGUMENTS;
|
|
|
|
|
|
|
|
rv = sc_lock(card);
|
|
|
|
if (rv < 0)
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rv, "C_GetAttributeValue");
|
2004-07-26 18:47:23 +00:00
|
|
|
|
2007-06-21 09:37:18 +00:00
|
|
|
rv = sc_pkcs15_read_data_object(fw_data->p15_card, dobj->info, out_data);
|
|
|
|
|
2004-07-26 18:47:23 +00:00
|
|
|
sc_unlock(card);
|
|
|
|
if (rv < 0)
|
2010-04-21 10:51:13 +00:00
|
|
|
return sc_to_cryptoki_error(rv, "C_GetAttributeValue");
|
2004-07-26 18:47:23 +00:00
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2008-01-03 08:59:14 +00:00
|
|
|
static CK_RV data_value_to_attr(CK_ATTRIBUTE_PTR attr, struct sc_pkcs15_data *data)
|
|
|
|
{
|
|
|
|
if (!attr || !data)
|
|
|
|
return CKR_ATTRIBUTE_VALUE_INVALID;
|
|
|
|
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "data %p\n", data);
|
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "data_len %i\n", data->data_len);
|
2004-07-26 18:47:23 +00:00
|
|
|
|
2008-01-03 08:59:14 +00:00
|
|
|
check_attribute_buffer(attr, data->data_len);
|
|
|
|
memcpy(attr->pValue, data->data, data->data_len);
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
2004-07-26 18:47:23 +00:00
|
|
|
|
2004-12-22 10:17:00 +00:00
|
|
|
static CK_RV pkcs15_dobj_get_attribute(struct sc_pkcs11_session *session,
|
2004-07-26 18:47:23 +00:00
|
|
|
void *object,
|
|
|
|
CK_ATTRIBUTE_PTR attr)
|
|
|
|
{
|
|
|
|
struct pkcs15_data_object *dobj = (struct pkcs15_data_object*) object;
|
|
|
|
size_t len;
|
|
|
|
|
|
|
|
switch (attr->type) {
|
|
|
|
case CKA_CLASS:
|
|
|
|
check_attribute_buffer(attr, sizeof(CK_OBJECT_CLASS));
|
|
|
|
*(CK_OBJECT_CLASS*)attr->pValue = CKO_DATA;
|
|
|
|
break;
|
|
|
|
case CKA_TOKEN:
|
|
|
|
check_attribute_buffer(attr, sizeof(CK_BBOOL));
|
|
|
|
*(CK_BBOOL*)attr->pValue = TRUE;
|
|
|
|
break;
|
|
|
|
case CKA_PRIVATE:
|
|
|
|
check_attribute_buffer(attr, sizeof(CK_BBOOL));
|
2005-02-11 20:09:34 +00:00
|
|
|
*(CK_BBOOL*)attr->pValue =
|
Douglas E. Engert:
Looking at framework-pkcs11.c, it looks like there is a bug in the handling of
auth_count, if there is more then one pin, and one of the pins is a
SC_PKCS15_PIN_FLAG_SO_PIN.
The for loop at line 767 will add a slot for each non SO_PIN or UNBLOCKING_PIN.
But at line 812, the auth_count is still set to the number of pins, even though
the SO_PIN did not cause a new slot to be allocated and thus the test of
hide_empty_tokens will not be used.
With the attached patch, I can get the expected behavior when hide_empty_tokens
= yes in the opensc.conf from pkcs11-tool -L, pkcs11-tool -O and pkcs11-tool -O
-l
There is only 1 slot allocated, the pkcs11-tool -O shows all the public
objects, and pkcs11-tool -O -l (after PIN) shows all the objects, and Heimdal
PKINIT still runs.
I still think that if two or more slots need to be allocated for multiple auth
pins, then all the public objects should be added to each. I have an additional
mod for this too.
Since the cards I am working with only have 1 pin, the attached mods works for
me. Note it looks like the pkcs15-openpgp.c might also be affected by this
change as it defines two pins an auth pin and a SO_PIN, much like the PIV card
does.
git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@3175 c6295689-39f2-0310-b995-f0e70906c6a9
2007-06-21 07:11:21 +00:00
|
|
|
(dobj->base.p15_object->flags & SC_PKCS15_CO_FLAG_PRIVATE) != 0;
|
2004-07-26 18:47:23 +00:00
|
|
|
break;
|
|
|
|
case CKA_MODIFIABLE:
|
|
|
|
check_attribute_buffer(attr, sizeof(CK_BBOOL));
|
2005-02-11 20:09:34 +00:00
|
|
|
*(CK_BBOOL*)attr->pValue =
|
2004-07-26 18:47:23 +00:00
|
|
|
(dobj->base.p15_object->flags & 0x02) != 0;
|
|
|
|
break;
|
|
|
|
case CKA_LABEL:
|
|
|
|
len = strlen(dobj->base.p15_object->label);
|
|
|
|
check_attribute_buffer(attr, len);
|
|
|
|
memcpy(attr->pValue, dobj->base.p15_object->label, len);
|
|
|
|
break;
|
|
|
|
case CKA_APPLICATION:
|
|
|
|
len = strlen(dobj->info->app_label);
|
|
|
|
check_attribute_buffer(attr, len);
|
|
|
|
memcpy(attr->pValue, dobj->info->app_label, len);
|
|
|
|
break;
|
|
|
|
#if 0
|
|
|
|
case CKA_ID:
|
|
|
|
check_attribute_buffer(attr, dobj->info->id.len);
|
|
|
|
memcpy(attr->pValue, dobj->info->id.value, dobj->info->id.len);
|
2005-02-11 20:09:34 +00:00
|
|
|
break;
|
2004-07-26 18:47:23 +00:00
|
|
|
#endif
|
|
|
|
case CKA_OBJECT_ID:
|
|
|
|
{
|
2004-12-22 10:17:00 +00:00
|
|
|
len = sizeof(dobj->info->app_oid);
|
2004-07-26 18:47:23 +00:00
|
|
|
|
|
|
|
check_attribute_buffer(attr, len);
|
|
|
|
memcpy(attr->pValue, dobj->info->app_oid.value, len);
|
|
|
|
}
|
2005-02-11 20:09:34 +00:00
|
|
|
break;
|
2004-07-26 18:47:23 +00:00
|
|
|
case CKA_VALUE:
|
|
|
|
{
|
|
|
|
CK_RV rv;
|
|
|
|
struct sc_pkcs15_data *data = NULL;
|
|
|
|
|
|
|
|
rv = pkcs15_dobj_get_value(session, dobj, &data);
|
2008-01-03 08:59:14 +00:00
|
|
|
if (rv == CKR_OK)
|
|
|
|
rv = data_value_to_attr(attr, data);
|
|
|
|
if (data) {
|
|
|
|
free(data->data);
|
|
|
|
free(data);
|
|
|
|
}
|
|
|
|
if (rv != CKR_OK)
|
2004-07-26 18:47:23 +00:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return CKR_ATTRIBUTE_TYPE_INVALID;
|
|
|
|
}
|
|
|
|
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct sc_pkcs11_object_ops pkcs15_dobj_ops = {
|
|
|
|
pkcs15_dobj_release,
|
|
|
|
pkcs15_dobj_set_attribute,
|
|
|
|
pkcs15_dobj_get_attribute,
|
|
|
|
sc_pkcs11_any_cmp_attribute,
|
2010-04-20 15:11:58 +00:00
|
|
|
pkcs15_any_destroy,
|
2004-07-26 18:47:23 +00:00
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2002-03-12 14:36:40 +00:00
|
|
|
/*
|
|
|
|
* get_attribute helpers
|
|
|
|
*/
|
2002-12-18 19:26:18 +00:00
|
|
|
static CK_RV
|
2002-04-17 18:34:32 +00:00
|
|
|
get_bignum(sc_pkcs15_bignum_t *bn, CK_ATTRIBUTE_PTR attr)
|
2002-03-12 14:36:40 +00:00
|
|
|
{
|
2002-04-17 18:34:32 +00:00
|
|
|
check_attribute_buffer(attr, bn->len);
|
|
|
|
memcpy(attr->pValue, bn->data, bn->len);
|
2002-03-12 14:36:40 +00:00
|
|
|
return CKR_OK;
|
|
|
|
}
|
|
|
|
|
2002-12-18 19:26:18 +00:00
|
|
|
static CK_RV
|
2002-04-17 18:34:32 +00:00
|
|
|
get_bignum_bits(sc_pkcs15_bignum_t *bn, CK_ATTRIBUTE_PTR attr)
|
2002-03-12 14:36:40 +00:00
|
|
|
{
|
|
|
|
CK_ULONG bits, mask;
|
|
|
|
|
2002-04-17 18:34:32 +00:00
|
|
|
bits = bn->len * 8;
|
2002-03-12 14:36:40 +00:00
|
|
|
for (mask = 0x80; mask; mask >>= 1, bits--) {
|
2002-04-17 18:34:32 +00:00
|
|
|
if (bn->data[0] & mask)
|
2002-03-12 14:36:40 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
check_attribute_buffer(attr, sizeof(bits));
|
|
|
|
*(CK_ULONG *) attr->pValue = bits;
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
|
|
|
|
2002-12-18 19:26:18 +00:00
|
|
|
static CK_RV
|
2002-04-17 18:34:32 +00:00
|
|
|
get_modulus(struct sc_pkcs15_pubkey *key, CK_ATTRIBUTE_PTR attr)
|
2002-03-12 14:36:40 +00:00
|
|
|
{
|
|
|
|
if (key == NULL)
|
|
|
|
return CKR_ATTRIBUTE_TYPE_INVALID;
|
2002-04-17 18:34:32 +00:00
|
|
|
switch (key->algorithm) {
|
|
|
|
case SC_ALGORITHM_RSA:
|
|
|
|
return get_bignum(&key->u.rsa.modulus, attr);
|
|
|
|
}
|
|
|
|
return CKR_ATTRIBUTE_TYPE_INVALID;
|
|
|
|
}
|
|
|
|
|
2002-12-18 19:26:18 +00:00
|
|
|
static CK_RV
|
2002-04-17 18:34:32 +00:00
|
|
|
get_modulus_bits(struct sc_pkcs15_pubkey *key, CK_ATTRIBUTE_PTR attr)
|
|
|
|
{
|
|
|
|
if (key == NULL)
|
|
|
|
return CKR_ATTRIBUTE_TYPE_INVALID;
|
|
|
|
switch (key->algorithm) {
|
|
|
|
case SC_ALGORITHM_RSA:
|
|
|
|
return get_bignum_bits(&key->u.rsa.modulus, attr);
|
|
|
|
}
|
|
|
|
return CKR_ATTRIBUTE_TYPE_INVALID;
|
|
|
|
}
|
|
|
|
|
2002-12-18 19:26:18 +00:00
|
|
|
static CK_RV
|
2002-04-17 18:34:32 +00:00
|
|
|
get_public_exponent(struct sc_pkcs15_pubkey *key, CK_ATTRIBUTE_PTR attr)
|
|
|
|
{
|
|
|
|
if (key == NULL)
|
|
|
|
return CKR_ATTRIBUTE_TYPE_INVALID;
|
|
|
|
switch (key->algorithm) {
|
|
|
|
case SC_ALGORITHM_RSA:
|
|
|
|
return get_bignum(&key->u.rsa.exponent, attr);
|
|
|
|
}
|
|
|
|
return CKR_ATTRIBUTE_TYPE_INVALID;
|
2002-03-12 14:36:40 +00:00
|
|
|
}
|
2002-03-20 19:31:56 +00:00
|
|
|
|
2010-12-01 20:08:42 +00:00
|
|
|
static CK_RV
|
|
|
|
get_ec_pubkey_params(struct sc_pkcs15_pubkey *key, CK_ATTRIBUTE_PTR attr)
|
|
|
|
{
|
2011-04-15 16:35:29 +00:00
|
|
|
struct sc_ec_params * ecp;
|
|
|
|
|
|
|
|
if (key == NULL)
|
|
|
|
return CKR_ATTRIBUTE_TYPE_INVALID;
|
|
|
|
if (key->alg_id == NULL)
|
2010-12-01 20:08:42 +00:00
|
|
|
return CKR_ATTRIBUTE_TYPE_INVALID;
|
2011-04-15 16:35:29 +00:00
|
|
|
ecp = (struct sc_ec_params *) key->alg_id->params;
|
|
|
|
|
|
|
|
switch (key->algorithm) {
|
|
|
|
case SC_ALGORITHM_EC:
|
|
|
|
check_attribute_buffer(attr, ecp->der_len);
|
|
|
|
memcpy(attr->pValue, ecp->der, ecp->der_len);
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
|
|
|
return CKR_ATTRIBUTE_TYPE_INVALID;
|
2010-12-01 20:08:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static CK_RV
|
|
|
|
get_ec_pubkey_point(struct sc_pkcs15_pubkey *key, CK_ATTRIBUTE_PTR attr)
|
|
|
|
{
|
2011-04-15 16:35:29 +00:00
|
|
|
if (key == NULL)
|
2010-12-01 20:08:42 +00:00
|
|
|
return CKR_ATTRIBUTE_TYPE_INVALID;
|
2011-04-15 16:35:29 +00:00
|
|
|
|
|
|
|
switch (key->algorithm) {
|
|
|
|
case SC_ALGORITHM_EC:
|
|
|
|
check_attribute_buffer(attr, key->u.ec.ecpointQ.len);
|
|
|
|
memcpy(attr->pValue, key->u.ec.ecpointQ.value, key->u.ec.ecpointQ.len);
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
|
|
|
return CKR_ATTRIBUTE_TYPE_INVALID;
|
2010-12-01 20:08:42 +00:00
|
|
|
}
|
|
|
|
|
2009-10-05 20:10:07 +00:00
|
|
|
static CK_RV
|
|
|
|
get_gostr3410_params(const u8 *params, size_t params_len, CK_ATTRIBUTE_PTR attr)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (!params || params_len == sizeof(int))
|
|
|
|
return CKR_ATTRIBUTE_TYPE_INVALID;
|
|
|
|
|
|
|
|
for (i = 0; i < sizeof(gostr3410_param_oid)/
|
|
|
|
sizeof(gostr3410_param_oid[0]); ++i) {
|
|
|
|
if (gostr3410_param_oid[i].param == ((int*)params)[0]) {
|
|
|
|
check_attribute_buffer(attr, sizeof(gostr3410_param_oid[i].oid));
|
|
|
|
memcpy(attr->pValue, gostr3410_param_oid[i].oid,
|
|
|
|
sizeof(gostr3410_param_oid[i].oid));
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return CKR_ATTRIBUTE_TYPE_INVALID;
|
|
|
|
}
|
|
|
|
|
2002-12-18 19:26:18 +00:00
|
|
|
/*
|
|
|
|
* Map pkcs15 usage bits to pkcs11 usage attributes.
|
|
|
|
*
|
|
|
|
* It's not totally clear to me whether SC_PKCS15_PRKEY_USAGE_NONREPUDIATION should
|
|
|
|
* be treated as being equivalent with CKA_SIGN or not...
|
|
|
|
*/
|
|
|
|
static CK_RV
|
|
|
|
get_usage_bit(unsigned int usage, CK_ATTRIBUTE_PTR attr)
|
|
|
|
{
|
|
|
|
static struct {
|
|
|
|
CK_ATTRIBUTE_TYPE type;
|
|
|
|
unsigned int flag;
|
|
|
|
} flag_mapping[] = {
|
2005-01-19 18:15:43 +00:00
|
|
|
{ CKA_ENCRYPT, SC_PKCS15_PRKEY_USAGE_ENCRYPT },
|
|
|
|
{ CKA_DECRYPT, SC_PKCS15_PRKEY_USAGE_DECRYPT },
|
2002-12-18 19:26:18 +00:00
|
|
|
{ CKA_SIGN, SC_PKCS15_PRKEY_USAGE_SIGN|SC_PKCS15_PRKEY_USAGE_NONREPUDIATION },
|
|
|
|
{ CKA_SIGN_RECOVER, SC_PKCS15_PRKEY_USAGE_SIGNRECOVER },
|
|
|
|
{ CKA_WRAP, SC_PKCS15_PRKEY_USAGE_WRAP },
|
|
|
|
{ CKA_UNWRAP, SC_PKCS15_PRKEY_USAGE_UNWRAP },
|
|
|
|
{ CKA_VERIFY, SC_PKCS15_PRKEY_USAGE_VERIFY },
|
|
|
|
{ CKA_VERIFY_RECOVER, SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER },
|
|
|
|
{ CKA_DERIVE, SC_PKCS15_PRKEY_USAGE_DERIVE },
|
|
|
|
{ 0, 0 }
|
|
|
|
};
|
|
|
|
unsigned int mask = 0, j;
|
|
|
|
|
|
|
|
for (j = 0; (mask = flag_mapping[j].flag) != 0; j++) {
|
|
|
|
if (flag_mapping[j].type == attr->type)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (mask == 0)
|
|
|
|
return CKR_ATTRIBUTE_TYPE_INVALID;
|
|
|
|
|
|
|
|
check_attribute_buffer(attr, sizeof(CK_BBOOL));
|
|
|
|
*(CK_BBOOL*)attr->pValue = (usage & mask)? TRUE : FALSE;
|
|
|
|
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static CK_RV
|
2002-03-20 19:31:56 +00:00
|
|
|
asn1_sequence_wrapper(const u8 *data, size_t len, CK_ATTRIBUTE_PTR attr)
|
|
|
|
{
|
|
|
|
u8 *dest;
|
|
|
|
unsigned int n;
|
2002-05-26 12:31:23 +00:00
|
|
|
size_t len2;
|
2006-05-12 20:01:26 +00:00
|
|
|
size_t lenb = 1;
|
2002-03-20 19:31:56 +00:00
|
|
|
|
2002-05-26 12:31:23 +00:00
|
|
|
len2 = len;
|
2006-05-09 21:35:07 +00:00
|
|
|
/* calculate the number of bytes needed for the length */
|
|
|
|
if (len > 127) {
|
|
|
|
unsigned int i;
|
|
|
|
for (i = 0; (len & (0xff << i)) != 0 && (0xff << i) != 0; i++)
|
|
|
|
lenb++;
|
|
|
|
}
|
|
|
|
check_attribute_buffer(attr, 1 + lenb + len);
|
2002-03-20 19:31:56 +00:00
|
|
|
|
2002-04-19 14:23:31 +00:00
|
|
|
dest = (u8 *) attr->pValue;
|
2002-03-20 19:31:56 +00:00
|
|
|
*dest++ = 0x30; /* SEQUENCE tag */
|
|
|
|
if (len <= 127) {
|
|
|
|
*dest++ = len;
|
|
|
|
} else {
|
|
|
|
for (n = 4; (len & 0xFF000000) == 0; n--)
|
|
|
|
len <<= 8;
|
|
|
|
*dest++ = 0x80 + n;
|
|
|
|
while (n--) {
|
|
|
|
*dest++ = len >> 24;
|
|
|
|
len <<= 8;
|
|
|
|
}
|
|
|
|
}
|
2002-05-26 12:31:23 +00:00
|
|
|
memcpy(dest, data, len2);
|
|
|
|
attr->ulValueLen = (dest - (u8 *) attr->pValue) + len2;
|
2002-03-20 19:31:56 +00:00
|
|
|
return CKR_OK;
|
|
|
|
}
|
2002-04-11 15:17:33 +00:00
|
|
|
|
2009-10-05 20:10:07 +00:00
|
|
|
static int register_gost_mechanisms(struct sc_pkcs11_card *p11card, int flags)
|
|
|
|
{
|
|
|
|
CK_MECHANISM_INFO mech_info;
|
|
|
|
sc_pkcs11_mechanism_type_t *mt;
|
|
|
|
int rc;
|
|
|
|
|
2010-11-29 00:58:12 +00:00
|
|
|
mech_info.flags = CKF_HW | CKF_SIGN | CKF_DECRYPT;
|
2009-10-05 20:10:07 +00:00
|
|
|
#ifdef ENABLE_OPENSSL
|
2010-11-29 00:58:12 +00:00
|
|
|
/* That practise definitely conflicts with CKF_HW -- andre 2010-11-28 */
|
2009-10-05 20:10:07 +00:00
|
|
|
mech_info.flags |= CKF_VERIFY;
|
|
|
|
#endif
|
|
|
|
mech_info.ulMinKeySize = SC_PKCS15_GOSTR3410_KEYSIZE;
|
|
|
|
mech_info.ulMaxKeySize = SC_PKCS15_GOSTR3410_KEYSIZE;
|
|
|
|
|
|
|
|
if (flags & SC_ALGORITHM_GOSTR3410_HASH_NONE) {
|
|
|
|
mt = sc_pkcs11_new_fw_mechanism(CKM_GOSTR3410,
|
|
|
|
&mech_info, CKK_GOSTR3410, NULL);
|
|
|
|
if (!mt)
|
|
|
|
return CKR_HOST_MEMORY;
|
|
|
|
rc = sc_pkcs11_register_mechanism(p11card, mt);
|
|
|
|
if (rc != CKR_OK)
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
if (flags & SC_ALGORITHM_GOSTR3410_HASH_GOSTR3411) {
|
|
|
|
mt = sc_pkcs11_new_fw_mechanism(CKM_GOSTR3410_WITH_GOSTR3411,
|
|
|
|
&mech_info, CKK_GOSTR3410, NULL);
|
|
|
|
if (!mt)
|
|
|
|
return CKR_HOST_MEMORY;
|
|
|
|
rc = sc_pkcs11_register_mechanism(p11card, mt);
|
|
|
|
if (rc != CKR_OK)
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
|
|
|
|
2011-04-21 16:29:13 +00:00
|
|
|
|
|
|
|
static int register_ec_mechanisms(struct sc_pkcs11_card *p11card, int flags,
|
|
|
|
unsigned long ext_flags, CK_ULONG min_key_size, CK_ULONG max_key_size)
|
2010-12-01 20:08:42 +00:00
|
|
|
{
|
|
|
|
CK_MECHANISM_INFO mech_info;
|
|
|
|
sc_pkcs11_mechanism_type_t *mt;
|
2011-04-21 16:29:13 +00:00
|
|
|
CK_FLAGS ec_flags = 0;
|
2010-12-01 20:08:42 +00:00
|
|
|
int rc;
|
|
|
|
|
|
|
|
if (ext_flags & SC_ALGORITHM_EXT_EC_F_P)
|
2011-04-21 16:29:13 +00:00
|
|
|
ec_flags |= CKF_EC_F_P;
|
2010-12-01 20:08:42 +00:00
|
|
|
if (ext_flags & SC_ALGORITHM_EXT_EC_F_2M)
|
2011-04-21 16:29:13 +00:00
|
|
|
ec_flags |= CKF_EC_F_2M;
|
2010-12-01 20:08:42 +00:00
|
|
|
if (ext_flags & SC_ALGORITHM_EXT_EC_ECPARAMETERS)
|
2011-04-21 16:29:13 +00:00
|
|
|
ec_flags |= CKF_EC_ECPARAMETERS;
|
2010-12-01 20:08:42 +00:00
|
|
|
if (ext_flags & SC_ALGORITHM_EXT_EC_NAMEDCURVE)
|
2011-04-21 16:29:13 +00:00
|
|
|
ec_flags |= CKF_EC_NAMEDCURVE;
|
2010-12-01 20:08:42 +00:00
|
|
|
if (ext_flags & SC_ALGORITHM_EXT_EC_UNCOMPRESES)
|
2011-04-21 16:29:13 +00:00
|
|
|
ec_flags |= CKF_EC_UNCOMPRESES;
|
2010-12-01 20:08:42 +00:00
|
|
|
if (ext_flags & SC_ALGORITHM_EXT_EC_COMPRESS)
|
2011-04-21 16:29:13 +00:00
|
|
|
ec_flags |= CKF_EC_COMPRESS;
|
|
|
|
|
|
|
|
mech_info.flags = CKF_HW | CKF_SIGN; /* check for more */
|
|
|
|
mech_info.flags |= ec_flags;
|
2010-12-01 20:08:42 +00:00
|
|
|
mech_info.ulMinKeySize = min_key_size;
|
|
|
|
mech_info.ulMaxKeySize = max_key_size;
|
2011-04-21 16:29:13 +00:00
|
|
|
|
|
|
|
mt = sc_pkcs11_new_fw_mechanism(CKM_ECDSA, &mech_info, CKK_EC, NULL);
|
2010-12-01 20:08:42 +00:00
|
|
|
if (!mt)
|
|
|
|
return CKR_HOST_MEMORY;
|
|
|
|
rc = sc_pkcs11_register_mechanism(p11card, mt);
|
|
|
|
if (rc != CKR_OK)
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
#if ENABLE_OPENSSL
|
|
|
|
mt = sc_pkcs11_new_fw_mechanism(CKM_ECDSA_SHA1,
|
|
|
|
&mech_info, CKK_EC, NULL);
|
|
|
|
if (!mt)
|
|
|
|
return CKR_HOST_MEMORY;
|
|
|
|
rc = sc_pkcs11_register_mechanism(p11card, mt);
|
|
|
|
if (rc != CKR_OK)
|
|
|
|
return rc;
|
|
|
|
#endif
|
2011-04-21 16:29:13 +00:00
|
|
|
if (flags & SC_ALGORITHM_ONBOARD_KEY_GEN) {
|
|
|
|
mech_info.flags = CKF_HW | CKF_GENERATE_KEY_PAIR;
|
|
|
|
mech_info.flags |= ec_flags;
|
|
|
|
mt = sc_pkcs11_new_fw_mechanism(CKM_EC_KEY_PAIR_GEN, &mech_info, CKK_EC, NULL);
|
|
|
|
if (!mt)
|
|
|
|
return CKR_HOST_MEMORY;
|
|
|
|
rc = sc_pkcs11_register_mechanism(p11card, mt);
|
|
|
|
if (rc != CKR_OK)
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2010-12-01 20:08:42 +00:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
/* TODO: -DEE Add CKM_ECDH1_COFACTOR_DERIVE as PIV can do this */
|
|
|
|
/* TODO: -DEE But this requires C_DeriveKey to be implemented */
|
|
|
|
|
|
|
|
mech_info.flags &= ~CKF_SIGN;
|
|
|
|
mech_info.flags |= CKF_DRIVE;
|
|
|
|
|
|
|
|
sc_pkcs11_new_fw_mechanism(CKM_ECDH1_COFACTOR_DERIVE,
|
|
|
|
CKM_ECDH1_COFACTOR_DERIVE, NULL);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return CKR_OK;
|
|
|
|
}
|
|
|
|
|
2011-04-21 16:29:13 +00:00
|
|
|
|
2002-12-17 11:49:12 +00:00
|
|
|
/*
|
|
|
|
* Mechanism handling
|
|
|
|
* FIXME: We should consult the card's algorithm list to
|
|
|
|
* find out what operations it supports
|
|
|
|
*/
|
2010-12-17 17:12:22 +00:00
|
|
|
static CK_RV register_mechanisms(struct sc_pkcs11_card *p11card)
|
2002-12-04 13:50:23 +00:00
|
|
|
{
|
2002-12-17 20:16:31 +00:00
|
|
|
sc_card_t *card = p11card->card;
|
|
|
|
sc_algorithm_info_t *alg_info;
|
2002-12-17 11:49:12 +00:00
|
|
|
CK_MECHANISM_INFO mech_info;
|
2011-01-03 15:10:18 +00:00
|
|
|
CK_ULONG ec_min_key_size, ec_max_key_size;
|
2010-12-01 20:08:42 +00:00
|
|
|
unsigned long ec_ext_flags;
|
2002-12-17 20:16:31 +00:00
|
|
|
sc_pkcs11_mechanism_type_t *mt;
|
|
|
|
unsigned int num;
|
|
|
|
int rc, flags = 0;
|
|
|
|
|
|
|
|
/* Register generic mechanisms */
|
|
|
|
sc_pkcs11_register_generic_mechanisms(p11card);
|
2002-12-04 13:50:23 +00:00
|
|
|
|
2010-11-29 00:58:12 +00:00
|
|
|
mech_info.flags = CKF_HW | CKF_SIGN | CKF_DECRYPT;
|
2008-03-06 16:06:59 +00:00
|
|
|
#ifdef ENABLE_OPENSSL
|
2010-11-29 00:58:12 +00:00
|
|
|
/* That practise definitely conflicts with CKF_HW -- andre 2010-11-28 */
|
2003-06-27 15:26:17 +00:00
|
|
|
mech_info.flags |= CKF_VERIFY;
|
|
|
|
#endif
|
2002-12-17 20:16:31 +00:00
|
|
|
mech_info.ulMinKeySize = ~0;
|
|
|
|
mech_info.ulMaxKeySize = 0;
|
2010-12-01 20:08:42 +00:00
|
|
|
ec_min_key_size = ~0;
|
|
|
|
ec_max_key_size = 0;
|
|
|
|
ec_ext_flags = 0;
|
2002-12-17 20:16:31 +00:00
|
|
|
|
|
|
|
/* For now, we just OR all the algorithm specific
|
|
|
|
* flags, based on the assumption that cards don't
|
|
|
|
* support different modes for different key sizes
|
2010-12-01 20:08:42 +00:00
|
|
|
* But we need to do this by type of key as
|
|
|
|
* each has different min/max and different flags.
|
|
|
|
*
|
|
|
|
* TODO: -DEE This code assumed RSA, but the GOST
|
|
|
|
* and EC code was forced in. There should be a
|
|
|
|
* routine for each key type.
|
2002-12-17 20:16:31 +00:00
|
|
|
*/
|
|
|
|
num = card->algorithm_count;
|
|
|
|
alg_info = card->algorithms;
|
|
|
|
while (num--) {
|
2010-12-01 20:08:42 +00:00
|
|
|
switch (alg_info->algorithm) {
|
|
|
|
case SC_ALGORITHM_RSA:
|
|
|
|
if (alg_info->key_length < mech_info.ulMinKeySize)
|
|
|
|
mech_info.ulMinKeySize = alg_info->key_length;
|
|
|
|
if (alg_info->key_length > mech_info.ulMaxKeySize)
|
|
|
|
mech_info.ulMaxKeySize = alg_info->key_length;
|
|
|
|
flags |= alg_info->flags;
|
|
|
|
break;
|
|
|
|
case SC_ALGORITHM_EC:
|
|
|
|
if (alg_info->key_length < ec_min_key_size)
|
|
|
|
ec_min_key_size = alg_info->key_length;
|
|
|
|
if (alg_info->key_length > ec_max_key_size)
|
|
|
|
ec_max_key_size = alg_info->key_length;
|
|
|
|
flags |= alg_info->flags;
|
|
|
|
ec_ext_flags |= alg_info->u._ec.ext_flags;
|
|
|
|
break;
|
|
|
|
case SC_ALGORITHM_GOSTR3410:
|
|
|
|
flags |= alg_info->flags;
|
|
|
|
break;
|
2004-07-26 18:47:23 +00:00
|
|
|
}
|
2002-12-17 20:16:31 +00:00
|
|
|
alg_info++;
|
|
|
|
}
|
|
|
|
|
2011-04-21 16:29:13 +00:00
|
|
|
if (flags & SC_ALGORITHM_ECDSA_RAW)
|
|
|
|
rc = register_ec_mechanisms(p11card, flags, ec_ext_flags, ec_min_key_size, ec_max_key_size);
|
2010-12-01 20:08:42 +00:00
|
|
|
|
2009-10-05 20:10:07 +00:00
|
|
|
if (flags & (SC_ALGORITHM_GOSTR3410_RAW
|
|
|
|
| SC_ALGORITHM_GOSTR3410_HASH_NONE
|
|
|
|
| SC_ALGORITHM_GOSTR3410_HASH_GOSTR3411)) {
|
|
|
|
if (flags & SC_ALGORITHM_GOSTR3410_RAW)
|
|
|
|
flags |= SC_ALGORITHM_GOSTR3410_HASH_NONE;
|
|
|
|
rc = register_gost_mechanisms(p11card, flags);
|
|
|
|
if (rc != CKR_OK)
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2002-12-17 20:16:31 +00:00
|
|
|
/* Check if we support raw RSA */
|
|
|
|
if (flags & SC_ALGORITHM_RSA_RAW) {
|
2010-11-29 14:22:09 +00:00
|
|
|
mt = sc_pkcs11_new_fw_mechanism(CKM_RSA_X_509, &mech_info, CKK_RSA, NULL);
|
2002-12-17 20:16:31 +00:00
|
|
|
rc = sc_pkcs11_register_mechanism(p11card, mt);
|
|
|
|
if (rc != CKR_OK)
|
|
|
|
return rc;
|
2002-12-19 09:27:08 +00:00
|
|
|
|
2005-06-27 13:52:08 +00:00
|
|
|
/* If the card supports RAW, it should by all means
|
2002-12-19 09:27:08 +00:00
|
|
|
* have registered everything else, too. If it didn't
|
|
|
|
* we help it a little
|
2010-12-17 17:12:22 +00:00
|
|
|
* FIXME? This may force us to support these in software
|
2002-12-19 09:27:08 +00:00
|
|
|
*/
|
2010-12-17 17:12:22 +00:00
|
|
|
flags |= SC_ALGORITHM_RSA_PAD_PKCS1;
|
|
|
|
#ifdef ENABLE_OPENSSL
|
|
|
|
/* all our software hashes are in OpenSSL */
|
|
|
|
flags |= SC_ALGORITHM_RSA_HASHES;
|
|
|
|
#endif
|
2002-12-17 20:16:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Check for PKCS1 */
|
|
|
|
if (flags & SC_ALGORITHM_RSA_PAD_PKCS1) {
|
2010-11-29 14:22:09 +00:00
|
|
|
mt = sc_pkcs11_new_fw_mechanism(CKM_RSA_PKCS, &mech_info, CKK_RSA, NULL);
|
2002-12-17 20:16:31 +00:00
|
|
|
rc = sc_pkcs11_register_mechanism(p11card, mt);
|
|
|
|
if (rc != CKR_OK)
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
/* if the driver doesn't say what hashes it supports,
|
|
|
|
* claim we will do all of them */
|
2010-12-17 17:12:22 +00:00
|
|
|
/* FIXME? This may force us to support these in software */
|
|
|
|
/* FIXME? and we only do hashes if OpenSSL is enabled */
|
|
|
|
if (!(flags & (SC_ALGORITHM_RSA_HASHES|SC_ALGORITHM_RSA_HASH_NONE)))
|
2002-12-17 20:16:31 +00:00
|
|
|
flags |= SC_ALGORITHM_RSA_HASHES;
|
|
|
|
|
2010-12-17 17:12:22 +00:00
|
|
|
#ifdef ENABLE_OPENSSL
|
|
|
|
/* sc_pkcs11_register_sign_and_hash_mechanism expects software hash */
|
2010-11-29 14:22:09 +00:00
|
|
|
if (flags & SC_ALGORITHM_RSA_HASH_SHA1) {
|
|
|
|
rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card, CKM_SHA1_RSA_PKCS, CKM_SHA_1, mt);
|
|
|
|
if (rc != CKR_OK)
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
if (flags & SC_ALGORITHM_RSA_HASH_SHA256) {
|
|
|
|
rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card, CKM_SHA256_RSA_PKCS, CKM_SHA256, mt);
|
|
|
|
if (rc != CKR_OK)
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
if (flags & SC_ALGORITHM_RSA_HASH_MD5) {
|
|
|
|
rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card, CKM_MD5_RSA_PKCS, CKM_MD5, mt);
|
|
|
|
if (rc != CKR_OK)
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
if (flags & SC_ALGORITHM_RSA_HASH_RIPEMD160) {
|
|
|
|
rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card, CKM_RIPEMD160_RSA_PKCS, CKM_RIPEMD160, mt);
|
|
|
|
if (rc != CKR_OK)
|
|
|
|
return rc;
|
|
|
|
}
|
2010-12-17 17:12:22 +00:00
|
|
|
#endif
|
2010-11-29 14:22:09 +00:00
|
|
|
|
|
|
|
if (flags & SC_ALGORITHM_ONBOARD_KEY_GEN) {
|
|
|
|
mech_info.flags = CKF_GENERATE_KEY_PAIR;
|
|
|
|
mt = sc_pkcs11_new_fw_mechanism(CKM_RSA_PKCS_KEY_PAIR_GEN, &mech_info, CKK_RSA, NULL);
|
|
|
|
if (!mt)
|
|
|
|
return CKR_HOST_MEMORY;
|
|
|
|
rc = sc_pkcs11_register_mechanism(p11card, mt);
|
|
|
|
if (rc != CKR_OK)
|
|
|
|
return rc;
|
|
|
|
}
|
2002-12-17 20:16:31 +00:00
|
|
|
}
|
2009-10-22 08:59:59 +00:00
|
|
|
|
2002-12-17 20:16:31 +00:00
|
|
|
return CKR_OK;
|
2002-12-04 13:50:23 +00:00
|
|
|
}
|
2003-06-24 11:26:17 +00:00
|
|
|
|
2007-06-21 12:01:39 +00:00
|
|
|
static int lock_card(struct pkcs15_fw_data *fw_data)
|
2003-06-24 11:26:17 +00:00
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
if ((rc = sc_lock(fw_data->p15_card->card)) < 0)
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(context, SC_LOG_DEBUG_NORMAL, "Failed to lock card (%d)\n", rc);
|
2003-06-24 11:26:17 +00:00
|
|
|
else
|
|
|
|
fw_data->locked++;
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2007-06-21 12:01:39 +00:00
|
|
|
static int unlock_card(struct pkcs15_fw_data *fw_data)
|
2003-06-24 11:26:17 +00:00
|
|
|
{
|
|
|
|
while (fw_data->locked) {
|
|
|
|
sc_unlock(fw_data->p15_card->card);
|
|
|
|
fw_data->locked--;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2004-01-08 08:32:46 +00:00
|
|
|
|
2005-02-01 19:02:15 +00:00
|
|
|
|
|
|
|
static int reselect_app_df(sc_pkcs15_card_t *p15card)
|
|
|
|
{
|
|
|
|
int r = SC_SUCCESS;
|
|
|
|
|
|
|
|
if (p15card->file_app != NULL) {
|
|
|
|
/* if the application df (of the pkcs15 application) is
|
|
|
|
* specified select it */
|
|
|
|
sc_path_t *tpath = &p15card->file_app->path;
|
2010-03-15 12:17:13 +00:00
|
|
|
sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "reselect application df\n");
|
2005-02-01 19:02:15 +00:00
|
|
|
r = sc_select_file(p15card->card, tpath, NULL);
|
|
|
|
}
|
|
|
|
return r;
|
|
|
|
}
|