opensc/src/pkcs11/secretkey.c
aj d22a2483c0 Header file cleanup.
git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@4081 c6295689-39f2-0310-b995-f0e70906c6a9
2010-03-04 08:14:36 +00:00

234 lines
5.8 KiB
C

/*
* Secret key handling for PKCS#11
*
* This module deals only with secret keys that have been unwrapped
* by the card. At the moment, we do not support key unwrapping
* where the key remains on the token.
*
* Copyright (C) 2002 Olaf Kirch <okir@lst.de>
* 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
*/
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include "sc-pkcs11.h"
struct pkcs11_secret_key {
struct sc_pkcs11_object object;
char * label;
CK_KEY_TYPE type;
CK_BYTE_PTR value;
CK_ULONG value_len;
};
extern struct sc_pkcs11_object_ops pkcs11_secret_key_ops;
#define set_attr(var, attr) \
if (attr->ulValueLen != sizeof(var)) \
return CKR_ATTRIBUTE_VALUE_INVALID; \
memcpy(&var, attr->pValue, attr->ulValueLen);
#define check_attr(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; \
} \
attr->ulValueLen = size;
#define get_attr(attr, type, value) \
check_attr(attr, sizeof(type)); \
*(type *) (attr->pValue) = value;
CK_RV
sc_pkcs11_create_secret_key(struct sc_pkcs11_session *session,
const u8 *value, size_t value_len,
CK_ATTRIBUTE_PTR _template,
CK_ULONG attribute_count,
struct sc_pkcs11_object **out)
{
struct pkcs11_secret_key *key;
CK_ATTRIBUTE_PTR attr;
int n, rv;
key = (struct pkcs11_secret_key *) calloc(1, sizeof(*key));
if (!key)
return CKR_HOST_MEMORY;
key->value = (CK_BYTE *) malloc(value_len);
if (!key->value) {
pkcs11_secret_key_ops.release(key);
return CKR_HOST_MEMORY; /* XXX correct? */
}
memcpy(key->value, value, value_len);
key->value_len = value_len;
key->object.ops = &pkcs11_secret_key_ops;
/* Make sure the key type is given in the template */
for (n = attribute_count, attr = _template; n--; attr++) {
if (attr->type == CKA_KEY_TYPE) {
set_attr(key->type, attr);
break;
}
}
if (n < 0) {
pkcs11_secret_key_ops.release(key);
return CKR_TEMPLATE_INCOMPLETE;
}
/* Set all the other attributes */
for (n = attribute_count, attr = _template; n--; attr++) {
rv = key->object.ops->set_attribute(session, key, attr);
if (rv != CKR_OK) {
pkcs11_secret_key_ops.release(key);
return rv;
}
}
*out = (struct sc_pkcs11_object *) key;
return CKR_OK;
}
static void
sc_pkcs11_secret_key_release(void *object)
{
struct pkcs11_secret_key *key;
key = (struct pkcs11_secret_key *) object;
if (key) {
if (key->value)
free(key->value);
if (key->label)
free(key->label);
free(key);
}
}
static CK_RV
sc_pkcs11_secret_key_set_attribute(struct sc_pkcs11_session *session,
void *object, CK_ATTRIBUTE_PTR attr)
{
struct pkcs11_secret_key *key;
CK_OBJECT_CLASS ck_class;
CK_KEY_TYPE ck_key_type;
CK_BBOOL ck_bbool;
key = (struct pkcs11_secret_key *) object;
switch (attr->type) {
case CKA_CLASS:
set_attr(ck_class, attr);
if (ck_class != CKO_SECRET_KEY)
return CKR_ATTRIBUTE_VALUE_INVALID;
break;
case CKA_KEY_TYPE:
set_attr(ck_key_type, attr);
if (ck_key_type != key->type)
return CKR_ATTRIBUTE_VALUE_INVALID;
break;
case CKA_LABEL:
if (key->label)
free(key->label);
key->label = strdup((const char *) attr->pValue);
break;
case CKA_TOKEN:
set_attr(ck_bbool, attr);
if (!ck_bbool)
return CKR_ATTRIBUTE_VALUE_INVALID;
break;
case CKA_VALUE:
if (key->value)
free(key->value);
key->value = (CK_BYTE *) malloc(attr->ulValueLen);
if (key->value == NULL)
return CKR_HOST_MEMORY;
key->value_len = attr->ulValueLen;
memcpy(key->value, attr->pValue, key->value_len);
break;
case CKA_ENCRYPT:
case CKA_DECRYPT:
case CKA_SIGN:
case CKA_VERIFY:
case CKA_WRAP:
case CKA_UNWRAP:
case CKA_EXTRACTABLE:
case CKA_ALWAYS_SENSITIVE:
case CKA_NEVER_EXTRACTABLE:
/* We ignore these for now, just making sure the argument
* has the right size */
set_attr(ck_bbool, attr);
break;
default:
return CKR_ATTRIBUTE_TYPE_INVALID;
}
return CKR_OK;
}
static CK_RV
sc_pkcs11_secret_key_get_attribute(struct sc_pkcs11_session *session,
void *object, CK_ATTRIBUTE_PTR attr)
{
struct pkcs11_secret_key *key;
key = (struct pkcs11_secret_key *) object;
switch (attr->type) {
case CKA_CLASS:
get_attr(attr, CK_OBJECT_CLASS, CKO_SECRET_KEY);
break;
case CKA_KEY_TYPE:
get_attr(attr, CK_KEY_TYPE, key->type);
case CKA_VALUE:
check_attr(attr, key->value_len);
memcpy(attr->pValue, key->value, key->value_len);
break;
case CKA_VALUE_LEN:
get_attr(attr, CK_ULONG, key->value_len);
break;
case CKA_SENSITIVE:
case CKA_SIGN:
case CKA_VERIFY:
case CKA_WRAP:
case CKA_UNWRAP:
case CKA_NEVER_EXTRACTABLE:
get_attr(attr, CK_BBOOL, 0);
break;
case CKA_ENCRYPT:
case CKA_DECRYPT:
case CKA_EXTRACTABLE:
case CKA_ALWAYS_SENSITIVE:
get_attr(attr, CK_BBOOL, 1);
break;
default:
return CKR_ATTRIBUTE_TYPE_INVALID;
}
return CKR_OK;
}
struct sc_pkcs11_object_ops pkcs11_secret_key_ops = {
sc_pkcs11_secret_key_release,
sc_pkcs11_secret_key_set_attribute,
sc_pkcs11_secret_key_get_attribute,
sc_pkcs11_any_cmp_attribute,
NULL, /* destroy_object */
NULL, /* get_size */
NULL, /* sign */
NULL, /* unwrap_key */
NULL /* decrypt */
};