- improved file selection on Cryptoflex cards
- fixed an incompatability in PKCS #11 module git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@178 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
d9792242cc
commit
f1582007f6
|
@ -168,85 +168,101 @@ static int parse_flex_sf_reply(struct sc_context *ctx, const u8 *buf, int buflen
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int flex_select_file(struct sc_card *card, const struct sc_path *path,
|
||||
struct sc_file *file)
|
||||
static int check_path(struct sc_card *card, const u8 **pathptr, size_t *pathlen,
|
||||
int need_info)
|
||||
{
|
||||
const u8 *curptr = card->cache.current_path.value;
|
||||
const u8 *ptr = *pathptr;
|
||||
size_t curlen = card->cache.current_path.len;
|
||||
size_t len = *pathlen;
|
||||
|
||||
if (curlen < 2)
|
||||
return 0;
|
||||
if (len < 2)
|
||||
return 0;
|
||||
if (memcmp(ptr, "\x3F\x00", 2) != 0) {
|
||||
/* Skip the MF id */
|
||||
curptr += 2;
|
||||
curlen -= 2;
|
||||
}
|
||||
if (len == curlen && memcmp(ptr, curptr, len) == 0) {
|
||||
if (need_info)
|
||||
return 0;
|
||||
*pathptr = ptr + len;
|
||||
*pathlen = 0;
|
||||
return 1;
|
||||
}
|
||||
if (curlen < len && memcmp(ptr, curptr, curlen) == 0) {
|
||||
*pathptr = ptr + curlen;
|
||||
*pathlen = len - curlen;
|
||||
return 1;
|
||||
}
|
||||
/* FIXME: Build additional logic */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cache_path(struct sc_card *card, const struct sc_path *path)
|
||||
{
|
||||
struct sc_path *curpath = &card->cache.current_path;
|
||||
|
||||
switch (path->type) {
|
||||
case SC_PATH_TYPE_FILE_ID:
|
||||
if (path->value[0] == 0x3F && path->value[1] == 0x00)
|
||||
sc_format_path("3F00", curpath);
|
||||
else {
|
||||
if (curpath->len + 2 > SC_MAX_PATH_SIZE) {
|
||||
curpath->len = 0;
|
||||
return;
|
||||
}
|
||||
memcpy(curpath->value + curpath->len, path->value, 2);
|
||||
curpath->len += 2;
|
||||
}
|
||||
break;
|
||||
case SC_PATH_TYPE_PATH:
|
||||
curpath->len = 0;
|
||||
if (path->value[0] != 0x3F || path->value[1] != 0)
|
||||
sc_format_path("3F00", curpath);
|
||||
if (curpath->len + path->len > SC_MAX_PATH_SIZE) {
|
||||
curpath->len = 0;
|
||||
return;
|
||||
}
|
||||
memcpy(curpath->value + curpath->len, path->value, path->len);
|
||||
curpath->len += path->len;
|
||||
break;
|
||||
case SC_PATH_TYPE_DF_NAME:
|
||||
/* All bets are off */
|
||||
curpath->len = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int select_file_id(struct sc_card *card, const u8 *buf, size_t buflen,
|
||||
u8 p1, struct sc_file *file)
|
||||
{
|
||||
int r, i;
|
||||
struct sc_apdu apdu;
|
||||
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||
const u8 *pathptr = path->value;
|
||||
size_t pathlen = path->len;
|
||||
int locked = 0;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 3);
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 0, 0);
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, p1, 0);
|
||||
apdu.resp = rbuf;
|
||||
apdu.resplen = sizeof(rbuf);
|
||||
apdu.p1 = apdu.p2 = 0;
|
||||
apdu.datalen = buflen;
|
||||
apdu.data = buf;
|
||||
apdu.lc = buflen;
|
||||
|
||||
switch (path->type) {
|
||||
case SC_PATH_TYPE_PATH:
|
||||
if ((pathlen & 1) != 0) /* not divisible by 2 */
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
if (pathlen != 2 || memcmp(pathptr, "\x3F\x00", 2) != 0) {
|
||||
struct sc_path tmppath;
|
||||
|
||||
locked = 1;
|
||||
r = sc_lock(card);
|
||||
SC_TEST_RET(card->ctx, r, "sc_lock() failed");
|
||||
if (memcmp(pathptr, "\x3F\x00", 2) != 0) {
|
||||
sc_format_path("I3F00", &tmppath);
|
||||
r = flex_select_file(card, &tmppath, NULL);
|
||||
if (r)
|
||||
sc_unlock(card);
|
||||
SC_TEST_RET(card->ctx, r, "Unable to select Master File (MF)");
|
||||
}
|
||||
while (pathlen > 2) {
|
||||
memcpy(tmppath.value, pathptr, 2);
|
||||
tmppath.len = 2;
|
||||
r = flex_select_file(card, &tmppath, NULL);
|
||||
if (r)
|
||||
sc_unlock(card);
|
||||
SC_TEST_RET(card->ctx, r, "Unable to select DF");
|
||||
pathptr += 2;
|
||||
pathlen -= 2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SC_PATH_TYPE_DF_NAME:
|
||||
apdu.p1 = 0x04;
|
||||
break;
|
||||
case SC_PATH_TYPE_FILE_ID:
|
||||
if ((pathlen & 1) != 0)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
break;
|
||||
}
|
||||
apdu.datalen = pathlen;
|
||||
apdu.data = pathptr;
|
||||
apdu.lc = pathlen;
|
||||
|
||||
/* No need to get file information, if file is NULL or already
|
||||
* valid. */
|
||||
#if 0
|
||||
if (file == NULL || sc_file_valid(file))
|
||||
#endif
|
||||
/* No need to get file information, if file is NULL. */
|
||||
if (file == NULL)
|
||||
apdu.resplen = 0;
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
if (locked)
|
||||
sc_unlock(card);
|
||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||
r = sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2);
|
||||
SC_TEST_RET(card->ctx, r, "Card returned error");
|
||||
#if 0
|
||||
if (file == NULL || sc_file_valid(file))
|
||||
#endif
|
||||
|
||||
if (file == NULL)
|
||||
return 0;
|
||||
|
||||
if (apdu.resplen < 14)
|
||||
return SC_ERROR_UNKNOWN_REPLY;
|
||||
|
||||
if (apdu.resp[0] == 0x6F) {
|
||||
error(card->ctx, "unsupported: card returned FCI\n");
|
||||
return SC_ERROR_UNKNOWN_REPLY; /* FIXME */
|
||||
|
@ -257,6 +273,61 @@ static int flex_select_file(struct sc_card *card, const struct sc_path *path,
|
|||
file->acl[i] = SC_AC_UNKNOWN;
|
||||
|
||||
return parse_flex_sf_reply(card->ctx, apdu.resp, apdu.resplen, file);
|
||||
|
||||
}
|
||||
|
||||
static int flex_select_file(struct sc_card *card, const struct sc_path *path,
|
||||
struct sc_file *file)
|
||||
{
|
||||
int r;
|
||||
const u8 *pathptr = path->value;
|
||||
size_t pathlen = path->len;
|
||||
int locked = 0, magic_done;
|
||||
u8 p1 = 0;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, 3);
|
||||
switch (path->type) {
|
||||
case SC_PATH_TYPE_PATH:
|
||||
if ((pathlen & 1) != 0) /* not divisible by 2 */
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
magic_done = check_path(card, &pathptr, &pathlen, file != NULL);
|
||||
if (pathlen == 0)
|
||||
return 0;
|
||||
if (pathlen != 2 || memcmp(pathptr, "\x3F\x00", 2) != 0) {
|
||||
locked = 1;
|
||||
r = sc_lock(card);
|
||||
SC_TEST_RET(card->ctx, r, "sc_lock() failed");
|
||||
if (!magic_done && memcmp(pathptr, "\x3F\x00", 2) != 0) {
|
||||
r = select_file_id(card, "\x3F\x00", 2, 0, NULL);
|
||||
if (r)
|
||||
sc_unlock(card);
|
||||
SC_TEST_RET(card->ctx, r, "Unable to select Master File (MF)");
|
||||
}
|
||||
while (pathlen > 2) {
|
||||
r = select_file_id(card, pathptr, 2, 0, NULL);
|
||||
if (r)
|
||||
sc_unlock(card);
|
||||
SC_TEST_RET(card->ctx, r, "Unable to select DF");
|
||||
pathptr += 2;
|
||||
pathlen -= 2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SC_PATH_TYPE_DF_NAME:
|
||||
p1 = 0x04;
|
||||
break;
|
||||
case SC_PATH_TYPE_FILE_ID:
|
||||
if (pathlen != 2)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
break;
|
||||
}
|
||||
r = select_file_id(card, pathptr, pathlen, p1, file);
|
||||
if (locked)
|
||||
sc_unlock(card);
|
||||
if (r)
|
||||
return r;
|
||||
cache_path(card, path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int flex_list_files(struct sc_card *card, u8 *buf, size_t buflen)
|
||||
|
@ -448,7 +519,10 @@ static int flex_create_file(struct sc_card *card, struct sc_file *file)
|
|||
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
|
||||
return sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2);
|
||||
r = sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2);
|
||||
SC_TEST_RET(card->ctx, r, "Card returned error");
|
||||
card->cache.current_path.len = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int flex_set_security_env(struct sc_card *card,
|
||||
|
|
|
@ -669,6 +669,20 @@ int sc_select_file(struct sc_card *card,
|
|||
int r;
|
||||
|
||||
assert(card != NULL && in_path != NULL);
|
||||
if (in_path->len > SC_MAX_PATH_SIZE)
|
||||
SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_INVALID_ARGUMENTS);
|
||||
if (in_path->type == SC_PATH_TYPE_PATH) {
|
||||
/* Perform a sanity check */
|
||||
int i;
|
||||
if ((in_path->len & 1) != 0)
|
||||
SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_INVALID_ARGUMENTS);
|
||||
for (i = 0; i < in_path->len/2; i++) {
|
||||
u8 p1 = in_path->value[2*i],
|
||||
p2 = in_path->value[2*i+1];
|
||||
if ((p1 == 0x3F && p2 == 0x00) && i > 0)
|
||||
SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_INVALID_ARGUMENTS);
|
||||
}
|
||||
}
|
||||
if (card->ctx->debug >= 2) {
|
||||
char line[128], *linep = line;
|
||||
|
||||
|
@ -680,8 +694,6 @@ int sc_select_file(struct sc_card *card,
|
|||
strcpy(linep, "\n");
|
||||
debug(card->ctx, line);
|
||||
}
|
||||
if (in_path->len > SC_MAX_PATH_SIZE)
|
||||
SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_INVALID_ARGUMENTS);
|
||||
if (card->ops->select_file == NULL)
|
||||
SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_NOT_SUPPORTED);
|
||||
r = card->ops->select_file(card, in_path, file);
|
||||
|
|
|
@ -152,7 +152,7 @@ static CK_RV pkcs15_create_tokens(struct sc_pkcs11_card *p11card)
|
|||
|
||||
debug(context, "Enumerating private keys\n");
|
||||
rv = sc_pkcs15_enum_private_keys(card);
|
||||
if (rv < 0)
|
||||
if (rv < 0)
|
||||
return sc_to_cryptoki_error(rv, reader);
|
||||
|
||||
for (i = 0; i < card->pin_count; i++) {
|
||||
|
@ -484,25 +484,24 @@ CK_RV pkcs15_prkey_sign(struct sc_pkcs11_session *ses, void *obj,
|
|||
CK_ULONG_PTR pulDataLen)
|
||||
{
|
||||
struct pkcs15_prkey_object *prkey = (struct pkcs15_prkey_object *) obj;
|
||||
int rv, hash;
|
||||
int rv, flags = 0;
|
||||
|
||||
debug(context, "Initiating signing operation.\n");
|
||||
|
||||
switch (pMechanism->mechanism) {
|
||||
case CKM_RSA_PKCS:
|
||||
hash = SC_PKCS15_HASH_NONE;
|
||||
break;
|
||||
case CKM_SHA1_RSA_PKCS:
|
||||
hash = SC_PKCS15_HASH_SHA1;
|
||||
flags = SC_PKCS15_HASH_SHA1;
|
||||
break;
|
||||
default:
|
||||
return CKR_MECHANISM_INVALID;
|
||||
}
|
||||
|
||||
debug(context, "Selected hash %d. Now computing signature.\n", hash);
|
||||
debug(context, "Selected flags %X. Now computing signature.\n", flags);
|
||||
rv = sc_pkcs15_compute_signature((struct sc_pkcs15_card*) ses->slot->card->fw_data,
|
||||
prkey->prkey_info,
|
||||
hash,
|
||||
flags,
|
||||
pData,
|
||||
ulDataLen,
|
||||
pSignature,
|
||||
|
|
|
@ -37,7 +37,6 @@ CK_RV C_Initialize(CK_VOID_PTR pReserved)
|
|||
error(context, "C_Initialize(): Cryptoki already initialized\n");
|
||||
return CKR_CRYPTOKI_ALREADY_INITIALIZED;
|
||||
}
|
||||
|
||||
rc = sc_establish_context(&context);
|
||||
if (rc != 0)
|
||||
return CKR_DEVICE_ERROR;
|
||||
|
|
|
@ -266,7 +266,7 @@ int main(int argc, char * const argv[])
|
|||
goto end;
|
||||
}
|
||||
|
||||
#if 0
|
||||
#if 1
|
||||
r = sc_lock(card);
|
||||
if (r) {
|
||||
fprintf(stderr, "Unable to lock card: %s\n", sc_strerror(r));
|
||||
|
@ -340,7 +340,7 @@ end:
|
|||
if (p15card)
|
||||
sc_pkcs15_unbind(p15card);
|
||||
if (card) {
|
||||
#if 0
|
||||
#if 1
|
||||
sc_unlock(card);
|
||||
#endif
|
||||
sc_disconnect_card(card);
|
||||
|
|
Loading…
Reference in New Issue