Merge pull request #618 from frankmorgner/atomic
Implemented atomic transactions for PKCS#11 See discussion here http://opensc.1086184.n5.nabble.com/State-of-stateless-support-td15513.html fixes https://www.opensc-project.org/opensc/ticket/186 fixes #596
This commit is contained in:
commit
2bb0cb2615
|
@ -594,6 +594,27 @@ app opensc-pkcs11 {
|
|||
# Default: false
|
||||
# lock_login = true;
|
||||
|
||||
# By default, interacting with the OpenSC PKCS#11 module may change the
|
||||
# state of the token, e.g. whether a user is logged in or not.
|
||||
#
|
||||
# Thus other users or other applications may change or use the state of
|
||||
# the token unknowingly. Other applications may create signatures
|
||||
# abusing an existing login or they may logout unnoticed.
|
||||
#
|
||||
# With this setting enabled the login state of the token is tracked and
|
||||
# cached (including the PIN). Every transaction is preceeded by
|
||||
# restoring the login state. After every transaction a logout is
|
||||
# performed. This setting by default also enables `lock_login` (see
|
||||
# above) to disable access for other applications during the atomic
|
||||
# transactions.
|
||||
#
|
||||
# Please note that any PIN-pad should be disabled (see `enable_pinpad`
|
||||
# above), because the user would have to input his PIN for every
|
||||
# transaction.
|
||||
#
|
||||
# Default: false
|
||||
# atomic = true;
|
||||
|
||||
# With this setting disabled, the OpenSC PKCS#11 module will initialize
|
||||
# the slots available when the application calls `C_GetSlotList`. With
|
||||
# this setting enabled, the slots will also get initialized when
|
||||
|
|
|
@ -1221,8 +1221,13 @@ cardos_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data,
|
|||
static int
|
||||
cardos_logout(sc_card_t *card)
|
||||
{
|
||||
if (card->type == SC_CARD_TYPE_CARDOS_M4_01 ||
|
||||
card->type == SC_CARD_TYPE_CARDOS_M4_2) {
|
||||
if (card->type == SC_CARD_TYPE_CARDOS_M4_01
|
||||
|| card->type == SC_CARD_TYPE_CARDOS_M4_2
|
||||
|| card->type == SC_CARD_TYPE_CARDOS_M4_2B
|
||||
|| card->type == SC_CARD_TYPE_CARDOS_M4_2C
|
||||
|| card->type == SC_CARD_TYPE_CARDOS_M4_3
|
||||
|| card->type == SC_CARD_TYPE_CARDOS_M4_4
|
||||
|| card->type == SC_CARD_TYPE_CARDOS_V5_0) {
|
||||
sc_apdu_t apdu;
|
||||
int r;
|
||||
sc_path_t path;
|
||||
|
|
|
@ -125,6 +125,7 @@ sc_list_files
|
|||
sc_lock
|
||||
sc_logout
|
||||
sc_make_cache_dir
|
||||
sc_mem_alloc_secure
|
||||
sc_mem_clear
|
||||
sc_mem_reverse
|
||||
sc_match_atr_block
|
||||
|
|
|
@ -34,8 +34,8 @@
|
|||
#include "pkcs15.h"
|
||||
|
||||
static int select_key_file(struct sc_pkcs15_card *p15card,
|
||||
const struct sc_pkcs15_prkey_info *prkey,
|
||||
sc_security_env_t *senv)
|
||||
const struct sc_pkcs15_prkey_info *prkey,
|
||||
sc_security_env_t *senv)
|
||||
{
|
||||
sc_context_t *ctx = p15card->card->ctx;
|
||||
sc_path_t path, file_id;
|
||||
|
@ -49,8 +49,8 @@ static int select_key_file(struct sc_pkcs15_card *p15card,
|
|||
/* TODO: Why file_app may be NULL -- at least 3F00 has to be present?
|
||||
* Check validity of the following assumption. */
|
||||
/* For pkcs15-emulated cards, the file_app may be NULL,
|
||||
in that case we allways assume an absolute path */
|
||||
if (!prkey->path.len && prkey->path.aid.len) {
|
||||
* in that case we allways assume an absolute path */
|
||||
if (!prkey->path.len && prkey->path.aid.len) {
|
||||
/* Private key is a SDO allocated in application DF */
|
||||
path = prkey->path;
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ static int select_key_file(struct sc_pkcs15_card *p15card,
|
|||
senv->file_ref = file_id;
|
||||
senv->flags |= SC_SEC_ENV_FILE_REF_PRESENT;
|
||||
}
|
||||
else if (prkey->path.len > 2) {
|
||||
else if (prkey->path.len > 2) {
|
||||
path = prkey->path;
|
||||
memcpy(file_id.value, prkey->path.value + prkey->path.len - 2, 2);
|
||||
file_id.len = 2;
|
||||
|
@ -70,7 +70,7 @@ static int select_key_file(struct sc_pkcs15_card *p15card,
|
|||
senv->file_ref = file_id;
|
||||
senv->flags |= SC_SEC_ENV_FILE_REF_PRESENT;
|
||||
}
|
||||
else {
|
||||
else {
|
||||
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "invalid private key path");
|
||||
}
|
||||
|
||||
|
@ -79,11 +79,122 @@ static int select_key_file(struct sc_pkcs15_card *p15card,
|
|||
|
||||
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
||||
}
|
||||
|
||||
static int use_key(struct sc_pkcs15_card *p15card,
|
||||
const struct sc_pkcs15_object *obj,
|
||||
sc_security_env_t *senv,
|
||||
int (*card_command)(sc_card_t *card,
|
||||
const u8 * in, size_t inlen,
|
||||
u8 * out, size_t outlen),
|
||||
const u8 * in, size_t inlen, u8 * out, size_t outlen)
|
||||
{
|
||||
int r = SC_SUCCESS;
|
||||
int revalidated_cached_pin = 0;
|
||||
const struct sc_pkcs15_prkey_info *prkey = (const struct sc_pkcs15_prkey_info *) obj->data;
|
||||
|
||||
r = sc_lock(p15card->card);
|
||||
LOG_TEST_RET(p15card->card->ctx, r, "sc_lock() failed");
|
||||
|
||||
do {
|
||||
if (prkey->path.len != 0 || prkey->path.aid.len != 0) {
|
||||
r = select_key_file(p15card, prkey, senv);
|
||||
if (r < 0) {
|
||||
sc_log(p15card->card->ctx,
|
||||
"Unable to select private key file");
|
||||
}
|
||||
}
|
||||
if (r == SC_SUCCESS)
|
||||
r = sc_set_security_env(p15card->card, senv, 0);
|
||||
|
||||
if (r == SC_SUCCESS)
|
||||
r = card_command(p15card->card, in, inlen, out, outlen);
|
||||
|
||||
if (revalidated_cached_pin)
|
||||
/* only re-validate once */
|
||||
break;
|
||||
if (r == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) {
|
||||
r = sc_pkcs15_pincache_revalidate(p15card, obj);
|
||||
if (r < 0)
|
||||
break;
|
||||
revalidated_cached_pin = 1;
|
||||
}
|
||||
} while (revalidated_cached_pin);
|
||||
|
||||
sc_unlock(p15card->card);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int format_senv(struct sc_pkcs15_card *p15card,
|
||||
const struct sc_pkcs15_object *obj,
|
||||
sc_security_env_t *senv_out, sc_algorithm_info_t **alg_info_out)
|
||||
{
|
||||
sc_context_t *ctx = p15card->card->ctx;
|
||||
const struct sc_pkcs15_prkey_info *prkey = (const struct sc_pkcs15_prkey_info *) obj->data;
|
||||
|
||||
memset(senv_out, 0, sizeof(*senv_out));
|
||||
|
||||
/* Card driver should have the access to supported algorithms from 'tokenInfo'. So that
|
||||
* it can get value of card specific 'AlgorithmInfo::algRef'. */
|
||||
memcpy(senv_out->supported_algos, &p15card->tokeninfo->supported_algos, sizeof(senv_out->supported_algos));
|
||||
|
||||
if ((obj->type & SC_PKCS15_TYPE_CLASS_MASK) != SC_PKCS15_TYPE_PRKEY)
|
||||
LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "This is not a private key");
|
||||
|
||||
/* If the key is not native, we can't operate with it. */
|
||||
if (!prkey->native)
|
||||
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "This key is not native, cannot operate with it");
|
||||
|
||||
switch (obj->type) {
|
||||
case SC_PKCS15_TYPE_PRKEY_RSA:
|
||||
*alg_info_out = sc_card_find_rsa_alg(p15card->card, prkey->modulus_length);
|
||||
if (*alg_info_out == NULL) {
|
||||
sc_log(ctx, "Card does not support RSA with key length %d", prkey->modulus_length);
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
senv_out->algorithm = SC_ALGORITHM_RSA;
|
||||
break;
|
||||
|
||||
case SC_PKCS15_TYPE_PRKEY_GOSTR3410:
|
||||
*alg_info_out = sc_card_find_gostr3410_alg(p15card->card, prkey->modulus_length);
|
||||
if (alg_info_out == NULL) {
|
||||
sc_log(ctx, "Card does not support GOSTR3410 with key length %d", prkey->modulus_length);
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
senv_out->algorithm = SC_ALGORITHM_GOSTR3410;
|
||||
break;
|
||||
|
||||
case SC_PKCS15_TYPE_PRKEY_EC:
|
||||
*alg_info_out = sc_card_find_ec_alg(p15card->card, prkey->field_length, NULL);
|
||||
if (*alg_info_out == NULL) {
|
||||
sc_log(ctx, "Card does not support EC with field_size %d", prkey->field_length);
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
senv_out->algorithm = SC_ALGORITHM_EC;
|
||||
|
||||
senv_out->flags |= SC_SEC_ENV_ALG_REF_PRESENT;
|
||||
senv_out->algorithm_ref = prkey->field_length;
|
||||
break;
|
||||
/* add other crypto types here */
|
||||
default:
|
||||
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Key type not supported");
|
||||
}
|
||||
senv_out->flags |= SC_SEC_ENV_ALG_PRESENT;
|
||||
|
||||
/* optional keyReference attribute (the default value is -1) */
|
||||
if (prkey->key_reference >= 0) {
|
||||
senv_out->key_ref_len = 1;
|
||||
senv_out->key_ref[0] = prkey->key_reference & 0xFF;
|
||||
senv_out->flags |= SC_SEC_ENV_KEY_REF_PRESENT;
|
||||
}
|
||||
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card,
|
||||
const struct sc_pkcs15_object *obj,
|
||||
unsigned long flags,
|
||||
const u8 * in, size_t inlen, u8 *out, size_t outlen)
|
||||
const struct sc_pkcs15_object *obj,
|
||||
unsigned long flags,
|
||||
const u8 * in, size_t inlen, u8 *out, size_t outlen)
|
||||
{
|
||||
sc_context_t *ctx = p15card->card->ctx;
|
||||
int r;
|
||||
|
@ -93,80 +204,21 @@ int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card,
|
|||
unsigned long pad_flags = 0, sec_flags = 0;
|
||||
|
||||
LOG_FUNC_CALLED(ctx);
|
||||
|
||||
memset(&senv, 0, sizeof(senv));
|
||||
|
||||
/* Card driver should have the access to supported algorithms from 'tokenInfo'. So that
|
||||
* it can get value of card specific 'AlgorithmInfo::algRef'. */
|
||||
memcpy(&senv.supported_algos, &p15card->tokeninfo->supported_algos, sizeof(senv.supported_algos));
|
||||
|
||||
/* If the key is not native, we can't operate with it. */
|
||||
if (!prkey->native)
|
||||
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "This key is not native, cannot operate with it");
|
||||
|
||||
|
||||
if (!(prkey->usage & (SC_PKCS15_PRKEY_USAGE_DECRYPT|SC_PKCS15_PRKEY_USAGE_UNWRAP)))
|
||||
LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "This key cannot be used for decryption");
|
||||
|
||||
switch (obj->type) {
|
||||
case SC_PKCS15_TYPE_PRKEY_RSA:
|
||||
alg_info = sc_card_find_rsa_alg(p15card->card, prkey->modulus_length);
|
||||
if (alg_info == NULL) {
|
||||
sc_log(ctx, "Card does not support RSA with key length %d", prkey->modulus_length);
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
senv.algorithm = SC_ALGORITHM_RSA;
|
||||
break;
|
||||
|
||||
case SC_PKCS15_TYPE_PRKEY_GOSTR3410:
|
||||
alg_info = sc_card_find_gostr3410_alg(p15card->card, prkey->modulus_length);
|
||||
if (alg_info == NULL) {
|
||||
sc_log(ctx, "Card does not support GOSTR3410 with key length %d", prkey->modulus_length);
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
senv.algorithm = SC_ALGORITHM_GOSTR3410;
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED,"Key type not supported");
|
||||
}
|
||||
r = format_senv(p15card, obj, &senv, &alg_info);
|
||||
LOG_TEST_RET(ctx, r, "Could not initialize security environment");
|
||||
senv.operation = SC_SEC_OPERATION_DECIPHER;
|
||||
|
||||
r = sc_get_encoding_flags(ctx, flags, alg_info->flags, &pad_flags, &sec_flags);
|
||||
LOG_TEST_RET(ctx, r, "cannot encode security operation flags");
|
||||
|
||||
senv.algorithm_flags = sec_flags;
|
||||
senv.operation = SC_SEC_OPERATION_DECIPHER;
|
||||
senv.flags = 0;
|
||||
/* optional keyReference attribute (the default value is -1) */
|
||||
if (prkey->key_reference >= 0) {
|
||||
senv.key_ref_len = 1;
|
||||
senv.key_ref[0] = prkey->key_reference & 0xFF;
|
||||
senv.flags |= SC_SEC_ENV_KEY_REF_PRESENT;
|
||||
}
|
||||
senv.flags |= SC_SEC_ENV_ALG_PRESENT;
|
||||
|
||||
r = sc_lock(p15card->card);
|
||||
LOG_TEST_RET(ctx, r, "sc_lock() failed");
|
||||
|
||||
if (prkey->path.len != 0 || prkey->path.aid.len != 0) {
|
||||
r = select_key_file(p15card, prkey, &senv);
|
||||
if (r < 0) {
|
||||
sc_unlock(p15card->card);
|
||||
LOG_TEST_RET(ctx, r,"Unable to select private key file");
|
||||
}
|
||||
}
|
||||
|
||||
r = sc_set_security_env(p15card->card, &senv, 0);
|
||||
if (r < 0) {
|
||||
sc_unlock(p15card->card);
|
||||
LOG_TEST_RET(ctx, r, "sc_set_security_env() failed");
|
||||
}
|
||||
r = sc_decipher(p15card->card, in, inlen, out, outlen);
|
||||
if (r == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) {
|
||||
if (sc_pkcs15_pincache_revalidate(p15card, obj) == SC_SUCCESS)
|
||||
r = sc_decipher(p15card->card, in, inlen, out, outlen);
|
||||
}
|
||||
sc_unlock(p15card->card);
|
||||
LOG_TEST_RET(ctx, r, "sc_decipher() failed");
|
||||
r = use_key(p15card, obj, &senv, sc_decipher, in, inlen, out,
|
||||
outlen);
|
||||
LOG_TEST_RET(ctx, r, "use_key() failed");
|
||||
|
||||
/* Strip any padding */
|
||||
if (pad_flags & SC_ALGORITHM_RSA_PAD_PKCS1) {
|
||||
|
@ -185,10 +237,10 @@ int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card,
|
|||
* In that case r = 0, and *poutlen = expected size
|
||||
*/
|
||||
int sc_pkcs15_derive(struct sc_pkcs15_card *p15card,
|
||||
const struct sc_pkcs15_object *obj,
|
||||
unsigned long flags,
|
||||
const u8 * in, size_t inlen, u8 *out,
|
||||
unsigned long *poutlen)
|
||||
const struct sc_pkcs15_object *obj,
|
||||
unsigned long flags,
|
||||
const u8 * in, size_t inlen, u8 *out,
|
||||
unsigned long *poutlen)
|
||||
{
|
||||
sc_context_t *ctx = p15card->card->ctx;
|
||||
int r;
|
||||
|
@ -199,81 +251,32 @@ int sc_pkcs15_derive(struct sc_pkcs15_card *p15card,
|
|||
|
||||
LOG_FUNC_CALLED(ctx);
|
||||
|
||||
memset(&senv, 0, sizeof(senv));
|
||||
|
||||
/* Card driver should have the access to supported algorithms from 'tokenInfo'. So that
|
||||
* it can get value of card specific 'AlgorithmInfo::algRef'. */
|
||||
memcpy(&senv.supported_algos, &p15card->tokeninfo->supported_algos, sizeof(senv.supported_algos));
|
||||
|
||||
/* If the key is not native, we can't operate with it. */
|
||||
if (!prkey->native)
|
||||
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "This key is not native, cannot operate with it");
|
||||
|
||||
if (!(prkey->usage & (SC_PKCS15_PRKEY_USAGE_DERIVE)))
|
||||
LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "This key cannot be used for derivation");
|
||||
|
||||
switch (obj->type) {
|
||||
case SC_PKCS15_TYPE_PRKEY_EC:
|
||||
alg_info = sc_card_find_ec_alg(p15card->card, prkey->field_length, NULL);
|
||||
if (alg_info == NULL) {
|
||||
sc_log(ctx, "Card does not support EC with field_size %d", prkey->field_length);
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
if (out == NULL || *poutlen < (prkey->field_length + 7) / 8) {
|
||||
*poutlen = (prkey->field_length + 7) / 8;
|
||||
r = 0; /* say no data to return */
|
||||
goto out;
|
||||
*poutlen = (prkey->field_length + 7) / 8;
|
||||
r = 0; /* say no data to return */
|
||||
LOG_FUNC_RETURN(ctx, r);
|
||||
}
|
||||
|
||||
senv.algorithm = SC_ALGORITHM_EC;
|
||||
senv.flags |= SC_SEC_ENV_ALG_PRESENT;
|
||||
|
||||
senv.flags |= SC_SEC_ENV_ALG_REF_PRESENT;
|
||||
senv.algorithm_ref = prkey->field_length;
|
||||
break;
|
||||
default:
|
||||
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED,"Key type not supported");
|
||||
}
|
||||
|
||||
r = format_senv(p15card, obj, &senv, &alg_info);
|
||||
LOG_TEST_RET(ctx, r, "Could not initialize security environment");
|
||||
senv.operation = SC_SEC_OPERATION_DERIVE;
|
||||
|
||||
r = sc_get_encoding_flags(ctx, flags, alg_info->flags, &pad_flags, &sec_flags);
|
||||
LOG_TEST_RET(ctx, r, "cannot encode security operation flags");
|
||||
|
||||
senv.algorithm_flags = sec_flags;
|
||||
senv.operation = SC_SEC_OPERATION_DERIVE;
|
||||
/* optional keyReference attribute (the default value is -1) */
|
||||
if (prkey->key_reference >= 0) {
|
||||
senv.key_ref_len = 1;
|
||||
senv.key_ref[0] = prkey->key_reference & 0xFF;
|
||||
senv.flags |= SC_SEC_ENV_KEY_REF_PRESENT;
|
||||
}
|
||||
|
||||
r = sc_lock(p15card->card);
|
||||
LOG_TEST_RET(ctx, r, "sc_lock() failed");
|
||||
|
||||
if (prkey->path.len != 0 || prkey->path.aid.len != 0) {
|
||||
r = select_key_file(p15card, prkey, &senv);
|
||||
if (r < 0) {
|
||||
sc_unlock(p15card->card);
|
||||
LOG_TEST_RET(ctx, r,"Unable to select private key file");
|
||||
}
|
||||
}
|
||||
|
||||
r = sc_set_security_env(p15card->card, &senv, 0);
|
||||
if (r < 0) {
|
||||
sc_unlock(p15card->card);
|
||||
LOG_TEST_RET(ctx, r, "sc_set_security_env() failed");
|
||||
}
|
||||
/* TODO Do we need a sc_derive? PIV at least can use the decipher,
|
||||
* senv.operation = SC_SEC_OPERATION_DERIVE;
|
||||
*/
|
||||
r = sc_decipher(p15card->card, in, inlen, out, *poutlen);
|
||||
if (r == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) {
|
||||
if (sc_pkcs15_pincache_revalidate(p15card, obj) == SC_SUCCESS)
|
||||
r = sc_decipher(p15card->card, in, inlen, out, *poutlen);
|
||||
}
|
||||
sc_unlock(p15card->card);
|
||||
LOG_TEST_RET(ctx, r, "sc_decipher/derive() failed");
|
||||
r = use_key(p15card, obj, &senv, sc_decipher, in, inlen, out,
|
||||
*poutlen);
|
||||
LOG_TEST_RET(ctx, r, "use_key() failed");
|
||||
|
||||
/* Strip any padding */
|
||||
if (pad_flags & SC_ALGORITHM_RSA_PAD_PKCS1) {
|
||||
|
@ -283,9 +286,8 @@ int sc_pkcs15_derive(struct sc_pkcs15_card *p15card,
|
|||
}
|
||||
|
||||
/* If card stores derived key on card, then no data is returned
|
||||
* and the key must be used on the card. */
|
||||
* and the key must be used on the card. */
|
||||
*poutlen = r;
|
||||
out:
|
||||
LOG_FUNC_RETURN(ctx, r);
|
||||
}
|
||||
|
||||
|
@ -310,62 +312,25 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
|
|||
unsigned long pad_flags = 0, sec_flags = 0;
|
||||
|
||||
LOG_FUNC_CALLED(ctx);
|
||||
sc_log(ctx, "security operation flags 0x%X", flags);
|
||||
|
||||
memset(&senv, 0, sizeof(senv));
|
||||
|
||||
/* Card driver should have the access to supported algorithms from 'tokenInfo'. So that
|
||||
* it can get value of card specific 'AlgorithmInfo::algRef'. */
|
||||
memcpy(&senv.supported_algos, &p15card->tokeninfo->supported_algos, sizeof(senv.supported_algos));
|
||||
|
||||
if ((obj->type & SC_PKCS15_TYPE_CLASS_MASK) != SC_PKCS15_TYPE_PRKEY)
|
||||
LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "This is not a private key");
|
||||
|
||||
/* If the key is not native, we can't operate with it. */
|
||||
if (!prkey->native)
|
||||
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "This key is not native, cannot operate with it");
|
||||
|
||||
if (!(prkey->usage & (SC_PKCS15_PRKEY_USAGE_SIGN|SC_PKCS15_PRKEY_USAGE_SIGNRECOVER|
|
||||
SC_PKCS15_PRKEY_USAGE_NONREPUDIATION)))
|
||||
SC_PKCS15_PRKEY_USAGE_NONREPUDIATION)))
|
||||
LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "This key cannot be used for signing");
|
||||
|
||||
r = format_senv(p15card, obj, &senv, &alg_info);
|
||||
LOG_TEST_RET(ctx, r, "Could not initialize security environment");
|
||||
senv.operation = SC_SEC_OPERATION_SIGN;
|
||||
|
||||
switch (obj->type) {
|
||||
case SC_PKCS15_TYPE_PRKEY_RSA:
|
||||
modlen = prkey->modulus_length / 8;
|
||||
alg_info = sc_card_find_rsa_alg(p15card->card, prkey->modulus_length);
|
||||
if (alg_info == NULL) {
|
||||
sc_log(ctx, "Card does not support RSA with key length %d", prkey->modulus_length);
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
senv.flags |= SC_SEC_ENV_ALG_PRESENT;
|
||||
senv.algorithm = SC_ALGORITHM_RSA;
|
||||
break;
|
||||
|
||||
case SC_PKCS15_TYPE_PRKEY_GOSTR3410:
|
||||
modlen = (prkey->modulus_length + 7) / 8 * 2;
|
||||
alg_info = sc_card_find_gostr3410_alg(p15card->card, prkey->modulus_length);
|
||||
if (alg_info == NULL) {
|
||||
sc_log(ctx, "Card does not support GOSTR3410 with key length %d", prkey->modulus_length);
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
senv.flags |= SC_SEC_ENV_ALG_PRESENT;
|
||||
senv.algorithm = SC_ALGORITHM_GOSTR3410;
|
||||
break;
|
||||
|
||||
case SC_PKCS15_TYPE_PRKEY_EC:
|
||||
modlen = ((prkey->field_length +7) / 8) * 2; /* 2*nLen */
|
||||
alg_info = sc_card_find_ec_alg(p15card->card, prkey->field_length, NULL);
|
||||
if (alg_info == NULL) {
|
||||
sc_log(ctx, "Card does not support EC with field_size %d", prkey->field_length);
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
senv.algorithm = SC_ALGORITHM_EC;
|
||||
senv.flags |= SC_SEC_ENV_ALG_PRESENT;
|
||||
|
||||
senv.flags |= SC_SEC_ENV_ALG_REF_PRESENT;
|
||||
senv.algorithm_ref = prkey->field_length;
|
||||
break;
|
||||
/* add other crypto types here */
|
||||
default:
|
||||
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Key type not supported");
|
||||
}
|
||||
|
@ -389,7 +354,7 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
|
|||
* senv.algorithm_flags: what the card will have to do */
|
||||
|
||||
/* if the card has SC_ALGORITHM_NEED_USAGE set, and the
|
||||
key is for signing and decryption, we need to emulate signing */
|
||||
* key is for signing and decryption, we need to emulate signing */
|
||||
/* TODO: -DEE assume only RSA keys will ever use _NEED_USAGE */
|
||||
|
||||
sc_log(ctx, "supported algorithm flags 0x%X, private key usage 0x%X", alg_info->flags, prkey->usage);
|
||||
|
@ -421,7 +386,7 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
|
|||
/* If the card doesn't support the requested algorithm, see if we
|
||||
* can strip the input so a more restrictive algo can be used */
|
||||
if ((flags == (SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE)) &&
|
||||
!(alg_info->flags & (SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_HASH_NONE))) {
|
||||
!(alg_info->flags & (SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_HASH_NONE))) {
|
||||
unsigned int algo;
|
||||
size_t tmplen = sizeof(buf);
|
||||
|
||||
|
@ -466,41 +431,10 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
|
|||
inlen = modlen;
|
||||
}
|
||||
|
||||
senv.operation = SC_SEC_OPERATION_SIGN;
|
||||
|
||||
/* optional keyReference attribute (the default value is -1) */
|
||||
if (prkey->key_reference >= 0) {
|
||||
senv.key_ref_len = 1;
|
||||
senv.key_ref[0] = prkey->key_reference & 0xFF;
|
||||
senv.flags |= SC_SEC_ENV_KEY_REF_PRESENT;
|
||||
}
|
||||
|
||||
r = sc_lock(p15card->card);
|
||||
LOG_TEST_RET(ctx, r, "sc_lock() failed");
|
||||
|
||||
sc_log(ctx, "Private key path '%s'", sc_print_path(&prkey->path));
|
||||
if (prkey->path.len != 0 || prkey->path.aid.len != 0) {
|
||||
r = select_key_file(p15card, prkey, &senv);
|
||||
if (r < 0) {
|
||||
sc_unlock(p15card->card);
|
||||
LOG_TEST_RET(ctx, r,"Unable to select private key file");
|
||||
}
|
||||
}
|
||||
|
||||
r = sc_set_security_env(p15card->card, &senv, 0);
|
||||
if (r < 0) {
|
||||
sc_unlock(p15card->card);
|
||||
LOG_TEST_RET(ctx, r, "sc_set_security_env() failed");
|
||||
}
|
||||
|
||||
r = sc_compute_signature(p15card->card, tmp, inlen, out, outlen);
|
||||
if (r == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED)
|
||||
if (sc_pkcs15_pincache_revalidate(p15card, obj) == SC_SUCCESS)
|
||||
r = sc_compute_signature(p15card->card, tmp, inlen, out, outlen);
|
||||
|
||||
r = use_key(p15card, obj, &senv, sc_compute_signature, tmp, inlen,
|
||||
out, outlen);
|
||||
LOG_TEST_RET(ctx, r, "use_key() failed");
|
||||
sc_mem_clear(buf, sizeof(buf));
|
||||
sc_unlock(p15card->card);
|
||||
LOG_TEST_RET(ctx, r, "sc_compute_signature() failed");
|
||||
|
||||
LOG_FUNC_RETURN(ctx, r);
|
||||
}
|
||||
|
|
|
@ -127,6 +127,121 @@ CK_RV sc_to_cryptoki_error(int rc, const char *ctx)
|
|||
}
|
||||
|
||||
|
||||
struct sc_pkcs11_login {
|
||||
CK_USER_TYPE userType;
|
||||
CK_CHAR_PTR pPin;
|
||||
CK_ULONG ulPinLen;
|
||||
};
|
||||
|
||||
CK_RV restore_login_state(struct sc_pkcs11_slot *slot)
|
||||
{
|
||||
CK_RV r = CKR_OK;
|
||||
|
||||
if (sc_pkcs11_conf.atomic && slot) {
|
||||
if (list_iterator_start(&slot->logins)) {
|
||||
struct sc_pkcs11_login *login = list_iterator_next(&slot->logins);
|
||||
while (login) {
|
||||
r = slot->p11card->framework->login(slot, login->userType,
|
||||
login->pPin, login->ulPinLen);
|
||||
if (r != CKR_OK)
|
||||
break;
|
||||
login = list_iterator_next(&slot->logins);
|
||||
}
|
||||
list_iterator_stop(&slot->logins);
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
CK_RV reset_login_state(struct sc_pkcs11_slot *slot, CK_RV rv)
|
||||
{
|
||||
if (slot) {
|
||||
if (sc_pkcs11_conf.atomic
|
||||
&& slot->p11card && slot->p11card->framework) {
|
||||
slot->p11card->framework->logout(slot);
|
||||
}
|
||||
|
||||
if (rv == CKR_USER_NOT_LOGGED_IN) {
|
||||
slot->login_user = -1;
|
||||
pop_all_login_states(slot);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
CK_RV push_login_state(struct sc_pkcs11_slot *slot,
|
||||
CK_USER_TYPE userType, CK_CHAR_PTR pPin, CK_ULONG ulPinLen)
|
||||
{
|
||||
CK_RV r = CKR_HOST_MEMORY;
|
||||
struct sc_pkcs11_login *login = NULL;
|
||||
|
||||
if (!sc_pkcs11_conf.atomic || !slot) {
|
||||
r = CKR_OK;
|
||||
goto err;
|
||||
}
|
||||
|
||||
login = (struct sc_pkcs11_login *) malloc(sizeof *login);
|
||||
if (login == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
login->pPin = sc_mem_alloc_secure(context, (sizeof *pPin)*ulPinLen);
|
||||
if (login->pPin == NULL) {
|
||||
goto err;
|
||||
}
|
||||
memcpy(login->pPin, pPin, (sizeof *pPin)*ulPinLen);
|
||||
login->ulPinLen = ulPinLen;
|
||||
login->userType = userType;
|
||||
|
||||
if (0 > list_append(&slot->logins, login)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = CKR_OK;
|
||||
|
||||
err:
|
||||
if (r != CKR_OK && login) {
|
||||
sc_mem_clear(login->pPin, login->ulPinLen);
|
||||
free(login->pPin);
|
||||
free(login);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void pop_login_state(struct sc_pkcs11_slot *slot)
|
||||
{
|
||||
if (slot) {
|
||||
unsigned int size = list_size(&slot->logins);
|
||||
if (size > 0) {
|
||||
struct sc_pkcs11_login *login = list_get_at(&slot->logins, size-1);
|
||||
if (login) {
|
||||
sc_mem_clear(login->pPin, login->ulPinLen);
|
||||
free(login->pPin);
|
||||
free(login);
|
||||
}
|
||||
if (0 > list_delete_at(&slot->logins, size-1))
|
||||
sc_log(context, "Error deleting login state");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pop_all_login_states(struct sc_pkcs11_slot *slot)
|
||||
{
|
||||
if (sc_pkcs11_conf.atomic && slot) {
|
||||
struct sc_pkcs11_login *login = list_fetch(&slot->logins);
|
||||
while (login) {
|
||||
sc_mem_clear(login->pPin, login->ulPinLen);
|
||||
free(login->pPin);
|
||||
free(login);
|
||||
login = list_fetch(&slot->logins);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Session manipulation */
|
||||
CK_RV session_start_operation(struct sc_pkcs11_session * session,
|
||||
int type, sc_pkcs11_mechanism_type_t * mech, struct sc_pkcs11_operation ** operation)
|
||||
|
@ -323,6 +438,7 @@ void load_pkcs11_parameters(struct sc_pkcs11_config *conf, sc_context_t * ctx)
|
|||
conf->slots_per_card = 4;
|
||||
}
|
||||
conf->hide_empty_tokens = 1;
|
||||
conf->atomic = 0;
|
||||
conf->lock_login = 0;
|
||||
conf->init_sloppy = 1;
|
||||
conf->pin_unblock_style = SC_PKCS11_PIN_UNBLOCK_NOT_ALLOWED;
|
||||
|
@ -339,6 +455,9 @@ void load_pkcs11_parameters(struct sc_pkcs11_config *conf, sc_context_t * ctx)
|
|||
conf->max_virtual_slots = scconf_get_int(conf_block, "max_virtual_slots", conf->max_virtual_slots);
|
||||
conf->slots_per_card = scconf_get_int(conf_block, "slots_per_card", conf->slots_per_card);
|
||||
conf->hide_empty_tokens = scconf_get_bool(conf_block, "hide_empty_tokens", conf->hide_empty_tokens);
|
||||
conf->atomic = scconf_get_bool(conf_block, "atomic", conf->atomic);
|
||||
if (conf->atomic)
|
||||
conf->lock_login = 1;
|
||||
conf->lock_login = scconf_get_bool(conf_block, "lock_login", conf->lock_login);
|
||||
conf->init_sloppy = scconf_get_bool(conf_block, "init_sloppy", conf->init_sloppy);
|
||||
|
||||
|
@ -371,9 +490,9 @@ void load_pkcs11_parameters(struct sc_pkcs11_config *conf, sc_context_t * ctx)
|
|||
free(tmp);
|
||||
|
||||
sc_log(ctx, "PKCS#11 options: plug_and_play=%d max_virtual_slots=%d slots_per_card=%d "
|
||||
"hide_empty_tokens=%d lock_login=%d pin_unblock_style=%d "
|
||||
"hide_empty_tokens=%d lock_login=%d atomic=%d pin_unblock_style=%d "
|
||||
"zero_ckaid_for_ca_certs=%d create_slots_flags=0x%X",
|
||||
conf->plug_and_play, conf->max_virtual_slots, conf->slots_per_card,
|
||||
conf->hide_empty_tokens, conf->lock_login, conf->pin_unblock_style,
|
||||
conf->hide_empty_tokens, conf->lock_login, conf->atomic, conf->pin_unblock_style,
|
||||
conf->zero_ckaid_for_ca_certs, conf->create_slots_flags);
|
||||
}
|
||||
|
|
|
@ -324,6 +324,8 @@ CK_RV C_Finalize(CK_VOID_PTR pReserved)
|
|||
|
||||
while ((slot = list_fetch(&virtual_slots))) {
|
||||
list_destroy(&slot->objects);
|
||||
pop_all_login_states(slot);
|
||||
list_destroy(&slot->logins);
|
||||
free(slot);
|
||||
}
|
||||
list_destroy(&virtual_slots);
|
||||
|
|
|
@ -541,7 +541,8 @@ C_Digest(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
if (rv == CKR_OK)
|
||||
rv = sc_pkcs11_md_final(session, pDigest, pulDigestLen);
|
||||
|
||||
out: sc_log(context, "C_Digest() = %s", lookup_enum ( RV_T, rv ));
|
||||
out:
|
||||
sc_log(context, "C_Digest() = %s", lookup_enum ( RV_T, rv ));
|
||||
sc_pkcs11_unlock();
|
||||
return rv;
|
||||
}
|
||||
|
@ -685,8 +686,12 @@ C_Sign(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
}
|
||||
|
||||
rv = sc_pkcs11_sign_update(session, pData, ulDataLen);
|
||||
if (rv == CKR_OK)
|
||||
rv = sc_pkcs11_sign_final(session, pSignature, pulSignatureLen);
|
||||
if (rv == CKR_OK) {
|
||||
rv = restore_login_state(session->slot);
|
||||
if (rv == CKR_OK)
|
||||
rv = sc_pkcs11_sign_final(session, pSignature, pulSignatureLen);
|
||||
rv = reset_login_state(session->slot, rv);
|
||||
}
|
||||
|
||||
out:
|
||||
sc_log(context, "C_Sign() = %s", lookup_enum ( RV_T, rv ));
|
||||
|
@ -746,7 +751,10 @@ C_SignFinal(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
*pulSignatureLen = length;
|
||||
rv = pSignature ? CKR_BUFFER_TOO_SMALL : CKR_OK;
|
||||
} else {
|
||||
rv = sc_pkcs11_sign_final(session, pSignature, pulSignatureLen);
|
||||
rv = restore_login_state(session->slot);
|
||||
if (rv == CKR_OK)
|
||||
rv = sc_pkcs11_sign_final(session, pSignature, pulSignatureLen);
|
||||
rv = reset_login_state(session->slot, rv);
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -859,7 +867,8 @@ CK_RV C_DecryptInit(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
|
||||
rv = sc_pkcs11_decr_init(session, pMechanism, object, key_type);
|
||||
|
||||
out: sc_log(context, "C_DecryptInit() = %s", lookup_enum ( RV_T, rv ));
|
||||
out:
|
||||
sc_log(context, "C_DecryptInit() = %s", lookup_enum ( RV_T, rv ));
|
||||
sc_pkcs11_unlock();
|
||||
return rv;
|
||||
}
|
||||
|
@ -878,9 +887,14 @@ CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
return rv;
|
||||
|
||||
rv = get_session(hSession, &session);
|
||||
if (rv == CKR_OK)
|
||||
rv = sc_pkcs11_decr(session, pEncryptedData, ulEncryptedDataLen,
|
||||
pData, pulDataLen);
|
||||
if (rv == CKR_OK) {
|
||||
rv = restore_login_state(session->slot);
|
||||
if (rv == CKR_OK) {
|
||||
rv = sc_pkcs11_decr(session, pEncryptedData,
|
||||
ulEncryptedDataLen, pData, pulDataLen);
|
||||
}
|
||||
rv = reset_login_state(session->slot, rv);
|
||||
}
|
||||
|
||||
sc_log(context, "C_Decrypt() = %s", lookup_enum ( RV_T, rv ));
|
||||
sc_pkcs11_unlock();
|
||||
|
@ -985,11 +999,15 @@ CK_RV C_GenerateKeyPair(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
slot = session->slot;
|
||||
if (slot->p11card->framework->gen_keypair == NULL)
|
||||
rv = CKR_FUNCTION_NOT_SUPPORTED;
|
||||
else
|
||||
rv = slot->p11card->framework->gen_keypair(slot, pMechanism,
|
||||
pPublicKeyTemplate, ulPublicKeyAttributeCount,
|
||||
pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
|
||||
phPublicKey, phPrivateKey);
|
||||
else {
|
||||
rv = restore_login_state(slot);
|
||||
if (rv == CKR_OK)
|
||||
rv = slot->p11card->framework->gen_keypair(slot, pMechanism,
|
||||
pPublicKeyTemplate, ulPublicKeyAttributeCount,
|
||||
pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
|
||||
phPublicKey, phPrivateKey);
|
||||
rv = reset_login_state(session->slot, rv);
|
||||
}
|
||||
|
||||
out:
|
||||
sc_pkcs11_unlock();
|
||||
|
@ -1084,9 +1102,12 @@ CK_RV C_DeriveKey(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
goto out;
|
||||
}
|
||||
|
||||
rv = sc_pkcs11_deri(session, pMechanism, object, key_type,
|
||||
hSession, *phKey, key_object);
|
||||
rv = restore_login_state(session->slot);
|
||||
if (rv == CKR_OK)
|
||||
rv = sc_pkcs11_deri(session, pMechanism, object, key_type,
|
||||
hSession, *phKey, key_object);
|
||||
/* TODO if (rv != CK_OK) need to destroy the object */
|
||||
rv = reset_login_state(session->slot, rv);
|
||||
|
||||
break;
|
||||
default:
|
||||
|
@ -1175,7 +1196,8 @@ CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
|
||||
rv = sc_pkcs11_verif_init(session, pMechanism, object, key_type);
|
||||
|
||||
out: sc_log(context, "C_VerifyInit() = %s", lookup_enum ( RV_T, rv ));
|
||||
out:
|
||||
sc_log(context, "C_VerifyInit() = %s", lookup_enum ( RV_T, rv ));
|
||||
sc_pkcs11_unlock();
|
||||
return rv;
|
||||
#endif
|
||||
|
@ -1202,10 +1224,15 @@ CK_RV C_Verify(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
goto out;
|
||||
|
||||
rv = sc_pkcs11_verif_update(session, pData, ulDataLen);
|
||||
if (rv == CKR_OK)
|
||||
rv = sc_pkcs11_verif_final(session, pSignature, ulSignatureLen);
|
||||
if (rv == CKR_OK) {
|
||||
rv = restore_login_state(session->slot);
|
||||
if (rv == CKR_OK)
|
||||
rv = sc_pkcs11_verif_final(session, pSignature, ulSignatureLen);
|
||||
rv = reset_login_state(session->slot, rv);
|
||||
}
|
||||
|
||||
out: sc_log(context, "C_Verify() = %s", lookup_enum ( RV_T, rv ));
|
||||
out:
|
||||
sc_log(context, "C_Verify() = %s", lookup_enum ( RV_T, rv ));
|
||||
sc_pkcs11_unlock();
|
||||
return rv;
|
||||
#endif
|
||||
|
@ -1250,8 +1277,12 @@ CK_RV C_VerifyFinal(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
return rv;
|
||||
|
||||
rv = get_session(hSession, &session);
|
||||
if (rv == CKR_OK)
|
||||
rv = sc_pkcs11_verif_final(session, pSignature, ulSignatureLen);
|
||||
if (rv == CKR_OK) {
|
||||
rv = restore_login_state(session->slot);
|
||||
if (rv == CKR_OK)
|
||||
rv = sc_pkcs11_verif_final(session, pSignature, ulSignatureLen);
|
||||
rv = reset_login_state(session->slot, rv);
|
||||
}
|
||||
|
||||
sc_log(context, "C_VerifyFinal() = %s", lookup_enum ( RV_T, rv ));
|
||||
sc_pkcs11_unlock();
|
||||
|
|
|
@ -107,7 +107,10 @@ static CK_RV sc_pkcs11_close_session(CK_SESSION_HANDLE hSession)
|
|||
slot->nsessions--;
|
||||
if (slot->nsessions == 0 && slot->login_user >= 0) {
|
||||
slot->login_user = -1;
|
||||
slot->p11card->framework->logout(slot);
|
||||
if (sc_pkcs11_conf.atomic)
|
||||
pop_all_login_states(slot);
|
||||
else
|
||||
slot->p11card->framework->logout(slot);
|
||||
}
|
||||
|
||||
if (list_delete(&sessions, session) != 0)
|
||||
|
@ -166,7 +169,8 @@ CK_RV C_CloseAllSessions(CK_SLOT_ID slotID)
|
|||
|
||||
rv = sc_pkcs11_close_all_sessions(slotID);
|
||||
|
||||
out:sc_pkcs11_unlock();
|
||||
out:
|
||||
sc_pkcs11_unlock();
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -269,10 +273,12 @@ CK_RV C_Login(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
if (userType == CKU_CONTEXT_SPECIFIC) {
|
||||
if (slot->login_user == -1) {
|
||||
rv = CKR_OPERATION_NOT_INITIALIZED;
|
||||
goto out;
|
||||
}
|
||||
else {
|
||||
rv = slot->p11card->framework->login(slot, userType, pPin, ulPinLen);
|
||||
rv = restore_login_state(slot);
|
||||
if (rv == CKR_OK)
|
||||
rv = slot->p11card->framework->login(slot, userType, pPin, ulPinLen);
|
||||
rv = reset_login_state(slot, rv);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -285,11 +291,18 @@ CK_RV C_Login(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
goto out;
|
||||
}
|
||||
|
||||
sc_log(context, "C_Login() userType %li", userType);
|
||||
rv = slot->p11card->framework->login(slot, userType, pPin, ulPinLen);
|
||||
sc_log(context, "fLogin() rv %li", rv);
|
||||
rv = restore_login_state(slot);
|
||||
if (rv == CKR_OK) {
|
||||
sc_log(context, "C_Login() userType %li", userType);
|
||||
rv = slot->p11card->framework->login(slot, userType, pPin, ulPinLen);
|
||||
sc_log(context, "fLogin() rv %li", rv);
|
||||
}
|
||||
if (rv == CKR_OK)
|
||||
rv = push_login_state(slot, userType, pPin, ulPinLen);
|
||||
if (rv == CKR_OK) {
|
||||
slot->login_user = userType;
|
||||
}
|
||||
rv = reset_login_state(slot, rv);
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -319,11 +332,15 @@ CK_RV C_Logout(CK_SESSION_HANDLE hSession)
|
|||
|
||||
if (slot->login_user >= 0) {
|
||||
slot->login_user = -1;
|
||||
rv = slot->p11card->framework->logout(slot);
|
||||
if (sc_pkcs11_conf.atomic)
|
||||
pop_all_login_states(slot);
|
||||
else
|
||||
rv = slot->p11card->framework->logout(slot);
|
||||
} else
|
||||
rv = CKR_USER_NOT_LOGGED_IN;
|
||||
|
||||
out:sc_pkcs11_unlock();
|
||||
out:
|
||||
sc_pkcs11_unlock();
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -358,8 +375,12 @@ CK_RV C_InitPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pPin, CK_ULONG ulPinLen)
|
|||
} else if (slot->p11card->framework->init_pin == NULL) {
|
||||
rv = CKR_FUNCTION_NOT_SUPPORTED;
|
||||
} else {
|
||||
rv = slot->p11card->framework->init_pin(slot, pPin, ulPinLen);
|
||||
sc_log(context, "C_InitPIN() init-pin result %li", rv);
|
||||
rv = restore_login_state(slot);
|
||||
if (rv == CKR_OK) {
|
||||
rv = slot->p11card->framework->init_pin(slot, pPin, ulPinLen);
|
||||
sc_log(context, "C_InitPIN() init-pin result %li", rv);
|
||||
}
|
||||
rv = reset_login_state(slot, rv);
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -395,7 +416,11 @@ CK_RV C_SetPIN(CK_SESSION_HANDLE hSession,
|
|||
goto out;
|
||||
}
|
||||
|
||||
rv = slot->p11card->framework->change_pin(slot, pOldPin, ulOldLen, pNewPin, ulNewLen);
|
||||
rv = restore_login_state(slot);
|
||||
if (rv == CKR_OK)
|
||||
rv = slot->p11card->framework->change_pin(slot, pOldPin, ulOldLen, pNewPin, ulNewLen);
|
||||
rv = reset_login_state(slot, rv);
|
||||
|
||||
out:
|
||||
sc_pkcs11_unlock();
|
||||
return rv;
|
||||
|
|
|
@ -78,6 +78,7 @@ struct sc_pkcs11_config {
|
|||
unsigned int slots_per_card;
|
||||
unsigned char hide_empty_tokens;
|
||||
unsigned char lock_login;
|
||||
unsigned char atomic;
|
||||
unsigned char init_sloppy;
|
||||
unsigned int pin_unblock_style;
|
||||
unsigned int create_puk_slot;
|
||||
|
@ -218,6 +219,7 @@ struct sc_pkcs11_slot {
|
|||
|
||||
int fw_data_idx; /* Index of framework data */
|
||||
struct sc_app_info *app_info; /* Application assosiated to slot */
|
||||
list_t logins; /* tracks all calls to C_Login if atomic operations are requested */
|
||||
};
|
||||
typedef struct sc_pkcs11_slot sc_pkcs11_slot_t;
|
||||
|
||||
|
@ -348,6 +350,14 @@ CK_RV slot_token_removed(CK_SLOT_ID id);
|
|||
CK_RV slot_allocate(struct sc_pkcs11_slot **, struct sc_pkcs11_card *);
|
||||
CK_RV slot_find_changed(CK_SLOT_ID_PTR idp, int mask);
|
||||
|
||||
/* Login tracking functions */
|
||||
CK_RV restore_login_state(struct sc_pkcs11_slot *slot);
|
||||
CK_RV reset_login_state(struct sc_pkcs11_slot *slot, CK_RV rv);
|
||||
CK_RV push_login_state(struct sc_pkcs11_slot *slot,
|
||||
CK_USER_TYPE userType, CK_CHAR_PTR pPin, CK_ULONG ulPinLen);
|
||||
void pop_login_state(struct sc_pkcs11_slot *slot);
|
||||
void pop_all_login_states(struct sc_pkcs11_slot *slot);
|
||||
|
||||
/* Session manipulation */
|
||||
CK_RV get_session(CK_SESSION_HANDLE hSession, struct sc_pkcs11_session ** session);
|
||||
CK_RV session_start_operation(struct sc_pkcs11_session *,
|
||||
|
|
|
@ -92,6 +92,8 @@ CK_RV create_slot(sc_reader_t *reader)
|
|||
list_init(&slot->objects);
|
||||
list_attributes_seeker(&slot->objects, object_list_seeker);
|
||||
|
||||
list_init(&slot->logins);
|
||||
|
||||
init_slot_info(&slot->slot_info);
|
||||
if (reader != NULL) {
|
||||
slot->reader = reader;
|
||||
|
|
Loading…
Reference in New Issue