- added error reporting for several new SWs

- added check_sw function to sc_card_operations


git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@211 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
jey 2002-02-15 23:17:58 +00:00
parent 709727d469
commit 262e5c2083
10 changed files with 112 additions and 76 deletions

View File

@ -256,7 +256,7 @@ static int select_file_id(struct sc_card *card, const u8 *buf, size_t buflen,
apdu.resplen = 0;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
r = sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2);
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
SC_TEST_RET(card->ctx, r, "Card returned error");
if (file == NULL)
@ -349,7 +349,7 @@ static int flex_list_files(struct sc_card *card, u8 *buf, size_t buflen)
return r;
if (apdu.sw1 == 0x6A && apdu.sw2 == 0x82)
break;
r = sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2);
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
if (r)
return r;
if (apdu.resplen != 4) {
@ -385,7 +385,7 @@ static int flex_delete_file(struct sc_card *card, const struct sc_path *path)
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);
return sc_check_sw(card, apdu.sw1, apdu.sw2);
}
static int acl_to_ac(unsigned int acl)
@ -524,7 +524,7 @@ 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");
r = sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2);
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
SC_TEST_RET(card->ctx, r, "Card returned error");
if (card->cache_valid) {
u8 file_id[2];
@ -598,7 +598,7 @@ static int flex_compute_signature(struct sc_card *card, const u8 *data,
apdu.resp = sbuf;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
r = sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2);
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
SC_TEST_RET(card->ctx, r, "Card returned error");
for (i = 0; i < apdu.resplen; i++)
out[i] = sbuf[apdu.resplen-1-i];
@ -640,7 +640,7 @@ static int flex_verify(struct sc_card *card, unsigned int type, int ref,
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
if (apdu.sw1 == 0x63)
return SC_ERROR_PIN_CODE_INCORRECT;
return sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2);
return sc_check_sw(card, apdu.sw1, apdu.sw2);
}
static const struct sc_card_driver * sc_get_driver(void)

View File

@ -144,7 +144,7 @@ gpk_finish(struct sc_card *card)
/*
* Error code handling for the GPK4000.
* sc_sw_to_errorcode doesn't seem to handle all of the
* sc_check_sw doesn't seem to handle all of the
* status words the GPK is capable of returning
*/
static int
@ -171,7 +171,7 @@ gpk_sw_to_errorcode(struct sc_card *card, u8 sw1, u8 sw2)
return SC_ERROR_INVALID_ARGUMENTS;
}
return sc_sw_to_errorcode(card, sw1, sw2);
return sc_check_sw(card, sw1, sw2);
}
/*

View File

@ -142,7 +142,7 @@ static int tcos_list_files(struct sc_card *card, u8 *buf, size_t buflen)
apdu.le = 256;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
r = sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2);
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
if (r == SC_ERROR_FILE_NOT_FOUND)
continue;
SC_TEST_RET(card->ctx, r, "Card returned error");

View File

@ -24,52 +24,10 @@
#include <assert.h>
#include <stdlib.h>
int sc_sw_to_errorcode(struct sc_card *card, int sw1, int sw2)
int sc_check_sw(struct sc_card *card, int sw1, int sw2)
{
if (sw1 != 0x90 || sw2 != 0)
error(card->ctx, "card returned SW1=%02X, SW2=%02X\n", sw1, sw2);
switch (sw1) {
case 0x67:
if (sw2 == 0)
return SC_ERROR_WRONG_LENGTH;
break;
case 0x69:
switch (sw2) {
case 0x82:
return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED;
default:
break;
}
break;
case 0x6A:
switch (sw2) {
case 0x81:
return SC_ERROR_NOT_SUPPORTED;
case 0x82:
return SC_ERROR_FILE_NOT_FOUND;
case 0x83:
return SC_ERROR_RECORD_NOT_FOUND;
case 0x85:
case 0x86:
case 0x87:
return SC_ERROR_INVALID_ARGUMENTS;
default:
break;
}
break;
case 0x6C:
error(card->ctx, "incorrect length, right length is %d\n",
sw2);
return SC_ERROR_WRONG_LENGTH;
case 0x6D:
return SC_ERROR_NOT_SUPPORTED;
case 0x6E:
return SC_ERROR_UNKNOWN_SMARTCARD;
case 0x90:
if (sw2 == 0)
return 0;
}
return SC_ERROR_UNKNOWN_REPLY;
assert(card->ops->check_sw != NULL);
return card->ops->check_sw(card, sw1, sw2);
}
static int _sc_pcscret_to_error(long rv)

View File

@ -31,7 +31,7 @@
#define SC_CARD_MAGIC 0x27182818
/* Internal use only */
int sc_sw_to_errorcode(struct sc_card *card, int sw1, int sw2);
int sc_check_sw(struct sc_card *card, int sw1, int sw2);
size_t sc_count_bit_string_size(const void * buf, size_t bufsize);
/* Default timeout value for SCardGetStatusChange */

View File

@ -25,6 +25,78 @@
#include <assert.h>
#include <ctype.h>
struct sc_card_error {
int SWs;
int errorno;
const char *errorstr;
};
const static struct sc_card_error iso7816_errors[] = {
{ 0x6200, SC_ERROR_UNKNOWN_REPLY, "State of non-volatile memory unchanged" },
{ 0x6281, SC_ERROR_UNKNOWN_REPLY, "Part of returned data may be corrupted" },
{ 0x6282, SC_ERROR_UNKNOWN_REPLY, "End of file/record reached before reading Le bytes" },
{ 0x6283, SC_ERROR_UNKNOWN_REPLY, "Selected file invalidated" },
{ 0x6284, SC_ERROR_UNKNOWN_REPLY, "FCI not formatted according to 5.1.5" },
{ 0x6300, SC_ERROR_UNKNOWN_REPLY, "State of non-volatile memory changed" },
{ 0x6381, SC_ERROR_UNKNOWN_REPLY, "File filled up by last write" },
{ 0x6581, SC_ERROR_UNKNOWN_REPLY, "Memory failure" },
{ 0x6700, SC_ERROR_WRONG_LENGTH, "Wrong length" },
{ 0x6800, SC_ERROR_UNKNOWN_REPLY, "Functions in CLA not supported" },
{ 0x6881, SC_ERROR_UNKNOWN_REPLY, "Logical channel not supported" },
{ 0x6882, SC_ERROR_UNKNOWN_REPLY, "Secure messaging not supported" },
{ 0x6900, SC_ERROR_UNKNOWN_REPLY, "Command not allowed" },
{ 0x6981, SC_ERROR_UNKNOWN_REPLY, "Command incompatible with file structure" },
{ 0x6982, SC_ERROR_SECURITY_STATUS_NOT_SATISFIED, "Security status not satisfied" },
{ 0x6983, SC_ERROR_UNKNOWN_REPLY, "Authentication method blocked" },
{ 0x6984, SC_ERROR_UNKNOWN_REPLY, "Referenced data invalidated" },
{ 0x6985, SC_ERROR_UNKNOWN_REPLY, "Conditions of use not satisfied" },
{ 0x6986, SC_ERROR_UNKNOWN_REPLY, "Command not allowed (no current EF)" },
{ 0x6987, SC_ERROR_UNKNOWN_REPLY, "Expected SM data objects missing" },
{ 0x6988, SC_ERROR_UNKNOWN_REPLY, "SM data objects incorrect" },
{ 0x6A00, SC_ERROR_UNKNOWN_REPLY, "Wrong parameter(s) P1-P2" },
{ 0x6A80, SC_ERROR_UNKNOWN_REPLY, "Incorrect parameters in the data field" },
{ 0x6A81, SC_ERROR_NOT_SUPPORTED, "Function not supported" },
{ 0x6A82, SC_ERROR_FILE_NOT_FOUND, "File not found" },
{ 0x6A83, SC_ERROR_RECORD_NOT_FOUND, "Record not found" },
{ 0x6A84, SC_ERROR_UNKNOWN_REPLY, "Not enough memory space in the file" },
{ 0x6A85, SC_ERROR_INVALID_ARGUMENTS, "Lc inconsistent with TLV structure" },
{ 0x6A86, SC_ERROR_INVALID_ARGUMENTS, "Incorrect parameters P1-P2" },
{ 0x6A87, SC_ERROR_INVALID_ARGUMENTS, "Lc inconsistent with P1-P2" },
{ 0x6A88, SC_ERROR_UNKNOWN_REPLY, "Referenced data not found" },
{ 0x6B00, SC_ERROR_UNKNOWN_REPLY, "Wrong parameter(s) P1-P2" },
{ 0x6D00, SC_ERROR_NOT_SUPPORTED, "Instruction code not supported or invalid" },
{ 0x6E00, SC_ERROR_CLASS_NOT_SUPPORTED, "Class not supported" },
{ 0x6F00, SC_ERROR_UNKNOWN_REPLY, "No precise diagnosis" }
};
static int iso7816_check_sw(struct sc_card *card, int sw1, int sw2)
{
const int err_count = sizeof(iso7816_errors)/sizeof(iso7816_errors[0]);
int i;
/* Handle special cases here */
if (sw1 == 0x6C) {
error(card->ctx, "Wrong length; correct length is %d\n", sw2);
return SC_ERROR_WRONG_LENGTH;
}
if (sw1 == 0x90)
return SC_NO_ERROR;
for (i = 0; i < err_count; i++)
if (iso7816_errors[i].SWs == ((sw1 << 8) | sw2)) {
error(card->ctx, "%s\n", iso7816_errors[i].errorstr);
return iso7816_errors[i].errorno;
}
error(card->ctx, "Unknown SWs; SW1=%02X, SW2=%02X\n", sw1, sw2);
return SC_ERROR_UNKNOWN_REPLY;
}
static int iso7816_read_binary(struct sc_card *card,
unsigned int idx, u8 *buf, size_t count,
unsigned long flags)
@ -42,7 +114,7 @@ static int iso7816_read_binary(struct sc_card *card,
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
if (apdu.resplen == 0)
SC_FUNC_RETURN(card->ctx, 2, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2));
SC_FUNC_RETURN(card->ctx, 2, sc_check_sw(card, apdu.sw1, apdu.sw2));
memcpy(buf, recvbuf, apdu.resplen);
SC_FUNC_RETURN(card->ctx, 3, apdu.resplen);
@ -68,7 +140,7 @@ static int iso7816_read_record(struct sc_card *card,
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
if (apdu.resplen == 0)
SC_FUNC_RETURN(card->ctx, 2, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2));
SC_FUNC_RETURN(card->ctx, 2, sc_check_sw(card, apdu.sw1, apdu.sw2));
memcpy(buf, recvbuf, apdu.resplen);
SC_FUNC_RETURN(card->ctx, 3, apdu.resplen);
@ -93,7 +165,7 @@ static int iso7816_write_binary(struct sc_card *card,
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
SC_TEST_RET(card->ctx, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2),
SC_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2),
"Card returned error");
SC_FUNC_RETURN(card->ctx, 3, count);
}
@ -117,7 +189,7 @@ static int iso7816_update_binary(struct sc_card *card,
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
SC_TEST_RET(card->ctx, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2),
SC_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2),
"Card returned error");
SC_FUNC_RETURN(card->ctx, 3, count);
}
@ -284,10 +356,10 @@ static int iso7816_select_file(struct sc_card *card,
if (file == NULL) {
if (apdu.sw1 == 0x61)
SC_FUNC_RETURN(card->ctx, 2, 0);
SC_FUNC_RETURN(card->ctx, 2, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2));
SC_FUNC_RETURN(card->ctx, 2, sc_check_sw(card, apdu.sw1, apdu.sw2));
}
r = sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2);
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
if (r)
SC_FUNC_RETURN(card->ctx, 2, r);
@ -322,7 +394,7 @@ static int iso7816_get_challenge(struct sc_card *card, u8 *rnd, size_t len)
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
if (apdu.resplen != 8)
return sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2);
return sc_check_sw(card, apdu.sw1, apdu.sw2);
memcpy(rnd, apdu.resp, n);
len -= n;
rnd += n;
@ -432,7 +504,7 @@ static int iso7816_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);
return sc_check_sw(card, apdu.sw1, apdu.sw2);
}
static int iso7816_delete_file(struct sc_card *card, const struct sc_path *path)
@ -455,7 +527,7 @@ static int iso7816_delete_file(struct sc_card *card, const struct sc_path *path)
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);
return sc_check_sw(card, apdu.sw1, apdu.sw2);
}
static int iso7816_list_files(struct sc_card *card, u8 *buf, size_t buflen)
@ -470,7 +542,7 @@ static int iso7816_list_files(struct sc_card *card, u8 *buf, size_t buflen)
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
if (apdu.resplen == 0)
return sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2);
return sc_check_sw(card, apdu.sw1, apdu.sw2);
return apdu.resplen;
}
@ -505,7 +577,7 @@ static int iso7816_verify(struct sc_card *card, unsigned int type, int ref,
*tries_left = apdu.sw2 & 0x0F;
return SC_ERROR_PIN_CODE_INCORRECT;
}
return sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2);
return sc_check_sw(card, apdu.sw1, apdu.sw2);
}
static int iso7816_set_security_env(struct sc_card *card,
@ -569,7 +641,7 @@ static int iso7816_set_security_env(struct sc_card *card,
sc_perror(card->ctx, r, "APDU transmit failed");
goto err;
}
r = sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2);
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
if (r) {
sc_perror(card->ctx, r, "Card returned error");
goto err;
@ -581,7 +653,7 @@ static int iso7816_set_security_env(struct sc_card *card,
r = sc_transmit_apdu(card, &apdu);
sc_unlock(card);
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
return sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2);
return sc_check_sw(card, apdu.sw1, apdu.sw2);
err:
if (locked)
sc_unlock(card);
@ -601,7 +673,7 @@ static int iso7816_restore_security_env(struct sc_card *card, int se_num)
apdu.resp = rbuf;
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);
return sc_check_sw(card, apdu.sw1, apdu.sw2);
}
static int iso7816_compute_signature(struct sc_card *card,
@ -637,7 +709,7 @@ static int iso7816_compute_signature(struct sc_card *card,
memcpy(out, apdu.resp, len);
SC_FUNC_RETURN(card->ctx, 4, len);
}
SC_FUNC_RETURN(card->ctx, 4, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2));
SC_FUNC_RETURN(card->ctx, 4, sc_check_sw(card, apdu.sw1, apdu.sw2));
}
static int iso7816_change_reference_data(struct sc_card *card, unsigned int type,
@ -676,7 +748,7 @@ static int iso7816_change_reference_data(struct sc_card *card, unsigned int type
*tries_left = apdu.sw2 & 0x0F;
SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_PIN_CODE_INCORRECT);
}
return sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2);
return sc_check_sw(card, apdu.sw1, apdu.sw2);
}
static int iso7816_reset_retry_counter(struct sc_card *card, unsigned int type, int ref,
@ -718,7 +790,7 @@ static int iso7816_reset_retry_counter(struct sc_card *card, unsigned int type,
r = sc_transmit_apdu(card, &apdu);
memset(sbuf, 0, len);
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
return sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2);
return sc_check_sw(card, apdu.sw1, apdu.sw2);
}
static struct sc_card_operations iso_ops = {
@ -757,6 +829,7 @@ const struct sc_card_driver * sc_get_iso7816_driver(void)
iso_ops.compute_signature = iso7816_compute_signature;
iso_ops.reset_retry_counter = iso7816_reset_retry_counter;
iso_ops.change_reference_data = iso7816_change_reference_data;
iso_ops.check_sw = iso7816_check_sw;
}
return &iso_driver;
}

View File

@ -43,6 +43,7 @@ extern "C" {
#endif
#define SC_SUCCESS 0
#define SC_NO_ERROR 0
#define SC_ERROR_MIN -1000
#define SC_ERROR_UNKNOWN -1000
@ -78,6 +79,7 @@ extern "C" {
#define SC_ERROR_WRONG_LENGTH -1030
#define SC_ERROR_RECORD_NOT_FOUND -1031
#define SC_ERROR_INTERNAL -1032
#define SC_ERROR_CLASS_NOT_SUPPORTED -1033
/* Different APDU cases */
#define SC_APDU_CASE_NONE 0
@ -157,7 +159,7 @@ extern "C" {
#define SC_MAX_PATH_SIZE 16
#define SC_MAX_PIN_SIZE 16
#define SC_MAX_ATR_SIZE 33
#define SC_MAX_SEC_ATTR_SIZE 16
#define SC_MAX_SEC_ATTR_SIZE 20
#define SC_MAX_PROP_ATTR_SIZE 16
#define SC_MAX_OBJECT_ID_OCTETS 16
#define SC_APDU_CHOP_SIZE 250
@ -366,6 +368,8 @@ struct sc_card_operations {
* writes the corresponding file identifiers to <buf>. Returns
* the number of bytes stored. */
int (*list_files)(struct sc_card *card, u8 *buf, size_t buflen);
int (*check_sw)(struct sc_card *card, int sw1, int sw2);
};
struct sc_card_driver {

View File

@ -31,7 +31,7 @@
#define SC_CARD_MAGIC 0x27182818
/* Internal use only */
int sc_sw_to_errorcode(struct sc_card *card, int sw1, int sw2);
int sc_check_sw(struct sc_card *card, int sw1, int sw2);
size_t sc_count_bit_string_size(const void * buf, size_t bufsize);
/* Default timeout value for SCardGetStatusChange */

View File

@ -328,7 +328,8 @@ const char *sc_strerror(int error)
"Card is invalid or cannot be handled",
"Wrong length",
"Record not found",
"Internal error"
"Internal error",
"Invalid CLA byte in APDU",
};
int nr_errors = sizeof(errors) / sizeof(errors[0]);

View File

@ -57,7 +57,7 @@ int sc_decipher(struct sc_card *card,
memcpy(out, apdu.resp, len);
SC_FUNC_RETURN(card->ctx, 2, len);
}
SC_FUNC_RETURN(card->ctx, 2, sc_sw_to_errorcode(card, apdu.sw1, apdu.sw2));
SC_FUNC_RETURN(card->ctx, 2, sc_check_sw(card, apdu.sw1, apdu.sw2));
}
int sc_compute_signature(struct sc_card *card,