opensc/src/pkcs11/mechanism.c

1247 lines
32 KiB
C
Raw Normal View History

/*
* Generic handling of PKCS11 mechanisms
*
* Copyright (C) 2002 Olaf Kirch <okir@suse.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"
/* Also used for verification data */
struct hash_signature_info {
CK_MECHANISM_TYPE mech;
CK_MECHANISM_TYPE hash_mech;
CK_MECHANISM_TYPE sign_mech;
sc_pkcs11_mechanism_type_t *hash_type;
sc_pkcs11_mechanism_type_t *sign_type;
};
/* Also used for verification and decryption data */
struct signature_data {
struct sc_pkcs11_object *key;
struct hash_signature_info *info;
sc_pkcs11_operation_t * md;
CK_BYTE buffer[4096/8];
2018-10-31 12:10:12 +00:00
unsigned int buffer_len;
};
/*
* Register a mechanism
*/
CK_RV
sc_pkcs11_register_mechanism(struct sc_pkcs11_card *p11card,
sc_pkcs11_mechanism_type_t *mt)
{
sc_pkcs11_mechanism_type_t **p;
if (mt == NULL)
return CKR_HOST_MEMORY;
p = (sc_pkcs11_mechanism_type_t **) realloc(p11card->mechanisms,
(p11card->nmechanisms + 2) * sizeof(*p));
if (p == NULL)
return CKR_HOST_MEMORY;
p11card->mechanisms = p;
p[p11card->nmechanisms++] = mt;
p[p11card->nmechanisms] = NULL;
return CKR_OK;
}
/*
* Look up a mechanism
*/
sc_pkcs11_mechanism_type_t *
sc_pkcs11_find_mechanism(struct sc_pkcs11_card *p11card, CK_MECHANISM_TYPE mech, unsigned int flags)
{
sc_pkcs11_mechanism_type_t *mt;
unsigned int n;
for (n = 0; n < p11card->nmechanisms; n++) {
mt = p11card->mechanisms[n];
if (mt && mt->mech == mech && ((mt->mech_info.flags & flags) == flags))
return mt;
}
return NULL;
}
/*
* Query mechanisms.
* All of this is greatly simplified by having the framework
* register all supported mechanisms at initialization
* time.
*/
CK_RV
sc_pkcs11_get_mechanism_list(struct sc_pkcs11_card *p11card,
CK_MECHANISM_TYPE_PTR pList,
CK_ULONG_PTR pulCount)
{
sc_pkcs11_mechanism_type_t *mt;
unsigned int n, count = 0;
2018-10-31 12:10:12 +00:00
CK_RV rv;
if (!p11card)
return CKR_TOKEN_NOT_PRESENT;
for (n = 0; n < p11card->nmechanisms; n++) {
if (!(mt = p11card->mechanisms[n]))
continue;
if (pList && count < *pulCount)
pList[count] = mt->mech;
count++;
}
rv = CKR_OK;
if (pList && count > *pulCount)
rv = CKR_BUFFER_TOO_SMALL;
*pulCount = count;
return rv;
}
CK_RV
sc_pkcs11_get_mechanism_info(struct sc_pkcs11_card *p11card,
CK_MECHANISM_TYPE mechanism,
CK_MECHANISM_INFO_PTR pInfo)
{
sc_pkcs11_mechanism_type_t *mt;
if (!(mt = sc_pkcs11_find_mechanism(p11card, mechanism, 0)))
return CKR_MECHANISM_INVALID;
memcpy(pInfo, &mt->mech_info, sizeof(*pInfo));
return CKR_OK;
}
/*
* Create/destroy operation handle
*/
sc_pkcs11_operation_t *
sc_pkcs11_new_operation(sc_pkcs11_session_t *session,
sc_pkcs11_mechanism_type_t *type)
{
sc_pkcs11_operation_t *res;
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
res = calloc(1, type->obj_size);
if (res) {
res->session = session;
res->type = type;
}
return res;
}
void
sc_pkcs11_release_operation(sc_pkcs11_operation_t **ptr)
{
sc_pkcs11_operation_t *operation = *ptr;
if (!operation)
return;
if (operation->type && operation->type->release)
operation->type->release(operation);
memset(operation, 0, sizeof(*operation));
free(operation);
*ptr = NULL;
}
CK_RV
sc_pkcs11_md_init(struct sc_pkcs11_session *session,
CK_MECHANISM_PTR pMechanism)
{
struct sc_pkcs11_card *p11card;
sc_pkcs11_operation_t *operation;
sc_pkcs11_mechanism_type_t *mt;
2018-10-31 12:10:12 +00:00
CK_RV rv;
LOG_FUNC_CALLED(context);
if (!session || !session->slot || !(p11card = session->slot->p11card))
LOG_FUNC_RETURN(context, CKR_ARGUMENTS_BAD);
/* See if we support this mechanism type */
mt = sc_pkcs11_find_mechanism(p11card, pMechanism->mechanism, CKF_DIGEST);
if (mt == NULL)
LOG_FUNC_RETURN(context, CKR_MECHANISM_INVALID);
rv = session_start_operation(session, SC_PKCS11_OPERATION_DIGEST, mt, &operation);
if (rv != CKR_OK)
2018-10-31 12:10:12 +00:00
LOG_FUNC_RETURN(context, (int) rv);
memcpy(&operation->mechanism, pMechanism, sizeof(CK_MECHANISM));
rv = mt->md_init(operation);
if (rv != CKR_OK)
session_stop_operation(session, SC_PKCS11_OPERATION_DIGEST);
2018-10-31 12:10:12 +00:00
LOG_FUNC_RETURN(context, (int) rv);
}
CK_RV
sc_pkcs11_md_update(struct sc_pkcs11_session *session,
CK_BYTE_PTR pData, CK_ULONG ulDataLen)
{
sc_pkcs11_operation_t *op;
2018-10-31 12:10:12 +00:00
CK_RV rv;
rv = session_get_operation(session, SC_PKCS11_OPERATION_DIGEST, &op);
if (rv != CKR_OK)
goto done;
rv = op->type->md_update(op, pData, ulDataLen);
done:
if (rv != CKR_OK)
session_stop_operation(session, SC_PKCS11_OPERATION_DIGEST);
2018-10-31 12:10:12 +00:00
LOG_FUNC_RETURN(context, (int) rv);
}
CK_RV
sc_pkcs11_md_final(struct sc_pkcs11_session *session,
CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
{
sc_pkcs11_operation_t *op;
CK_RV rv;
rv = session_get_operation(session, SC_PKCS11_OPERATION_DIGEST, &op);
if (rv != CKR_OK)
2018-10-31 12:10:12 +00:00
LOG_FUNC_RETURN(context, (int) rv);
/* This is a request for the digest length */
if (pData == NULL)
*pulDataLen = 0;
rv = op->type->md_final(op, pData, pulDataLen);
if (rv == CKR_BUFFER_TOO_SMALL)
LOG_FUNC_RETURN(context, pData == NULL ? CKR_OK : CKR_BUFFER_TOO_SMALL);
session_stop_operation(session, SC_PKCS11_OPERATION_DIGEST);
2018-10-31 12:10:12 +00:00
LOG_FUNC_RETURN(context, (int) rv);
}
/*
* Initialize a signing context. When we get here, we know
* the key object is capable of signing _something_
*/
CK_RV
sc_pkcs11_sign_init(struct sc_pkcs11_session *session, CK_MECHANISM_PTR pMechanism,
struct sc_pkcs11_object *key, CK_MECHANISM_TYPE key_type)
{
struct sc_pkcs11_card *p11card;
sc_pkcs11_operation_t *operation;
sc_pkcs11_mechanism_type_t *mt;
2018-10-31 12:10:12 +00:00
CK_RV rv;
LOG_FUNC_CALLED(context);
if (!session || !session->slot || !(p11card = session->slot->p11card))
LOG_FUNC_RETURN(context, CKR_ARGUMENTS_BAD);
/* See if we support this mechanism type */
sc_log(context, "mechanism 0x%lX, key-type 0x%lX",
pMechanism->mechanism, key_type);
mt = sc_pkcs11_find_mechanism(p11card, pMechanism->mechanism, CKF_SIGN);
if (mt == NULL)
LOG_FUNC_RETURN(context, CKR_MECHANISM_INVALID);
/* See if compatible with key type */
if (mt->key_type != key_type)
LOG_FUNC_RETURN(context, CKR_KEY_TYPE_INCONSISTENT);
if (pMechanism->pParameter &&
pMechanism->ulParameterLen > sizeof(operation->mechanism_params))
LOG_FUNC_RETURN(context, CKR_ARGUMENTS_BAD);
rv = session_start_operation(session, SC_PKCS11_OPERATION_SIGN, mt, &operation);
if (rv != CKR_OK)
2018-10-31 12:10:12 +00:00
LOG_FUNC_RETURN(context, (int) rv);
memcpy(&operation->mechanism, pMechanism, sizeof(CK_MECHANISM));
if (pMechanism->pParameter) {
memcpy(&operation->mechanism_params, pMechanism->pParameter,
pMechanism->ulParameterLen);
operation->mechanism.pParameter = &operation->mechanism_params;
}
rv = mt->sign_init(operation, key);
if (rv != CKR_OK)
session_stop_operation(session, SC_PKCS11_OPERATION_SIGN);
2018-10-31 12:10:12 +00:00
LOG_FUNC_RETURN(context, (int) rv);
}
CK_RV
sc_pkcs11_sign_update(struct sc_pkcs11_session *session,
CK_BYTE_PTR pData, CK_ULONG ulDataLen)
{
sc_pkcs11_operation_t *op;
2018-10-31 12:10:12 +00:00
CK_RV rv;
LOG_FUNC_CALLED(context);
rv = session_get_operation(session, SC_PKCS11_OPERATION_SIGN, &op);
if (rv != CKR_OK)
2018-10-31 12:10:12 +00:00
LOG_FUNC_RETURN(context, (int) rv);
if (op->type->sign_update == NULL) {
rv = CKR_KEY_TYPE_INCONSISTENT;
goto done;
}
rv = op->type->sign_update(op, pData, ulDataLen);
done:
if (rv != CKR_OK)
session_stop_operation(session, SC_PKCS11_OPERATION_SIGN);
2018-10-31 12:10:12 +00:00
LOG_FUNC_RETURN(context, (int) rv);
}
CK_RV
sc_pkcs11_sign_final(struct sc_pkcs11_session *session,
CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
{
sc_pkcs11_operation_t *op;
2018-10-31 12:10:12 +00:00
CK_RV rv;
LOG_FUNC_CALLED(context);
rv = session_get_operation(session, SC_PKCS11_OPERATION_SIGN, &op);
if (rv != CKR_OK)
2018-10-31 12:10:12 +00:00
LOG_FUNC_RETURN(context, (int) rv);
/* Bail out for signature mechanisms that don't do hashing */
if (op->type->sign_final == NULL) {
rv = CKR_KEY_TYPE_INCONSISTENT;
goto done;
}
rv = op->type->sign_final(op, pSignature, pulSignatureLen);
done:
if (rv != CKR_BUFFER_TOO_SMALL && pSignature != NULL)
session_stop_operation(session, SC_PKCS11_OPERATION_SIGN);
2018-10-31 12:10:12 +00:00
LOG_FUNC_RETURN(context, (int) rv);
}
CK_RV
sc_pkcs11_sign_size(struct sc_pkcs11_session *session, CK_ULONG_PTR pLength)
{
sc_pkcs11_operation_t *op;
2018-10-31 12:10:12 +00:00
CK_RV rv;
rv = session_get_operation(session, SC_PKCS11_OPERATION_SIGN, &op);
if (rv != CKR_OK)
2018-10-31 12:10:12 +00:00
LOG_FUNC_RETURN(context, (int) rv);
/* Bail out for signature mechanisms that don't do hashing */
if (op->type->sign_size == NULL) {
rv = CKR_KEY_TYPE_INCONSISTENT;
goto done;
}
rv = op->type->sign_size(op, pLength);
done:
if (rv != CKR_OK)
session_stop_operation(session, SC_PKCS11_OPERATION_SIGN);
2018-10-31 12:10:12 +00:00
LOG_FUNC_RETURN(context, (int) rv);
}
/*
* Initialize a signature operation
*/
static CK_RV
sc_pkcs11_signature_init(sc_pkcs11_operation_t *operation,
struct sc_pkcs11_object *key)
{
struct hash_signature_info *info;
struct signature_data *data;
CK_RV rv;
int can_do_it = 0;
LOG_FUNC_CALLED(context);
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 (!(data = calloc(1, sizeof(*data))))
LOG_FUNC_RETURN(context, CKR_HOST_MEMORY);
data->info = NULL;
data->key = key;
if (key->ops->can_do) {
rv = key->ops->can_do(operation->session, key, operation->type->mech, CKF_SIGN);
if (rv == CKR_OK) {
/* Mechanism recognised and can be performed by pkcs#15 card */
can_do_it = 1;
}
else if (rv == CKR_FUNCTION_NOT_SUPPORTED) {
/* Mechanism not recognised by pkcs#15 card */
can_do_it = 0;
}
else {
/* Mechanism recognised but cannot be performed by pkcs#15 card, or some general error. */
free(data);
2018-10-31 12:10:12 +00:00
LOG_FUNC_RETURN(context, (int) rv);
}
}
/* Validate the mechanism parameters */
if (key->ops->init_params) {
rv = key->ops->init_params(operation->session, &operation->mechanism);
if (rv != CKR_OK) {
/* Probably bad arguments */
free(data);
2018-10-31 12:10:12 +00:00
LOG_FUNC_RETURN(context, (int) rv);
}
}
/* If this is a signature with hash operation,
* and card cannot perform itself signature with hash operation,
* set up the hash operation */
info = (struct hash_signature_info *) operation->type->mech_data;
if (info != NULL && !can_do_it) {
/* Initialize hash operation */
data->md = sc_pkcs11_new_operation(operation->session, info->hash_type);
if (data->md == NULL)
rv = CKR_HOST_MEMORY;
else
rv = info->hash_type->md_init(data->md);
if (rv != CKR_OK) {
sc_pkcs11_release_operation(&data->md);
free(data);
2018-10-31 12:10:12 +00:00
LOG_FUNC_RETURN(context, (int) rv);
}
data->info = info;
}
operation->priv_data = data;
LOG_FUNC_RETURN(context, CKR_OK);
}
static CK_RV
sc_pkcs11_signature_update(sc_pkcs11_operation_t *operation,
CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
{
struct signature_data *data;
LOG_FUNC_CALLED(context);
sc_log(context, "data part length %li", ulPartLen);
data = (struct signature_data *) operation->priv_data;
if (data->md) {
CK_RV rv = data->md->type->md_update(data->md, pPart, ulPartLen);
2018-10-31 12:10:12 +00:00
LOG_FUNC_RETURN(context, (int) rv);
}
/* This signature mechanism operates on the raw data */
if (data->buffer_len + ulPartLen > sizeof(data->buffer))
LOG_FUNC_RETURN(context, CKR_DATA_LEN_RANGE);
memcpy(data->buffer + data->buffer_len, pPart, ulPartLen);
data->buffer_len += ulPartLen;
LOG_FUNC_RETURN(context, CKR_OK);
}
static CK_RV
sc_pkcs11_signature_final(sc_pkcs11_operation_t *operation,
CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
{
struct signature_data *data;
CK_RV rv;
LOG_FUNC_CALLED(context);
data = (struct signature_data *) operation->priv_data;
if (data->md) {
sc_pkcs11_operation_t *md = data->md;
CK_ULONG len = sizeof(data->buffer);
rv = md->type->md_final(md, data->buffer, &len);
if (rv == CKR_BUFFER_TOO_SMALL)
rv = CKR_FUNCTION_FAILED;
if (rv != CKR_OK)
2018-10-31 12:10:12 +00:00
LOG_FUNC_RETURN(context, (int) rv);
data->buffer_len = (unsigned int) len;
}
rv = data->key->ops->sign(operation->session, data->key, &operation->mechanism,
data->buffer, data->buffer_len, pSignature, pulSignatureLen);
2018-10-31 12:10:12 +00:00
LOG_FUNC_RETURN(context, (int) rv);
}
static CK_RV
sc_pkcs11_signature_size(sc_pkcs11_operation_t *operation, CK_ULONG_PTR pLength)
{
struct sc_pkcs11_object *key;
CK_ATTRIBUTE attr = { CKA_MODULUS_BITS, pLength, sizeof(*pLength) };
CK_KEY_TYPE key_type;
CK_ATTRIBUTE attr_key_type = { CKA_KEY_TYPE, &key_type, sizeof(key_type) };
CK_RV rv;
key = ((struct signature_data *) operation->priv_data)->key;
/*
* EC and GOSTR do not have CKA_MODULUS_BITS attribute.
* But other code in framework treats them as if they do.
* So should do switch(key_type)
* and then get what ever attributes are needed.
*/
rv = key->ops->get_attribute(operation->session, key, &attr_key_type);
if (rv == CKR_OK) {
switch(key_type) {
case CKK_RSA:
rv = key->ops->get_attribute(operation->session, key, &attr);
/* convert bits to bytes */
if (rv == CKR_OK)
*pLength = (*pLength + 7) / 8;
break;
case CKK_EC:
/* TODO: -DEE we should use something other then CKA_MODULUS_BITS... */
rv = key->ops->get_attribute(operation->session, key, &attr);
*pLength = ((*pLength + 7)/8) * 2 ; /* 2*nLen in bytes */
break;
case CKK_GOSTR3410:
rv = key->ops->get_attribute(operation->session, key, &attr);
if (rv == CKR_OK)
*pLength = (*pLength + 7) / 8 * 2;
break;
default:
rv = CKR_MECHANISM_INVALID;
}
}
2018-10-31 12:10:12 +00:00
LOG_FUNC_RETURN(context, (int) rv);
}
static void
sc_pkcs11_signature_release(sc_pkcs11_operation_t *operation)
{
struct signature_data *data;
data = (struct signature_data *) operation->priv_data;
if (!data)
return;
sc_pkcs11_release_operation(&data->md);
memset(data, 0, sizeof(*data));
free(data);
}
Complete rewrite of OpenSC build system. 1. Build system now supports MinGW (Windows) compilation using msys and cross compilation. 2. Ability to explicitly disable and enable dependencies of the package. 3. openct, pcsc and nsplugins features are disabled by default. 4. Modified pcsc driver to use pcsc dynamically, no compile time dependency is required. 5. --enable-pcsc-lite configuration option renamed to --enable-pcsc. 6. Install opensc.conf file (as opensc.conf.new if opensc.conf exists). 7. Add--enable-doc configuration option, allow installing documentation into target. 8. Add --disable-man configuration option, allow msys mingw32 users to build from svn without extra dependencies. 9. Add export files to each library in order to export only required symbols. Windows native build may use these files instead of scanning objects' symbols. 10. Add opensc-tool --info to display some general information about the build. 11. Create compatibility library to be linked against library instread of recompiling the same source files in different places. 12. Add different win32 version resource to each class of outputs. 13. Make xsl-stylesheets location selectable. 14. Some win32 fixups. 15. Some warning fixups. 16. Many other autoconf/automake cleanups. Alon Bar-Lev svn diff -r 3315:3399 https://www.opensc-project.org/svn/opensc/branches/alonbl/mingw _M . D configure.in _M src _M src/openssh M src/openssh/Makefile.am _M src/tools M src/tools/rutoken-tool.c M src/tools/opensc-tool.c M src/tools/cardos-info.c M src/tools/pkcs15-crypt.c M src/tools/pkcs15-init.c M src/tools/piv-tool.c M src/tools/netkey-tool.c M src/tools/eidenv.c M src/tools/cryptoflex-tool.c M src/tools/util.c M src/tools/pkcs11-tool.c M src/tools/pkcs15-tool.c M src/tools/util.h M src/tools/opensc-explorer.c M src/tools/Makefile.am _M src/pkcs11 M src/pkcs11/pkcs11-global.c M src/pkcs11/framework-pkcs15.c M src/pkcs11/mechanism.c M src/pkcs11/pkcs11-display.c M src/pkcs11/pkcs11-object.c A src/pkcs11/opensc-pkcs11.exports M src/pkcs11/sc-pkcs11.h M src/pkcs11/pkcs11-spy.c M src/pkcs11/openssl.c M src/pkcs11/Makefile.am A src/pkcs11/pkcs11-spy.exports _M src/tests _M src/tests/regression M src/tests/regression/Makefile.am M src/tests/sc-test.c M src/tests/pintest.c M src/tests/Makefile.am _M src/include _M src/include/opensc M src/include/opensc/Makefile.am A src/include/opensc/svnignore M src/include/Makefile.am _M src/signer _M src/signer/npinclude M src/signer/npinclude/Makefile.am M src/signer/Makefile.am A src/signer/signer.exports _M src/common A src/common/compat_dummy.c D src/common/getopt.txt D src/common/strlcpy.c D src/common/LICENSE A src/common/compat_getopt.txt A src/common/compat_strlcpy.c A src/common/LICENSE.compat_getopt A src/common/compat_getopt.c D src/common/strlcpy.h D src/common/ChangeLog D src/common/getpass.c D src/common/my_getopt.c A src/common/compat_strlcpy.h A src/common/compat_getpass.c A src/common/compat_getopt.h A src/common/ChangeLog.compat_getopt D src/common/README.strlcpy D src/common/my_getopt.h A src/common/compat_getpass.h A src/common/README.compat_strlcpy D src/common/strlcpy.3 A src/common/README.compat_getopt D src/common/getopt.3 D src/common/README.my_getopt A src/common/compat_strlcpy.3 A src/common/compat_getopt.3 M src/common/Makefile.am M src/Makefile.am _M src/pkcs15init M src/pkcs15init/pkcs15-oberthur.c M src/pkcs15init/profile.c M src/pkcs15init/pkcs15-lib.c M src/pkcs15init/pkcs15-rutoken.c A src/pkcs15init/pkcs15init.exports M src/pkcs15init/pkcs15-gpk.c M src/pkcs15init/Makefile.am _M src/scconf M src/scconf/Makefile.am M src/scconf/parse.c A src/scconf/scconf.exports _M src/libopensc M src/libopensc/card-rutoken.c M src/libopensc/compression.c M src/libopensc/sc.c M src/libopensc/card-piv.c M src/libopensc/pkcs15-openpgp.c M src/libopensc/pkcs15-postecert.c M src/libopensc/pkcs15-tcos.c M src/libopensc/opensc-config.in M src/libopensc/reader-pcsc.c A src/libopensc/internal-winscard.h M src/libopensc/ctx.c A src/libopensc/libopensc.exports M src/libopensc/pkcs15-piv.c M src/libopensc/pkcs15-infocamere.c M src/libopensc/internal.h M src/libopensc/pkcs15-actalis.c M src/libopensc/pkcs15-starcert.c M src/libopensc/card-oberthur.c M src/libopensc/pkcs15-atrust-acos.c M src/libopensc/p15card-helper.c D src/libopensc/part10.h M src/libopensc/ui.c M src/libopensc/card-gpk.c M src/libopensc/pkcs15-wrap.c M src/libopensc/pkcs15-gemsafeGPK.c M src/libopensc/log.c M src/libopensc/pkcs15-esteid.c M src/libopensc/pkcs15-prkey-rutoken.c M src/libopensc/log.h M src/libopensc/Makefile.am M src/libopensc/reader-openct.c _M aclocal M aclocal/Makefile.am _M win32 M win32/Makefile.am A win32/versioninfo.rc.in A win32/ltrc.inc A configure.ac _M doc _M doc/tools M doc/tools/pkcs15-profile.xml D doc/changelog.sh D doc/export-wiki.xsl _M doc/api _M doc/api/file M doc/api/man.xsl _M doc/api/asn1 _M doc/api/apps _M doc/api/init _M doc/api/types _M doc/api/card M doc/api/html.xsl _M doc/api/misc _M doc/api/util M doc/Makefile.am D doc/export-wiki.sh AM doc/nonpersistent A doc/nonpersistent/export-wiki.xsl A doc/nonpersistent/Makefile.am A doc/nonpersistent/export-wiki.sh A doc/nonpersistent/svn2cl.xsl D doc/generate-man.sh D doc/svn2cl.xsl M Makefile.am A svnignore _M etc M etc/opensc.conf.in M etc/Makefile.am D man _M solaris M solaris/Makefile git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@3405 c6295689-39f2-0310-b995-f0e70906c6a9
2008-03-06 16:06:59 +00:00
#ifdef ENABLE_OPENSSL
/*
* Initialize a verify context. When we get here, we know
* the key object is capable of verifying _something_
*/
CK_RV
sc_pkcs11_verif_init(struct sc_pkcs11_session *session, CK_MECHANISM_PTR pMechanism,
struct sc_pkcs11_object *key, CK_MECHANISM_TYPE key_type)
{
struct sc_pkcs11_card *p11card;
sc_pkcs11_operation_t *operation;
sc_pkcs11_mechanism_type_t *mt;
2018-10-31 12:10:12 +00:00
CK_RV rv;
if (!session || !session->slot
|| !(p11card = session->slot->p11card))
return CKR_ARGUMENTS_BAD;
/* See if we support this mechanism type */
mt = sc_pkcs11_find_mechanism(p11card, pMechanism->mechanism, CKF_VERIFY);
if (mt == NULL)
return CKR_MECHANISM_INVALID;
/* See if compatible with key type */
if (mt->key_type != key_type)
return CKR_KEY_TYPE_INCONSISTENT;
rv = session_start_operation(session, SC_PKCS11_OPERATION_VERIFY, mt, &operation);
if (rv != CKR_OK)
return rv;
memcpy(&operation->mechanism, pMechanism, sizeof(CK_MECHANISM));
if (pMechanism->pParameter) {
memcpy(&operation->mechanism_params, pMechanism->pParameter,
pMechanism->ulParameterLen);
operation->mechanism.pParameter = &operation->mechanism_params;
}
rv = mt->verif_init(operation, key);
if (rv != CKR_OK)
session_stop_operation(session, SC_PKCS11_OPERATION_VERIFY);
return rv;
}
CK_RV
sc_pkcs11_verif_update(struct sc_pkcs11_session *session,
CK_BYTE_PTR pData, CK_ULONG ulDataLen)
{
sc_pkcs11_operation_t *op;
2018-10-31 12:10:12 +00:00
CK_RV rv;
rv = session_get_operation(session, SC_PKCS11_OPERATION_VERIFY, &op);
if (rv != CKR_OK)
return rv;
if (op->type->verif_update == NULL) {
rv = CKR_KEY_TYPE_INCONSISTENT;
goto done;
}
rv = op->type->verif_update(op, pData, ulDataLen);
done:
if (rv != CKR_OK)
session_stop_operation(session, SC_PKCS11_OPERATION_VERIFY);
return rv;
}
CK_RV
sc_pkcs11_verif_final(struct sc_pkcs11_session *session,
CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
{
sc_pkcs11_operation_t *op;
2018-10-31 12:10:12 +00:00
CK_RV rv;
rv = session_get_operation(session, SC_PKCS11_OPERATION_VERIFY, &op);
if (rv != CKR_OK)
return rv;
if (op->type->verif_final == NULL) {
rv = CKR_KEY_TYPE_INCONSISTENT;
goto done;
}
rv = op->type->verif_final(op, pSignature, ulSignatureLen);
done:
session_stop_operation(session, SC_PKCS11_OPERATION_VERIFY);
return rv;
}
/*
* Initialize a verify operation
*/
static CK_RV
sc_pkcs11_verify_init(sc_pkcs11_operation_t *operation,
struct sc_pkcs11_object *key)
{
struct hash_signature_info *info;
struct signature_data *data;
2018-10-31 12:10:12 +00:00
CK_RV rv;
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 (!(data = calloc(1, sizeof(*data))))
return CKR_HOST_MEMORY;
data->info = NULL;
data->key = key;
if (key->ops->can_do) {
rv = key->ops->can_do(operation->session, key, operation->type->mech, CKF_SIGN);
if ((rv == CKR_OK) || (rv == CKR_FUNCTION_NOT_SUPPORTED)) {
/* Mechanism recognized and can be performed by pkcs#15 card or algorithm references not supported */
}
else {
/* Mechanism cannot be performed by pkcs#15 card, or some general error. */
free(data);
2018-10-31 12:10:12 +00:00
LOG_FUNC_RETURN(context, (int) rv);
}
}
/* Validate the mechanism parameters */
if (key->ops->init_params) {
rv = key->ops->init_params(operation->session, &operation->mechanism);
if (rv != CKR_OK) {
/* Probably bad arguments */
free(data);
2018-10-31 12:10:12 +00:00
LOG_FUNC_RETURN(context, (int) rv);
}
}
/* If this is a verify with hash operation, set up the
* hash operation */
info = (struct hash_signature_info *) operation->type->mech_data;
if (info != NULL) {
/* Initialize hash operation */
data->md = sc_pkcs11_new_operation(operation->session,
info->hash_type);
if (data->md == NULL)
rv = CKR_HOST_MEMORY;
else
rv = info->hash_type->md_init(data->md);
if (rv != CKR_OK) {
sc_pkcs11_release_operation(&data->md);
free(data);
return rv;
}
data->info = info;
}
operation->priv_data = data;
return CKR_OK;
}
static CK_RV
sc_pkcs11_verify_update(sc_pkcs11_operation_t *operation,
CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
{
struct signature_data *data;
data = (struct signature_data *) operation->priv_data;
if (data->md) {
sc_pkcs11_operation_t *md = data->md;
return md->type->md_update(md, pPart, ulPartLen);
}
/* This verification mechanism operates on the raw data */
if (data->buffer_len + ulPartLen > sizeof(data->buffer))
return CKR_DATA_LEN_RANGE;
memcpy(data->buffer + data->buffer_len, pPart, ulPartLen);
data->buffer_len += ulPartLen;
return CKR_OK;
}
static CK_RV
sc_pkcs11_verify_final(sc_pkcs11_operation_t *operation,
CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
{
struct signature_data *data;
struct sc_pkcs11_object *key;
unsigned char *pubkey_value = NULL;
CK_KEY_TYPE key_type;
CK_BYTE params[9 /* GOST_PARAMS_ENCODED_OID_SIZE */] = { 0 };
CK_ATTRIBUTE attr = {CKA_VALUE, NULL, 0};
CK_ATTRIBUTE attr_key_type = {CKA_KEY_TYPE, &key_type, sizeof(key_type)};
CK_ATTRIBUTE attr_key_params = {CKA_GOSTR3410_PARAMS, &params, sizeof(params)};
2018-10-31 12:10:12 +00:00
CK_RV rv;
data = (struct signature_data *) operation->priv_data;
if (pSignature == NULL)
return CKR_ARGUMENTS_BAD;
key = data->key;
rv = key->ops->get_attribute(operation->session, key, &attr_key_type);
if (rv != CKR_OK)
return rv;
if (key_type != CKK_GOSTR3410)
attr.type = CKA_SPKI;
rv = key->ops->get_attribute(operation->session, key, &attr);
if (rv != CKR_OK)
return rv;
pubkey_value = calloc(1, attr.ulValueLen);
if (!pubkey_value) {
rv = CKR_HOST_MEMORY;
goto done;
}
attr.pValue = pubkey_value;
rv = key->ops->get_attribute(operation->session, key, &attr);
if (rv != CKR_OK)
goto done;
if (key_type == CKK_GOSTR3410) {
rv = key->ops->get_attribute(operation->session, key, &attr_key_params);
if (rv != CKR_OK)
goto done;
}
2018-10-31 12:10:12 +00:00
rv = sc_pkcs11_verify_data(pubkey_value, (unsigned int) attr.ulValueLen,
params, sizeof(params),
&operation->mechanism, data->md,
2018-10-31 12:10:12 +00:00
data->buffer, data->buffer_len, pSignature, (unsigned int) ulSignatureLen);
done:
free(pubkey_value);
return rv;
}
#endif
/*
* Initialize a decryption context. When we get here, we know
* the key object is capable of decrypting _something_
*/
CK_RV
sc_pkcs11_decr_init(struct sc_pkcs11_session *session,
CK_MECHANISM_PTR pMechanism,
struct sc_pkcs11_object *key,
CK_MECHANISM_TYPE key_type)
{
struct sc_pkcs11_card *p11card;
sc_pkcs11_operation_t *operation;
sc_pkcs11_mechanism_type_t *mt;
CK_RV rv;
if (!session || !session->slot
|| !(p11card = session->slot->p11card))
return CKR_ARGUMENTS_BAD;
/* See if we support this mechanism type */
mt = sc_pkcs11_find_mechanism(p11card, pMechanism->mechanism, CKF_DECRYPT);
if (mt == NULL)
return CKR_MECHANISM_INVALID;
/* See if compatible with key type */
if (mt->key_type != key_type)
return CKR_KEY_TYPE_INCONSISTENT;
rv = session_start_operation(session, SC_PKCS11_OPERATION_DECRYPT, mt, &operation);
if (rv != CKR_OK)
return rv;
memcpy(&operation->mechanism, pMechanism, sizeof(CK_MECHANISM));
if (pMechanism->pParameter) {
memcpy(&operation->mechanism_params, pMechanism->pParameter,
pMechanism->ulParameterLen);
operation->mechanism.pParameter = &operation->mechanism_params;
}
rv = mt->decrypt_init(operation, key);
if (rv != CKR_OK)
session_stop_operation(session, SC_PKCS11_OPERATION_DECRYPT);
return rv;
}
CK_RV
sc_pkcs11_decr(struct sc_pkcs11_session *session,
CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen,
CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
{
sc_pkcs11_operation_t *op;
2018-10-31 12:10:12 +00:00
CK_RV rv;
rv = session_get_operation(session, SC_PKCS11_OPERATION_DECRYPT, &op);
if (rv != CKR_OK)
return rv;
rv = op->type->decrypt(op, pEncryptedData, ulEncryptedDataLen,
pData, pulDataLen);
if (rv != CKR_BUFFER_TOO_SMALL && pData != NULL)
session_stop_operation(session, SC_PKCS11_OPERATION_DECRYPT);
return rv;
}
CK_RV
sc_pkcs11_wrap(struct sc_pkcs11_session *session,
CK_MECHANISM_PTR pMechanism,
struct sc_pkcs11_object *wrappingKey, /* wrapping key */
CK_KEY_TYPE key_type, /* type of the wrapping key */
struct sc_pkcs11_object *targetKey, /* the key to be wrapped */
CK_BYTE_PTR wrappedData,
CK_ULONG_PTR wrappedDataLen)
{
struct sc_pkcs11_card *p11card;
sc_pkcs11_operation_t *operation;
sc_pkcs11_mechanism_type_t *mt;
CK_RV rv;
if (!session || !session->slot || !(p11card = session->slot->p11card))
return CKR_ARGUMENTS_BAD;
/* See if we support this mechanism type */
mt = sc_pkcs11_find_mechanism(p11card, pMechanism->mechanism, CKF_UNWRAP);
if (mt == NULL)
return CKR_MECHANISM_INVALID;
/* See if compatible with key type */
/* TODO: what if there are several mechanisms with different key types? Should we loop through them? */
if (mt->key_type != key_type)
return CKR_KEY_TYPE_INCONSISTENT;
rv = session_start_operation(session, SC_PKCS11_OPERATION_WRAP, mt, &operation);
if (rv != CKR_OK)
return rv;
memcpy(&operation->mechanism, pMechanism, sizeof(CK_MECHANISM));
rv = operation->type->wrap(operation, wrappingKey,
targetKey, wrappedData,
wrappedDataLen);
session_stop_operation(session, SC_PKCS11_OPERATION_WRAP);
return rv;
}
/*
* Unwrap a wrapped key into card. A new key object is created on card.
*/
CK_RV
sc_pkcs11_unwrap(struct sc_pkcs11_session *session,
CK_MECHANISM_PTR pMechanism,
struct sc_pkcs11_object *unwrappingKey,
CK_KEY_TYPE key_type, /* type of the unwrapping key */
CK_BYTE_PTR pWrappedKey, /* the wrapped key */
CK_ULONG ulWrappedKeyLen, /* bytes length of wrapped key */
struct sc_pkcs11_object *targetKey)
{
struct sc_pkcs11_card *p11card;
sc_pkcs11_operation_t *operation;
sc_pkcs11_mechanism_type_t *mt;
CK_RV rv;
if (!session || !session->slot || !(p11card = session->slot->p11card))
return CKR_ARGUMENTS_BAD;
/* See if we support this mechanism type */
mt = sc_pkcs11_find_mechanism(p11card, pMechanism->mechanism, CKF_UNWRAP);
if (mt == NULL)
return CKR_MECHANISM_INVALID;
/* See if compatible with key type */
/* TODO: what if there are several mechanisms with different key types? Should we loop through them? */
if (mt->key_type != key_type)
return CKR_KEY_TYPE_INCONSISTENT;
rv = session_start_operation(session, SC_PKCS11_OPERATION_UNWRAP, mt, &operation);
if (rv != CKR_OK)
return rv;
memcpy(&operation->mechanism, pMechanism, sizeof(CK_MECHANISM));
/*
* TODO: does it make sense to support unwrapping to an in memory key object?
* This implementation assumes that the key should be unwrapped into a
* key object on card, regardless whether CKA_TOKEN = FALSE
* CKA_TOKEN = FALSE is considered an on card session object.
*/
rv = operation->type->unwrap(operation, unwrappingKey,
pWrappedKey, ulWrappedKeyLen,
targetKey);
session_stop_operation(session, SC_PKCS11_OPERATION_UNWRAP);
return rv;
}
/* Derive one key from another, and return results in created object */
CK_RV
sc_pkcs11_deri(struct sc_pkcs11_session *session,
CK_MECHANISM_PTR pMechanism,
struct sc_pkcs11_object * basekey,
CK_KEY_TYPE key_type,
CK_SESSION_HANDLE hSession,
CK_OBJECT_HANDLE hdkey,
struct sc_pkcs11_object * dkey)
{
struct sc_pkcs11_card *p11card;
sc_pkcs11_operation_t *operation;
sc_pkcs11_mechanism_type_t *mt;
CK_BYTE_PTR keybuf = NULL;
CK_ULONG ulDataLen = 0;
CK_ATTRIBUTE template[] = {
{CKA_VALUE, keybuf, 0}
};
CK_RV rv;
if (!session || !session->slot
|| !(p11card = session->slot->p11card))
return CKR_ARGUMENTS_BAD;
/* See if we support this mechanism type */
mt = sc_pkcs11_find_mechanism(p11card, pMechanism->mechanism, CKF_DERIVE);
if (mt == NULL)
return CKR_MECHANISM_INVALID;
/* See if compatible with key type */
if (mt->key_type != key_type)
return CKR_KEY_TYPE_INCONSISTENT;
rv = session_start_operation(session, SC_PKCS11_OPERATION_DERIVE, mt, &operation);
if (rv != CKR_OK)
return rv;
memcpy(&operation->mechanism, pMechanism, sizeof(CK_MECHANISM));
/* Get the size of the data to be returned
* If the card could derive a key an leave it on the card
* then no data is returned.
* If the card returns the data, we will store it in the secret key CKA_VALUE
*/
ulDataLen = 0;
rv = operation->type->derive(operation, basekey,
pMechanism->pParameter, pMechanism->ulParameterLen,
NULL, &ulDataLen);
if (rv != CKR_OK)
goto out;
if (ulDataLen > 0)
keybuf = calloc(1,ulDataLen);
else
keybuf = calloc(1,8); /* pass in dummy buffer */
if (!keybuf) {
rv = CKR_HOST_MEMORY;
goto out;
}
/* Now do the actual derivation */
rv = operation->type->derive(operation, basekey,
pMechanism->pParameter, pMechanism->ulParameterLen,
keybuf, &ulDataLen);
if (rv != CKR_OK)
goto out;
/* add the CKA_VALUE attribute to the template if it was returned
* if not assume it is on the card...
* But for now PIV with ECDH returns the generic key data
* TODO need to support truncation, if CKA_VALUE_LEN < ulDataLem
*/
if (ulDataLen > 0) {
template[0].pValue = keybuf;
template[0].ulValueLen = ulDataLen;
dkey->ops->set_attribute(session, dkey, &template[0]);
memset(keybuf,0,ulDataLen);
}
out:
session_stop_operation(session, SC_PKCS11_OPERATION_DERIVE);
if (keybuf)
free(keybuf);
return rv;
}
/*
* Initialize a decrypt operation
*/
static CK_RV
sc_pkcs11_decrypt_init(sc_pkcs11_operation_t *operation,
struct sc_pkcs11_object *key)
{
struct signature_data *data;
CK_RV rv;
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 (!(data = calloc(1, sizeof(*data))))
return CKR_HOST_MEMORY;
data->key = key;
if (key->ops->can_do) {
rv = key->ops->can_do(operation->session, key, operation->type->mech, CKF_DECRYPT);
if ((rv == CKR_OK) || (rv == CKR_FUNCTION_NOT_SUPPORTED)) {
/* Mechanism recognized and can be performed by pkcs#15 card or algorithm references not supported */
}
else {
/* Mechanism cannot be performed by pkcs#15 card, or some general error. */
free(data);
2018-10-31 12:10:12 +00:00
LOG_FUNC_RETURN(context, (int) rv);
}
}
operation->priv_data = data;
return CKR_OK;
}
static CK_RV
sc_pkcs11_decrypt(sc_pkcs11_operation_t *operation,
CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen,
CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
{
struct signature_data *data;
struct sc_pkcs11_object *key;
data = (struct signature_data*) operation->priv_data;
key = data->key;
return key->ops->decrypt(operation->session,
key, &operation->mechanism,
pEncryptedData, ulEncryptedDataLen,
pData, pulDataLen);
}
static CK_RV
sc_pkcs11_derive(sc_pkcs11_operation_t *operation,
struct sc_pkcs11_object *basekey,
CK_BYTE_PTR pmechParam, CK_ULONG ulmechParamLen,
CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
{
return basekey->ops->derive(operation->session,
basekey,
&operation->mechanism,
pmechParam, ulmechParamLen,
pData, pulDataLen);
}
static CK_RV
sc_pkcs11_wrap_operation(sc_pkcs11_operation_t *operation,
struct sc_pkcs11_object *wrappingKey,
struct sc_pkcs11_object *targetKey,
CK_BYTE_PTR pWrappedData, CK_ULONG_PTR ulWrappedDataLen)
{
if (!operation || !wrappingKey || !wrappingKey->ops || !wrappingKey->ops->wrap_key)
return CKR_ARGUMENTS_BAD;
return wrappingKey->ops->wrap_key(operation->session,
wrappingKey,
&operation->mechanism,
targetKey, pWrappedData,
ulWrappedDataLen);
}
static CK_RV
sc_pkcs11_unwrap_operation(sc_pkcs11_operation_t *operation,
struct sc_pkcs11_object *unwrappingKey,
CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen,
struct sc_pkcs11_object *targetKey)
{
if (!operation || !unwrappingKey || !unwrappingKey->ops || !unwrappingKey->ops->unwrap_key)
return CKR_ARGUMENTS_BAD;
return unwrappingKey->ops->unwrap_key(operation->session,
unwrappingKey,
&operation->mechanism,
pWrappedKey, ulWrappedKeyLen,
targetKey);
}
/*
* Create new mechanism type for a mechanism supported by
* the card
*/
sc_pkcs11_mechanism_type_t *
sc_pkcs11_new_fw_mechanism(CK_MECHANISM_TYPE mech,
CK_MECHANISM_INFO_PTR pInfo,
CK_KEY_TYPE key_type,
const void *priv_data,
void (*free_priv_data)(const void *priv_data))
{
sc_pkcs11_mechanism_type_t *mt;
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
mt = calloc(1, sizeof(*mt));
if (mt == NULL)
return mt;
mt->mech = mech;
mt->mech_info = *pInfo;
mt->key_type = key_type;
mt->mech_data = priv_data;
mt->free_mech_data = free_priv_data;
mt->obj_size = sizeof(sc_pkcs11_operation_t);
mt->release = sc_pkcs11_signature_release;
if (pInfo->flags & CKF_SIGN) {
mt->sign_init = sc_pkcs11_signature_init;
mt->sign_update = sc_pkcs11_signature_update;
mt->sign_final = sc_pkcs11_signature_final;
mt->sign_size = sc_pkcs11_signature_size;
Complete rewrite of OpenSC build system. 1. Build system now supports MinGW (Windows) compilation using msys and cross compilation. 2. Ability to explicitly disable and enable dependencies of the package. 3. openct, pcsc and nsplugins features are disabled by default. 4. Modified pcsc driver to use pcsc dynamically, no compile time dependency is required. 5. --enable-pcsc-lite configuration option renamed to --enable-pcsc. 6. Install opensc.conf file (as opensc.conf.new if opensc.conf exists). 7. Add--enable-doc configuration option, allow installing documentation into target. 8. Add --disable-man configuration option, allow msys mingw32 users to build from svn without extra dependencies. 9. Add export files to each library in order to export only required symbols. Windows native build may use these files instead of scanning objects' symbols. 10. Add opensc-tool --info to display some general information about the build. 11. Create compatibility library to be linked against library instread of recompiling the same source files in different places. 12. Add different win32 version resource to each class of outputs. 13. Make xsl-stylesheets location selectable. 14. Some win32 fixups. 15. Some warning fixups. 16. Many other autoconf/automake cleanups. Alon Bar-Lev svn diff -r 3315:3399 https://www.opensc-project.org/svn/opensc/branches/alonbl/mingw _M . D configure.in _M src _M src/openssh M src/openssh/Makefile.am _M src/tools M src/tools/rutoken-tool.c M src/tools/opensc-tool.c M src/tools/cardos-info.c M src/tools/pkcs15-crypt.c M src/tools/pkcs15-init.c M src/tools/piv-tool.c M src/tools/netkey-tool.c M src/tools/eidenv.c M src/tools/cryptoflex-tool.c M src/tools/util.c M src/tools/pkcs11-tool.c M src/tools/pkcs15-tool.c M src/tools/util.h M src/tools/opensc-explorer.c M src/tools/Makefile.am _M src/pkcs11 M src/pkcs11/pkcs11-global.c M src/pkcs11/framework-pkcs15.c M src/pkcs11/mechanism.c M src/pkcs11/pkcs11-display.c M src/pkcs11/pkcs11-object.c A src/pkcs11/opensc-pkcs11.exports M src/pkcs11/sc-pkcs11.h M src/pkcs11/pkcs11-spy.c M src/pkcs11/openssl.c M src/pkcs11/Makefile.am A src/pkcs11/pkcs11-spy.exports _M src/tests _M src/tests/regression M src/tests/regression/Makefile.am M src/tests/sc-test.c M src/tests/pintest.c M src/tests/Makefile.am _M src/include _M src/include/opensc M src/include/opensc/Makefile.am A src/include/opensc/svnignore M src/include/Makefile.am _M src/signer _M src/signer/npinclude M src/signer/npinclude/Makefile.am M src/signer/Makefile.am A src/signer/signer.exports _M src/common A src/common/compat_dummy.c D src/common/getopt.txt D src/common/strlcpy.c D src/common/LICENSE A src/common/compat_getopt.txt A src/common/compat_strlcpy.c A src/common/LICENSE.compat_getopt A src/common/compat_getopt.c D src/common/strlcpy.h D src/common/ChangeLog D src/common/getpass.c D src/common/my_getopt.c A src/common/compat_strlcpy.h A src/common/compat_getpass.c A src/common/compat_getopt.h A src/common/ChangeLog.compat_getopt D src/common/README.strlcpy D src/common/my_getopt.h A src/common/compat_getpass.h A src/common/README.compat_strlcpy D src/common/strlcpy.3 A src/common/README.compat_getopt D src/common/getopt.3 D src/common/README.my_getopt A src/common/compat_strlcpy.3 A src/common/compat_getopt.3 M src/common/Makefile.am M src/Makefile.am _M src/pkcs15init M src/pkcs15init/pkcs15-oberthur.c M src/pkcs15init/profile.c M src/pkcs15init/pkcs15-lib.c M src/pkcs15init/pkcs15-rutoken.c A src/pkcs15init/pkcs15init.exports M src/pkcs15init/pkcs15-gpk.c M src/pkcs15init/Makefile.am _M src/scconf M src/scconf/Makefile.am M src/scconf/parse.c A src/scconf/scconf.exports _M src/libopensc M src/libopensc/card-rutoken.c M src/libopensc/compression.c M src/libopensc/sc.c M src/libopensc/card-piv.c M src/libopensc/pkcs15-openpgp.c M src/libopensc/pkcs15-postecert.c M src/libopensc/pkcs15-tcos.c M src/libopensc/opensc-config.in M src/libopensc/reader-pcsc.c A src/libopensc/internal-winscard.h M src/libopensc/ctx.c A src/libopensc/libopensc.exports M src/libopensc/pkcs15-piv.c M src/libopensc/pkcs15-infocamere.c M src/libopensc/internal.h M src/libopensc/pkcs15-actalis.c M src/libopensc/pkcs15-starcert.c M src/libopensc/card-oberthur.c M src/libopensc/pkcs15-atrust-acos.c M src/libopensc/p15card-helper.c D src/libopensc/part10.h M src/libopensc/ui.c M src/libopensc/card-gpk.c M src/libopensc/pkcs15-wrap.c M src/libopensc/pkcs15-gemsafeGPK.c M src/libopensc/log.c M src/libopensc/pkcs15-esteid.c M src/libopensc/pkcs15-prkey-rutoken.c M src/libopensc/log.h M src/libopensc/Makefile.am M src/libopensc/reader-openct.c _M aclocal M aclocal/Makefile.am _M win32 M win32/Makefile.am A win32/versioninfo.rc.in A win32/ltrc.inc A configure.ac _M doc _M doc/tools M doc/tools/pkcs15-profile.xml D doc/changelog.sh D doc/export-wiki.xsl _M doc/api _M doc/api/file M doc/api/man.xsl _M doc/api/asn1 _M doc/api/apps _M doc/api/init _M doc/api/types _M doc/api/card M doc/api/html.xsl _M doc/api/misc _M doc/api/util M doc/Makefile.am D doc/export-wiki.sh AM doc/nonpersistent A doc/nonpersistent/export-wiki.xsl A doc/nonpersistent/Makefile.am A doc/nonpersistent/export-wiki.sh A doc/nonpersistent/svn2cl.xsl D doc/generate-man.sh D doc/svn2cl.xsl M Makefile.am A svnignore _M etc M etc/opensc.conf.in M etc/Makefile.am D man _M solaris M solaris/Makefile git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@3405 c6295689-39f2-0310-b995-f0e70906c6a9
2008-03-06 16:06:59 +00:00
#ifdef ENABLE_OPENSSL
mt->verif_init = sc_pkcs11_verify_init;
mt->verif_update = sc_pkcs11_verify_update;
mt->verif_final = sc_pkcs11_verify_final;
#endif
}
if (pInfo->flags & CKF_WRAP) {
mt->wrap = sc_pkcs11_wrap_operation;
}
if (pInfo->flags & CKF_UNWRAP) {
mt->unwrap = sc_pkcs11_unwrap_operation;
}
if (pInfo->flags & CKF_DERIVE) {
mt->derive = sc_pkcs11_derive;
}
if (pInfo->flags & CKF_DECRYPT) {
mt->decrypt_init = sc_pkcs11_decrypt_init;
mt->decrypt = sc_pkcs11_decrypt;
}
return mt;
}
/*
* Register generic mechanisms
*/
CK_RV
sc_pkcs11_register_generic_mechanisms(struct sc_pkcs11_card *p11card)
{
Complete rewrite of OpenSC build system. 1. Build system now supports MinGW (Windows) compilation using msys and cross compilation. 2. Ability to explicitly disable and enable dependencies of the package. 3. openct, pcsc and nsplugins features are disabled by default. 4. Modified pcsc driver to use pcsc dynamically, no compile time dependency is required. 5. --enable-pcsc-lite configuration option renamed to --enable-pcsc. 6. Install opensc.conf file (as opensc.conf.new if opensc.conf exists). 7. Add--enable-doc configuration option, allow installing documentation into target. 8. Add --disable-man configuration option, allow msys mingw32 users to build from svn without extra dependencies. 9. Add export files to each library in order to export only required symbols. Windows native build may use these files instead of scanning objects' symbols. 10. Add opensc-tool --info to display some general information about the build. 11. Create compatibility library to be linked against library instread of recompiling the same source files in different places. 12. Add different win32 version resource to each class of outputs. 13. Make xsl-stylesheets location selectable. 14. Some win32 fixups. 15. Some warning fixups. 16. Many other autoconf/automake cleanups. Alon Bar-Lev svn diff -r 3315:3399 https://www.opensc-project.org/svn/opensc/branches/alonbl/mingw _M . D configure.in _M src _M src/openssh M src/openssh/Makefile.am _M src/tools M src/tools/rutoken-tool.c M src/tools/opensc-tool.c M src/tools/cardos-info.c M src/tools/pkcs15-crypt.c M src/tools/pkcs15-init.c M src/tools/piv-tool.c M src/tools/netkey-tool.c M src/tools/eidenv.c M src/tools/cryptoflex-tool.c M src/tools/util.c M src/tools/pkcs11-tool.c M src/tools/pkcs15-tool.c M src/tools/util.h M src/tools/opensc-explorer.c M src/tools/Makefile.am _M src/pkcs11 M src/pkcs11/pkcs11-global.c M src/pkcs11/framework-pkcs15.c M src/pkcs11/mechanism.c M src/pkcs11/pkcs11-display.c M src/pkcs11/pkcs11-object.c A src/pkcs11/opensc-pkcs11.exports M src/pkcs11/sc-pkcs11.h M src/pkcs11/pkcs11-spy.c M src/pkcs11/openssl.c M src/pkcs11/Makefile.am A src/pkcs11/pkcs11-spy.exports _M src/tests _M src/tests/regression M src/tests/regression/Makefile.am M src/tests/sc-test.c M src/tests/pintest.c M src/tests/Makefile.am _M src/include _M src/include/opensc M src/include/opensc/Makefile.am A src/include/opensc/svnignore M src/include/Makefile.am _M src/signer _M src/signer/npinclude M src/signer/npinclude/Makefile.am M src/signer/Makefile.am A src/signer/signer.exports _M src/common A src/common/compat_dummy.c D src/common/getopt.txt D src/common/strlcpy.c D src/common/LICENSE A src/common/compat_getopt.txt A src/common/compat_strlcpy.c A src/common/LICENSE.compat_getopt A src/common/compat_getopt.c D src/common/strlcpy.h D src/common/ChangeLog D src/common/getpass.c D src/common/my_getopt.c A src/common/compat_strlcpy.h A src/common/compat_getpass.c A src/common/compat_getopt.h A src/common/ChangeLog.compat_getopt D src/common/README.strlcpy D src/common/my_getopt.h A src/common/compat_getpass.h A src/common/README.compat_strlcpy D src/common/strlcpy.3 A src/common/README.compat_getopt D src/common/getopt.3 D src/common/README.my_getopt A src/common/compat_strlcpy.3 A src/common/compat_getopt.3 M src/common/Makefile.am M src/Makefile.am _M src/pkcs15init M src/pkcs15init/pkcs15-oberthur.c M src/pkcs15init/profile.c M src/pkcs15init/pkcs15-lib.c M src/pkcs15init/pkcs15-rutoken.c A src/pkcs15init/pkcs15init.exports M src/pkcs15init/pkcs15-gpk.c M src/pkcs15init/Makefile.am _M src/scconf M src/scconf/Makefile.am M src/scconf/parse.c A src/scconf/scconf.exports _M src/libopensc M src/libopensc/card-rutoken.c M src/libopensc/compression.c M src/libopensc/sc.c M src/libopensc/card-piv.c M src/libopensc/pkcs15-openpgp.c M src/libopensc/pkcs15-postecert.c M src/libopensc/pkcs15-tcos.c M src/libopensc/opensc-config.in M src/libopensc/reader-pcsc.c A src/libopensc/internal-winscard.h M src/libopensc/ctx.c A src/libopensc/libopensc.exports M src/libopensc/pkcs15-piv.c M src/libopensc/pkcs15-infocamere.c M src/libopensc/internal.h M src/libopensc/pkcs15-actalis.c M src/libopensc/pkcs15-starcert.c M src/libopensc/card-oberthur.c M src/libopensc/pkcs15-atrust-acos.c M src/libopensc/p15card-helper.c D src/libopensc/part10.h M src/libopensc/ui.c M src/libopensc/card-gpk.c M src/libopensc/pkcs15-wrap.c M src/libopensc/pkcs15-gemsafeGPK.c M src/libopensc/log.c M src/libopensc/pkcs15-esteid.c M src/libopensc/pkcs15-prkey-rutoken.c M src/libopensc/log.h M src/libopensc/Makefile.am M src/libopensc/reader-openct.c _M aclocal M aclocal/Makefile.am _M win32 M win32/Makefile.am A win32/versioninfo.rc.in A win32/ltrc.inc A configure.ac _M doc _M doc/tools M doc/tools/pkcs15-profile.xml D doc/changelog.sh D doc/export-wiki.xsl _M doc/api _M doc/api/file M doc/api/man.xsl _M doc/api/asn1 _M doc/api/apps _M doc/api/init _M doc/api/types _M doc/api/card M doc/api/html.xsl _M doc/api/misc _M doc/api/util M doc/Makefile.am D doc/export-wiki.sh AM doc/nonpersistent A doc/nonpersistent/export-wiki.xsl A doc/nonpersistent/Makefile.am A doc/nonpersistent/export-wiki.sh A doc/nonpersistent/svn2cl.xsl D doc/generate-man.sh D doc/svn2cl.xsl M Makefile.am A svnignore _M etc M etc/opensc.conf.in M etc/Makefile.am D man _M solaris M solaris/Makefile git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@3405 c6295689-39f2-0310-b995-f0e70906c6a9
2008-03-06 16:06:59 +00:00
#ifdef ENABLE_OPENSSL
sc_pkcs11_register_openssl_mechanisms(p11card);
#endif
return CKR_OK;
}
void free_info(const void *info)
{
free((void *) info);
}
/*
* Register a sign+hash algorithm derived from an algorithm supported
* by the token + a software hash mechanism
*/
CK_RV
sc_pkcs11_register_sign_and_hash_mechanism(struct sc_pkcs11_card *p11card,
CK_MECHANISM_TYPE mech,
CK_MECHANISM_TYPE hash_mech,
sc_pkcs11_mechanism_type_t *sign_type)
{
sc_pkcs11_mechanism_type_t *hash_type, *new_type;
struct hash_signature_info *info;
CK_MECHANISM_INFO mech_info = sign_type->mech_info;
2017-08-04 05:08:52 +00:00
CK_RV rv;
if (!(hash_type = sc_pkcs11_find_mechanism(p11card, hash_mech, CKF_DIGEST)))
return CKR_MECHANISM_INVALID;
/* These hash-based mechs can only be used for sign/verify */
mech_info.flags &= (CKF_SIGN | CKF_SIGN_RECOVER | CKF_VERIFY | CKF_VERIFY_RECOVER);
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
info = calloc(1, sizeof(*info));
if (!info)
return CKR_HOST_MEMORY;
info->mech = mech;
info->sign_type = sign_type;
info->hash_type = hash_type;
info->sign_mech = sign_type->mech;
info->hash_mech = hash_mech;
new_type = sc_pkcs11_new_fw_mechanism(mech, &mech_info, sign_type->key_type, info, free_info);
if (!new_type) {
2017-08-04 05:08:52 +00:00
free_info(info);
return CKR_HOST_MEMORY;
}
2017-08-04 05:08:52 +00:00
rv = sc_pkcs11_register_mechanism(p11card, new_type);
if (CKR_OK != rv) {
new_type->free_mech_data(new_type->mech_data);
free(new_type);
}
return rv;
}