added read and write of data groups
adds read_binary_rec and write_binary_rec to scutil.h
This commit is contained in:
@@ -51,24 +51,6 @@ static ssize_t getline(char **lineptr, size_t *n, FILE *stream)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const char *newpin = NULL;
|
|
||||||
static const char *pin = NULL;
|
|
||||||
static const char *puk = NULL;
|
|
||||||
static const char *can = NULL;
|
|
||||||
static const char *mrz = NULL;
|
|
||||||
static u8 chat[0xff];
|
|
||||||
static u8 desc[0xffff];
|
|
||||||
size_t *certs_lens = NULL;
|
|
||||||
static const unsigned char **certs = NULL;
|
|
||||||
static unsigned char *privkey = NULL;
|
|
||||||
static size_t privkey_len = 0;
|
|
||||||
static u8 auxiliary_data[0xff];
|
|
||||||
static size_t auxiliary_data_len = 0;
|
|
||||||
|
|
||||||
static sc_context_t *ctx = NULL;
|
|
||||||
static sc_card_t *card = NULL;
|
|
||||||
static sc_reader_t *reader;
|
|
||||||
|
|
||||||
int fread_to_eof(const unsigned char *file, unsigned char **buf, size_t *buflen)
|
int fread_to_eof(const unsigned char *file, unsigned char **buf, size_t *buflen)
|
||||||
{
|
{
|
||||||
FILE *input;
|
FILE *input;
|
||||||
@@ -107,6 +89,36 @@ err:
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void read_dg(sc_card_t *card, unsigned char sfid, const char *dg_str,
|
||||||
|
unsigned char **dg, size_t *dg_len)
|
||||||
|
{
|
||||||
|
int r = read_binary_rec(card, sfid, dg, dg_len);
|
||||||
|
if (r < 0)
|
||||||
|
fprintf(stderr, "Coult not read DG %02u %s (%s)\n",
|
||||||
|
sfid, dg_str, sc_strerror(r));
|
||||||
|
else
|
||||||
|
bin_print(stdout, dg_str, *dg, *dg_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_dg(sc_card_t *card, unsigned char sfid, const char *dg_str,
|
||||||
|
const char *dg_hex)
|
||||||
|
{
|
||||||
|
unsigned char dg[0xff];
|
||||||
|
size_t dg_len = sizeof dg;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = sc_hex_to_bin(dg_hex, dg, &dg_len);
|
||||||
|
if (r < 0) {
|
||||||
|
fprintf(stderr, "Coult not parse DG %02u %s (%s)\n",
|
||||||
|
sfid, dg_str, sc_strerror(r));
|
||||||
|
} else {
|
||||||
|
r = write_binary_rec(card, sfid, dg, dg_len);
|
||||||
|
if (r < 0)
|
||||||
|
printf("Coult not write DG %02u %s (%s)\n",
|
||||||
|
sfid, dg_str, sc_strerror(r));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int npa_translate_apdus(sc_card_t *card, FILE *input)
|
int npa_translate_apdus(sc_card_t *card, FILE *input)
|
||||||
{
|
{
|
||||||
u8 buf[4 + 3 + 0xffff + 3];
|
u8 buf[4 + 3 + 0xffff + 3];
|
||||||
@@ -147,7 +159,7 @@ int npa_translate_apdus(sc_card_t *card, FILE *input)
|
|||||||
|
|
||||||
r = sc_bytes2apdu(card->ctx, buf, apdulen, &apdu);
|
r = sc_bytes2apdu(card->ctx, buf, apdulen, &apdu);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
bin_log(ctx, SC_LOG_DEBUG_NORMAL, "Invalid C-APDU", buf, apdulen);
|
bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Invalid C-APDU", buf, apdulen);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,8 +187,28 @@ int npa_translate_apdus(sc_card_t *card, FILE *input)
|
|||||||
int
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
const char *newpin = NULL;
|
||||||
|
const char *pin = NULL;
|
||||||
|
const char *puk = NULL;
|
||||||
|
const char *can = NULL;
|
||||||
|
const char *mrz = NULL;
|
||||||
|
|
||||||
|
unsigned char chat[0xff];
|
||||||
|
unsigned char desc[0xffff];
|
||||||
|
unsigned char **certs = NULL;
|
||||||
|
size_t *certs_lens = NULL;
|
||||||
|
unsigned char *privkey = NULL;
|
||||||
|
size_t privkey_len = 0;
|
||||||
|
unsigned char auxiliary_data[0xff];
|
||||||
|
size_t auxiliary_data_len = 0;
|
||||||
|
unsigned char new_dg[0xff];
|
||||||
|
size_t new_dg_len;
|
||||||
|
|
||||||
|
sc_context_t *ctx = NULL;
|
||||||
|
sc_card_t *card = NULL;
|
||||||
|
sc_reader_t *reader;
|
||||||
|
|
||||||
int r, oindex = 0, tr_version = EAC_TR_VERSION_2_02;
|
int r, oindex = 0, tr_version = EAC_TR_VERSION_2_02;
|
||||||
size_t channeldatalen;
|
|
||||||
struct establish_pace_channel_input pace_input;
|
struct establish_pace_channel_input pace_input;
|
||||||
struct establish_pace_channel_output pace_output;
|
struct establish_pace_channel_output pace_output;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
@@ -184,6 +216,8 @@ main (int argc, char **argv)
|
|||||||
FILE *input = NULL;
|
FILE *input = NULL;
|
||||||
CVC_CERT *cvc_cert = NULL;
|
CVC_CERT *cvc_cert = NULL;
|
||||||
unsigned char *certs_chat = NULL;
|
unsigned char *certs_chat = NULL;
|
||||||
|
unsigned char *dg = NULL;
|
||||||
|
size_t dg_len = 0;
|
||||||
|
|
||||||
struct gengetopt_args_info cmdline;
|
struct gengetopt_args_info cmdline;
|
||||||
|
|
||||||
@@ -502,7 +536,8 @@ main (int argc, char **argv)
|
|||||||
npa_secret_name(pace_input.pin_id));
|
npa_secret_name(pace_input.pin_id));
|
||||||
|
|
||||||
if (cmdline.cv_certificate_given || cmdline.private_key_given) {
|
if (cmdline.cv_certificate_given || cmdline.private_key_given) {
|
||||||
r = perform_terminal_authentication(card, certs, certs_lens,
|
r = perform_terminal_authentication(card,
|
||||||
|
(const unsigned char **) certs, certs_lens,
|
||||||
privkey, privkey_len, auxiliary_data, auxiliary_data_len);
|
privkey, privkey_len, auxiliary_data, auxiliary_data_len);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto err;
|
goto err;
|
||||||
@@ -514,6 +549,60 @@ main (int argc, char **argv)
|
|||||||
printf("Performed Chip Authentication.\n");
|
printf("Performed Chip Authentication.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cmdline.read_dg1_flag)
|
||||||
|
read_dg(card, 1, "Document Type", &dg, &dg_len);
|
||||||
|
if (cmdline.read_dg2_flag)
|
||||||
|
read_dg(card, 2, "Issuing State", &dg, &dg_len);
|
||||||
|
if (cmdline.read_dg3_flag)
|
||||||
|
read_dg(card, 3, "Date of Expiry", &dg, &dg_len);
|
||||||
|
if (cmdline.read_dg4_flag)
|
||||||
|
read_dg(card, 4, "Given Names", &dg, &dg_len);
|
||||||
|
if (cmdline.read_dg5_flag)
|
||||||
|
read_dg(card, 5, "Family Names", &dg, &dg_len);
|
||||||
|
if (cmdline.read_dg6_flag)
|
||||||
|
read_dg(card, 6, "Religious/Artistic Name", &dg, &dg_len);
|
||||||
|
if (cmdline.read_dg7_flag)
|
||||||
|
read_dg(card, 7, "Academic Title", &dg, &dg_len);
|
||||||
|
if (cmdline.read_dg8_flag)
|
||||||
|
read_dg(card, 8, "Date of Birth", &dg, &dg_len);
|
||||||
|
if (cmdline.read_dg9_flag)
|
||||||
|
read_dg(card, 9, "Place of Birth", &dg, &dg_len);
|
||||||
|
if (cmdline.read_dg10_flag)
|
||||||
|
read_dg(card, 10, "Nationality", &dg, &dg_len);
|
||||||
|
if (cmdline.read_dg11_flag)
|
||||||
|
read_dg(card, 11, "Sex", &dg, &dg_len);
|
||||||
|
if (cmdline.read_dg12_flag)
|
||||||
|
read_dg(card, 12, "Optional Data", &dg, &dg_len);
|
||||||
|
if (cmdline.read_dg13_flag)
|
||||||
|
read_dg(card, 13, "", &dg, &dg_len);
|
||||||
|
if (cmdline.read_dg14_flag)
|
||||||
|
read_dg(card, 14, "", &dg, &dg_len);
|
||||||
|
if (cmdline.read_dg15_flag)
|
||||||
|
read_dg(card, 15, "", &dg, &dg_len);
|
||||||
|
if (cmdline.read_dg16_flag)
|
||||||
|
read_dg(card, 16, "", &dg, &dg_len);
|
||||||
|
if (cmdline.read_dg17_flag)
|
||||||
|
read_dg(card, 17, "Normal Place of Residence", &dg, &dg_len);
|
||||||
|
if (cmdline.read_dg18_flag)
|
||||||
|
read_dg(card, 18, "Community ID", &dg, &dg_len);
|
||||||
|
if (cmdline.read_dg19_flag)
|
||||||
|
read_dg(card, 19, "Residence Permit I", &dg, &dg_len);
|
||||||
|
if (cmdline.read_dg20_flag)
|
||||||
|
read_dg(card, 20, "Residence Permit II", &dg, &dg_len);
|
||||||
|
if (cmdline.read_dg21_flag)
|
||||||
|
read_dg(card, 21, "Optional Data", &dg, &dg_len);
|
||||||
|
|
||||||
|
if (cmdline.write_dg17_given)
|
||||||
|
write_dg(card, 17, "Normal Place of Residence", cmdline.write_dg17_arg);
|
||||||
|
if (cmdline.write_dg18_given)
|
||||||
|
write_dg(card, 18, "Community ID", cmdline.write_dg18_arg);
|
||||||
|
if (cmdline.write_dg19_given)
|
||||||
|
write_dg(card, 19, "Residence Permit I", cmdline.write_dg19_arg);
|
||||||
|
if (cmdline.write_dg20_given)
|
||||||
|
write_dg(card, 20, "Residence Permit II", cmdline.write_dg20_arg);
|
||||||
|
if (cmdline.write_dg21_given)
|
||||||
|
write_dg(card, 21, "Optional Data", cmdline.write_dg21_arg);
|
||||||
|
|
||||||
if (cmdline.translate_given) {
|
if (cmdline.translate_given) {
|
||||||
if (strncmp(cmdline.translate_arg, "stdin", strlen("stdin")) == 0)
|
if (strncmp(cmdline.translate_arg, "stdin", strlen("stdin")) == 0)
|
||||||
input = stdin;
|
input = stdin;
|
||||||
@@ -535,16 +624,11 @@ main (int argc, char **argv)
|
|||||||
|
|
||||||
err:
|
err:
|
||||||
cmdline_parser_free(&cmdline);
|
cmdline_parser_free(&cmdline);
|
||||||
if (pace_output.ef_cardaccess)
|
free(pace_output.ef_cardaccess);
|
||||||
free(pace_output.ef_cardaccess);
|
free(pace_output.recent_car);
|
||||||
if (pace_output.recent_car)
|
free(pace_output.previous_car);
|
||||||
free(pace_output.recent_car);
|
free(pace_output.id_icc);
|
||||||
if (pace_output.previous_car)
|
free(pace_output.id_pcd);
|
||||||
free(pace_output.previous_car);
|
|
||||||
if (pace_output.id_icc)
|
|
||||||
free(pace_output.id_icc);
|
|
||||||
if (pace_output.id_pcd)
|
|
||||||
free(pace_output.id_pcd);
|
|
||||||
if (input)
|
if (input)
|
||||||
fclose(input);
|
fclose(input);
|
||||||
if (certs) {
|
if (certs) {
|
||||||
@@ -559,6 +643,7 @@ err:
|
|||||||
free(certs_chat);
|
free(certs_chat);
|
||||||
if (cvc_cert)
|
if (cvc_cert)
|
||||||
CVC_CERT_free(cvc_cert);
|
CVC_CERT_free(cvc_cert);
|
||||||
|
free(dg);
|
||||||
|
|
||||||
sm_stop(card);
|
sm_stop(card);
|
||||||
sc_reset(card, 1);
|
sc_reset(card, 1);
|
||||||
|
|||||||
@@ -79,6 +79,96 @@ option "unblock" U
|
|||||||
"Unblock PIN (uses PUK to activate three more retries)"
|
"Unblock PIN (uses PUK to activate three more retries)"
|
||||||
flag off
|
flag off
|
||||||
|
|
||||||
|
section "Read and Write Data Groups"
|
||||||
|
option "read-dg1" -
|
||||||
|
"Read DG 1 (Document Type)"
|
||||||
|
flag off
|
||||||
|
option "read-dg2" -
|
||||||
|
"Read DG 2 (Issuing State)"
|
||||||
|
flag off
|
||||||
|
option "read-dg3" -
|
||||||
|
"Read DG 3 (Date of Expiry)"
|
||||||
|
flag off
|
||||||
|
option "read-dg4" -
|
||||||
|
"Read DG 4 (Given Names)"
|
||||||
|
flag off
|
||||||
|
option "read-dg5" -
|
||||||
|
"Read DG 5 (Family Names)"
|
||||||
|
flag off
|
||||||
|
option "read-dg6" -
|
||||||
|
"Read DG 6 (Religious/Artistic Name)"
|
||||||
|
flag off
|
||||||
|
option "read-dg7" -
|
||||||
|
"Read DG 7 (Academic Title)"
|
||||||
|
flag off
|
||||||
|
option "read-dg8" -
|
||||||
|
"Read DG 8 (Date of Birth)"
|
||||||
|
flag off
|
||||||
|
option "read-dg9" -
|
||||||
|
"Read DG 9 (Place of Birth)"
|
||||||
|
flag off
|
||||||
|
option "read-dg10" -
|
||||||
|
"Read DG 10 (Nationality)"
|
||||||
|
flag off
|
||||||
|
option "read-dg11" -
|
||||||
|
"Read DG 11 (Sex)"
|
||||||
|
flag off
|
||||||
|
option "read-dg12" -
|
||||||
|
"Read DG 12 (Optional Data)"
|
||||||
|
flag off
|
||||||
|
option "read-dg13" -
|
||||||
|
"Read DG 13"
|
||||||
|
flag off
|
||||||
|
option "read-dg14" -
|
||||||
|
"Read DG 14"
|
||||||
|
flag off
|
||||||
|
option "read-dg15" -
|
||||||
|
"Read DG 15"
|
||||||
|
flag off
|
||||||
|
option "read-dg16" -
|
||||||
|
"Read DG 16"
|
||||||
|
flag off
|
||||||
|
option "read-dg17" -
|
||||||
|
"Read DG 17 (Normal Place of Residence)"
|
||||||
|
flag off
|
||||||
|
option "read-dg18" -
|
||||||
|
"Read DG 18 (Community ID)"
|
||||||
|
flag off
|
||||||
|
option "read-dg19" -
|
||||||
|
"Read DG 19 (Residence Permit I)"
|
||||||
|
flag off
|
||||||
|
option "read-dg20" -
|
||||||
|
"Read DG 20 (Residence Permit II)"
|
||||||
|
flag off
|
||||||
|
option "read-dg21" -
|
||||||
|
"Read DG 21 (Optional Data)"
|
||||||
|
flag off
|
||||||
|
option "write-dg17" -
|
||||||
|
"Write DG 17 (Normal Place of Residence)"
|
||||||
|
string
|
||||||
|
typestr="HEX_STRING"
|
||||||
|
optional
|
||||||
|
option "write-dg18" -
|
||||||
|
"Write DG 18 (Community ID)"
|
||||||
|
string
|
||||||
|
typestr="HEX_STRING"
|
||||||
|
optional
|
||||||
|
option "write-dg19" -
|
||||||
|
"Write DG 19 (Residence Permit I)"
|
||||||
|
string
|
||||||
|
typestr="HEX_STRING"
|
||||||
|
optional
|
||||||
|
option "write-dg20" -
|
||||||
|
"Write DG 20 (Residence Permit II)"
|
||||||
|
string
|
||||||
|
typestr="HEX_STRING"
|
||||||
|
optional
|
||||||
|
option "write-dg21" -
|
||||||
|
"Write DG 21 (Optional Data)"
|
||||||
|
string
|
||||||
|
typestr="HEX_STRING"
|
||||||
|
optional
|
||||||
|
|
||||||
section "Special options, not always useful"
|
section "Special options, not always useful"
|
||||||
option "break" b
|
option "break" b
|
||||||
"Brute force PIN, CAN or PUK"
|
"Brute force PIN, CAN or PUK"
|
||||||
|
|||||||
@@ -312,19 +312,14 @@ int get_pace_capabilities(u8 *bitmap)
|
|||||||
|
|
||||||
#define ISO_READ_BINARY 0xB0
|
#define ISO_READ_BINARY 0xB0
|
||||||
#define ISO_P1_FLAG_SFID 0x80
|
#define ISO_P1_FLAG_SFID 0x80
|
||||||
/** Read an EF.
|
int read_binary_rec(sc_card_t *card, unsigned char sfid,
|
||||||
* @note MF must be selected before calling this function.
|
|
||||||
* */
|
|
||||||
static int get_ef(sc_card_t *card, unsigned char sfid,
|
|
||||||
u8 **ef, size_t *ef_len)
|
u8 **ef, size_t *ef_len)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
/* we read less bytes than possible. this is a workaround for acr 122,
|
/* we read less bytes than possible. this is a workaround for acr 122,
|
||||||
* which only supports apdus of max 250 bytes */
|
* which only supports apdus of max 250 bytes */
|
||||||
size_t read = maxresp - 8;
|
size_t read = maxresp - 8;
|
||||||
u8 p2;
|
|
||||||
sc_apdu_t apdu;
|
sc_apdu_t apdu;
|
||||||
sc_file_t *file = NULL;
|
|
||||||
u8 *p;
|
u8 *p;
|
||||||
struct iso_sm_ctx *iso_sm_ctx = card->sm_ctx.info.cmd_data;
|
struct iso_sm_ctx *iso_sm_ctx = card->sm_ctx.info.cmd_data;
|
||||||
|
|
||||||
@@ -386,27 +381,80 @@ static int get_ef(sc_card_t *card, unsigned char sfid,
|
|||||||
*ef + *ef_len, read, 0);
|
*ef + *ef_len, read, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* test cards only return an empty FCI template,
|
|
||||||
* so we can't determine any file proberties */
|
|
||||||
if (file && *ef_len < file->size) {
|
|
||||||
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Actual filesize differs from the size in file "
|
|
||||||
"proberties (%u!=%u).", *ef_len, file->size);
|
|
||||||
r = SC_ERROR_FILE_TOO_SMALL;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = SC_SUCCESS;
|
r = SC_SUCCESS;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
free(file);
|
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_ef_card_access(sc_card_t *card,
|
#define ISO_WRITE_BINARY 0xD0
|
||||||
|
int write_binary_rec(sc_card_t *card, unsigned char sfid,
|
||||||
|
u8 *ef, size_t ef_len)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
/* we write less bytes than possible. this is a workaround for acr 122,
|
||||||
|
* which only supports apdus of max 250 bytes */
|
||||||
|
size_t write = maxresp - 8;
|
||||||
|
sc_apdu_t apdu;
|
||||||
|
sc_file_t *file = NULL;
|
||||||
|
u8 *p;
|
||||||
|
struct iso_sm_ctx *iso_sm_ctx = card->sm_ctx.info.cmd_data;
|
||||||
|
|
||||||
|
if (!card) {
|
||||||
|
r = SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write > SC_MAX_APDU_BUFFER_SIZE-2
|
||||||
|
|| (card->sm_ctx.sm_mode == SM_MODE_TRANSMIT
|
||||||
|
&& write > (((SC_MAX_APDU_BUFFER_SIZE-2
|
||||||
|
/* for encrypted APDUs we usually get authenticated status
|
||||||
|
* bytes (4B), a MAC (11B) and a cryptogram with padding
|
||||||
|
* indicator (3B without data). The cryptogram is always
|
||||||
|
* padded to the block size. */
|
||||||
|
-18) / iso_sm_ctx->block_length)
|
||||||
|
* iso_sm_ctx->block_length - 1)))
|
||||||
|
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_EXT,
|
||||||
|
ISO_WRITE_BINARY, ISO_P1_FLAG_SFID|sfid, 0);
|
||||||
|
else
|
||||||
|
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT,
|
||||||
|
ISO_WRITE_BINARY, ISO_P1_FLAG_SFID|sfid, 0);
|
||||||
|
|
||||||
|
if (write > ef_len) {
|
||||||
|
apdu.datalen = ef_len;
|
||||||
|
apdu.lc = ef_len;
|
||||||
|
} else {
|
||||||
|
apdu.datalen = write;
|
||||||
|
apdu.lc = write;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
|
/* emulate the behaviour of sc_write_binary */
|
||||||
|
if (r >= 0)
|
||||||
|
r = apdu.resplen;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (r < 0 || r > ef_len) {
|
||||||
|
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not write EF.");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
ef_len -= r;
|
||||||
|
ef += r;
|
||||||
|
if (!ef_len)
|
||||||
|
break;
|
||||||
|
|
||||||
|
r = sc_write_binary(card, ef_len, ef, write, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
err:
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_ef_card_access(sc_card_t *card,
|
||||||
u8 **ef_cardaccess, size_t *length_ef_cardaccess)
|
u8 **ef_cardaccess, size_t *length_ef_cardaccess)
|
||||||
{
|
{
|
||||||
return get_ef(card, SFID_EF_CARDACCESS, ef_cardaccess, length_ef_cardaccess);
|
return read_binary_rec(card, SFID_EF_CARDACCESS, ef_cardaccess, length_ef_cardaccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int format_mse_cdata(struct sc_context *ctx, int protocol,
|
static int format_mse_cdata(struct sc_context *ctx, int protocol,
|
||||||
@@ -1821,7 +1869,7 @@ err:
|
|||||||
int get_ef_card_security(sc_card_t *card,
|
int get_ef_card_security(sc_card_t *card,
|
||||||
u8 **ef_security, size_t *length_ef_security)
|
u8 **ef_security, size_t *length_ef_security)
|
||||||
{
|
{
|
||||||
return get_ef(card, SFID_EF_CARDSECURITY, ef_security, length_ef_security);
|
return read_binary_rec(card, SFID_EF_CARDSECURITY, ef_security, length_ef_security);
|
||||||
}
|
}
|
||||||
|
|
||||||
int perform_chip_authentication(sc_card_t *card)
|
int perform_chip_authentication(sc_card_t *card)
|
||||||
|
|||||||
@@ -89,5 +89,31 @@ void _bin_log(sc_context_t *ctx, int type, const char *file, int line,
|
|||||||
*/
|
*/
|
||||||
int print_avail(int verbose);
|
int print_avail(int verbose);
|
||||||
|
|
||||||
|
/** Recursively read an EF by short file identifier.
|
||||||
|
*
|
||||||
|
* @param[in] card
|
||||||
|
* @param[in] sfid Short file identifier
|
||||||
|
* @param[in,out] ef Where to safe the file. the buffer will be allocated
|
||||||
|
* using \c realloc() and should be set to NULL, if
|
||||||
|
* empty.
|
||||||
|
* @param[in,out] ef_len Length of \a *ef
|
||||||
|
*
|
||||||
|
* @note The appropriate directory must be selected before calling this function.
|
||||||
|
* */
|
||||||
|
int read_binary_rec(sc_card_t *card, unsigned char sfid,
|
||||||
|
u8 **ef, size_t *ef_len);
|
||||||
|
|
||||||
|
/** Recursively write an EF by short file identifier.
|
||||||
|
*
|
||||||
|
* @param[in] card
|
||||||
|
* @param[in] sfid Short file identifier
|
||||||
|
* @param[in] ef Date to write
|
||||||
|
* @param[in] ef_len Length of \a ef
|
||||||
|
*
|
||||||
|
* @note The appropriate directory must be selected before calling this function.
|
||||||
|
* */
|
||||||
|
int write_binary_rec(sc_card_t *card, unsigned char sfid,
|
||||||
|
u8 *ef, size_t ef_len);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
/* @} */
|
/* @} */
|
||||||
|
|||||||
Reference in New Issue
Block a user