implemented sc_format_apdu_ex
This commit is contained in:
parent
155b197932
commit
27526de021
|
@ -63,6 +63,63 @@ void sc_format_apdu(sc_card_t *card, sc_apdu_t *apdu,
|
|||
apdu->p2 = (u8) p2;
|
||||
}
|
||||
|
||||
void sc_format_apdu_cse_lc_le(struct sc_apdu *apdu)
|
||||
{
|
||||
/* TODO calculating the APDU case, Lc and Le should actually only be
|
||||
* done in sc_apdu2bytes, but to gradually change OpenSC we start here. */
|
||||
|
||||
if (!apdu)
|
||||
return;
|
||||
if (apdu->datalen > SC_MAX_APDU_DATA_SIZE
|
||||
|| apdu->resplen > SC_MAX_APDU_RESP_SIZE) {
|
||||
/* extended length */
|
||||
if (apdu->datalen < SC_MAX_EXT_APDU_DATA_SIZE)
|
||||
apdu->lc = apdu->datalen;
|
||||
if (apdu->resplen < SC_MAX_EXT_APDU_RESP_SIZE)
|
||||
apdu->le = apdu->resplen;
|
||||
if (apdu->resplen && !apdu->datalen)
|
||||
apdu->cse = SC_APDU_CASE_2_EXT;
|
||||
if (!apdu->resplen && apdu->datalen)
|
||||
apdu->cse = SC_APDU_CASE_3_EXT;
|
||||
if (apdu->resplen && apdu->datalen)
|
||||
apdu->cse = SC_APDU_CASE_4_EXT;
|
||||
} else {
|
||||
/* short length */
|
||||
if (apdu->datalen < SC_MAX_APDU_DATA_SIZE)
|
||||
apdu->lc = apdu->datalen;
|
||||
if (apdu->resplen < SC_MAX_APDU_RESP_SIZE)
|
||||
apdu->le = apdu->resplen;
|
||||
if (!apdu->resplen && !apdu->datalen)
|
||||
apdu->cse = SC_APDU_CASE_1;
|
||||
if (apdu->resplen && !apdu->datalen)
|
||||
apdu->cse = SC_APDU_CASE_2_SHORT;
|
||||
if (!apdu->resplen && apdu->datalen)
|
||||
apdu->cse = SC_APDU_CASE_3_SHORT;
|
||||
if (apdu->resplen && apdu->datalen)
|
||||
apdu->cse = SC_APDU_CASE_4_SHORT;
|
||||
}
|
||||
}
|
||||
|
||||
void sc_format_apdu_ex(struct sc_card *card, struct sc_apdu *apdu,
|
||||
u8 ins, u8 p1, u8 p2, u8 *data, size_t datalen, u8 *resp, size_t resplen)
|
||||
{
|
||||
if (!apdu) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(apdu, 0, sizeof(*apdu));
|
||||
if (card)
|
||||
apdu->cla = (u8) card->cla;
|
||||
apdu->ins = ins;
|
||||
apdu->p1 = p1;
|
||||
apdu->p2 = p2;
|
||||
apdu->resp = resp;
|
||||
apdu->resplen = resplen;
|
||||
apdu->data = data;
|
||||
apdu->datalen = datalen;
|
||||
sc_format_apdu_cse_lc_le(apdu);
|
||||
}
|
||||
|
||||
static sc_card_t * sc_card_new(sc_context_t *ctx)
|
||||
{
|
||||
sc_card_t *card;
|
||||
|
|
|
@ -147,10 +147,7 @@ iso7816_read_binary(struct sc_card *card, unsigned int idx, u8 *buf, size_t coun
|
|||
return SC_ERROR_OFFSET_TOO_LARGE;
|
||||
}
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0xB0, (idx >> 8) & 0x7F, idx & 0xFF);
|
||||
apdu.le = count;
|
||||
apdu.resplen = count;
|
||||
apdu.resp = buf;
|
||||
sc_format_apdu_ex(card, &apdu, 0xB0, (idx >> 8) & 0x7F, idx & 0xFF, NULL, 0, buf, count);
|
||||
|
||||
fixup_transceive_length(card, &apdu);
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
|
@ -1501,7 +1498,7 @@ int iso7816_logout(sc_card_t *card, unsigned char pin_reference)
|
|||
int r;
|
||||
sc_apdu_t apdu;
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x20, 0xFF, pin_reference);
|
||||
sc_format_apdu_ex(card, &apdu, 0x20, 0xFF, pin_reference, NULL, 0, NULL, 0);
|
||||
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
if (r < 0)
|
||||
|
|
|
@ -109,6 +109,7 @@ sc_file_set_type_attr
|
|||
sc_file_set_content
|
||||
sc_file_valid
|
||||
sc_format_apdu
|
||||
sc_format_apdu_ex
|
||||
sc_bytes2apdu
|
||||
sc_format_asn1_entry
|
||||
sc_format_oid
|
||||
|
|
|
@ -813,6 +813,10 @@ int sc_transmit_apdu(struct sc_card *card, struct sc_apdu *apdu);
|
|||
|
||||
void sc_format_apdu(struct sc_card *, struct sc_apdu *, int, int, int, int);
|
||||
|
||||
void sc_format_apdu_ex(struct sc_card *card, struct sc_apdu *apdu,
|
||||
u8 ins, u8 p1, u8 p2,
|
||||
u8 *data, size_t datalen, u8 *resp, size_t resplen);
|
||||
|
||||
int sc_check_apdu(struct sc_card *, const struct sc_apdu *);
|
||||
|
||||
/** Transforms an APDU from binary to its @c sc_apdu_t representation
|
||||
|
|
|
@ -32,7 +32,11 @@ typedef unsigned char u8;
|
|||
#define SC_MAX_CARD_DRIVER_SNAME_SIZE 16
|
||||
#define SC_MAX_CARD_APPS 8
|
||||
#define SC_MAX_APDU_BUFFER_SIZE 261 /* takes account of: CLA INS P1 P2 Lc [255 byte of data] Le */
|
||||
#define SC_MAX_APDU_DATA_SIZE 0xFF
|
||||
#define SC_MAX_APDU_RESP_SIZE (0xFF+1)
|
||||
#define SC_MAX_EXT_APDU_BUFFER_SIZE 65538
|
||||
#define SC_MAX_EXT_APDU_DATA_SIZE 0xFFFF
|
||||
#define SC_MAX_EXT_APDU_RESP_SIZE (0xFFFF+1)
|
||||
#define SC_MAX_PIN_SIZE 256 /* OpenPGP card has 254 max */
|
||||
#define SC_MAX_ATR_SIZE 33
|
||||
#define SC_MAX_UID_SIZE 10
|
||||
|
|
|
@ -249,8 +249,6 @@ IMPLEMENT_ASN1_FUNCTIONS(EAC_GEN_AUTH_CA_R)
|
|||
|
||||
|
||||
|
||||
#define maxresp SC_MAX_APDU_BUFFER_SIZE - 2
|
||||
|
||||
/** @brief NPA secure messaging context */
|
||||
struct eac_sm_ctx {
|
||||
/** @brief EAC context */
|
||||
|
@ -521,8 +519,6 @@ static int eac_mse(sc_card_t *card,
|
|||
r = SC_ERROR_INVALID_ARGUMENTS;
|
||||
goto err;
|
||||
}
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, ISO_MSE, p1, p2);
|
||||
|
||||
r = format_mse_cdata(card->ctx, protocol, key_reference1,
|
||||
key_reference1_len, key_reference2, key_reference2_len,
|
||||
|
@ -530,10 +526,8 @@ static int eac_mse(sc_card_t *card,
|
|||
chat, &d);
|
||||
if (r < 0)
|
||||
goto err;
|
||||
apdu.data = d;
|
||||
apdu.datalen = r;
|
||||
apdu.lc = r;
|
||||
|
||||
sc_format_apdu_ex(card, &apdu, ISO_MSE, p1, p2,
|
||||
d, r, NULL, 0);
|
||||
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
if (r < 0)
|
||||
|
@ -618,11 +612,7 @@ static int eac_gen_auth_1_encrypted_nonce(sc_card_t *card,
|
|||
EAC_GEN_AUTH_PACE_R *r_data = NULL;
|
||||
unsigned char *d = NULL, *p;
|
||||
int r, l;
|
||||
unsigned char resp[maxresp];
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, ISO_GENERAL_AUTHENTICATE,
|
||||
0x00, 0x00);
|
||||
apdu.cla = ISO_COMMAND_CHAINING;
|
||||
unsigned char resp[SC_MAX_EXT_APDU_RESP_SIZE];
|
||||
|
||||
c_data = EAC_GEN_AUTH_PACE_C_new();
|
||||
if (!c_data) {
|
||||
|
@ -635,14 +625,13 @@ static int eac_gen_auth_1_encrypted_nonce(sc_card_t *card,
|
|||
r = SC_ERROR_INTERNAL;
|
||||
goto err;
|
||||
}
|
||||
apdu.data = d;
|
||||
apdu.datalen = r;
|
||||
apdu.lc = r;
|
||||
|
||||
sc_format_apdu_ex(card, &apdu, ISO_GENERAL_AUTHENTICATE, 0x00, 0x00,
|
||||
d, r, resp, sizeof resp);
|
||||
apdu.cla = ISO_COMMAND_CHAINING;
|
||||
|
||||
sc_debug_hex(card->ctx, SC_LOG_DEBUG_SM, "General authenticate (Encrypted Nonce) command data", apdu.data, apdu.datalen);
|
||||
|
||||
apdu.resplen = sizeof resp;
|
||||
apdu.resp = resp;
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
if (r < 0)
|
||||
goto err;
|
||||
|
@ -702,11 +691,7 @@ static int eac_gen_auth_2_map_nonce(sc_card_t *card,
|
|||
EAC_GEN_AUTH_PACE_R *r_data = NULL;
|
||||
unsigned char *d = NULL, *p;
|
||||
int r, l;
|
||||
unsigned char resp[maxresp];
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, ISO_GENERAL_AUTHENTICATE,
|
||||
0x00, 0x00);
|
||||
apdu.cla = ISO_COMMAND_CHAINING;
|
||||
unsigned char resp[SC_MAX_EXT_APDU_RESP_SIZE];
|
||||
|
||||
c_data = EAC_GEN_AUTH_PACE_C_new();
|
||||
if (!c_data) {
|
||||
|
@ -727,14 +712,12 @@ static int eac_gen_auth_2_map_nonce(sc_card_t *card,
|
|||
r = SC_ERROR_INTERNAL;
|
||||
goto err;
|
||||
}
|
||||
apdu.data = d;
|
||||
apdu.datalen = r;
|
||||
apdu.lc = r;
|
||||
sc_format_apdu_ex(card, &apdu, ISO_GENERAL_AUTHENTICATE, 0x00, 0x00,
|
||||
d, r, resp, sizeof resp);
|
||||
apdu.cla = ISO_COMMAND_CHAINING;
|
||||
|
||||
sc_debug_hex(card->ctx, SC_LOG_DEBUG_SM, "General authenticate (Map Nonce) command data", apdu.data, apdu.datalen);
|
||||
|
||||
apdu.resplen = sizeof resp;
|
||||
apdu.resp = resp;
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
if (r < 0)
|
||||
goto err;
|
||||
|
@ -794,11 +777,7 @@ static int eac_gen_auth_3_perform_key_agreement(sc_card_t *card,
|
|||
EAC_GEN_AUTH_PACE_R *r_data = NULL;
|
||||
unsigned char *d = NULL, *p;
|
||||
int r, l;
|
||||
unsigned char resp[maxresp];
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, ISO_GENERAL_AUTHENTICATE,
|
||||
0x00, 0x00);
|
||||
apdu.cla = ISO_COMMAND_CHAINING;
|
||||
unsigned char resp[SC_MAX_EXT_APDU_RESP_SIZE];
|
||||
|
||||
c_data = EAC_GEN_AUTH_PACE_C_new();
|
||||
if (!c_data) {
|
||||
|
@ -819,14 +798,12 @@ static int eac_gen_auth_3_perform_key_agreement(sc_card_t *card,
|
|||
r = SC_ERROR_INTERNAL;
|
||||
goto err;
|
||||
}
|
||||
apdu.data = d;
|
||||
apdu.datalen = r;
|
||||
apdu.lc = r;
|
||||
sc_format_apdu_ex(card, &apdu, ISO_GENERAL_AUTHENTICATE, 0x00, 0x00,
|
||||
d, r, resp, sizeof resp);
|
||||
apdu.cla = ISO_COMMAND_CHAINING;
|
||||
|
||||
sc_debug_hex(card->ctx, SC_LOG_DEBUG_SM, "General authenticate (Perform Key Agreement) command data", apdu.data, apdu.datalen);
|
||||
|
||||
apdu.resplen = sizeof resp;
|
||||
apdu.resp = resp;
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
if (r < 0)
|
||||
goto err;
|
||||
|
@ -888,10 +865,7 @@ static int eac_gen_auth_4_mutual_authentication(sc_card_t *card,
|
|||
EAC_GEN_AUTH_PACE_R *r_data = NULL;
|
||||
unsigned char *d = NULL, *p;
|
||||
int r, l;
|
||||
unsigned char resp[maxresp];
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, ISO_GENERAL_AUTHENTICATE,
|
||||
0x00, 0x00);
|
||||
unsigned char resp[SC_MAX_EXT_APDU_RESP_SIZE];
|
||||
|
||||
c_data = EAC_GEN_AUTH_PACE_C_new();
|
||||
if (!c_data) {
|
||||
|
@ -912,14 +886,12 @@ static int eac_gen_auth_4_mutual_authentication(sc_card_t *card,
|
|||
r = SC_ERROR_INTERNAL;
|
||||
goto err;
|
||||
}
|
||||
apdu.data = d;
|
||||
apdu.datalen = r;
|
||||
apdu.lc = r;
|
||||
|
||||
sc_format_apdu_ex(card, &apdu, ISO_GENERAL_AUTHENTICATE, 0x00, 0x00,
|
||||
d, r, resp, sizeof resp);
|
||||
|
||||
sc_debug_hex(card->ctx, SC_LOG_DEBUG_SM, "General authenticate (Perform Key Agreement) command data", apdu.data, apdu.datalen);
|
||||
|
||||
apdu.resplen = sizeof resp;
|
||||
apdu.resp = resp;
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
if (r < 0)
|
||||
goto err;
|
||||
|
@ -1420,10 +1392,7 @@ static int eac_get_challenge(sc_card_t *card,
|
|||
goto err;
|
||||
}
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0x84, 0x00, 0x00);
|
||||
apdu.le = len;
|
||||
apdu.resplen = len;
|
||||
apdu.resp = challenge;
|
||||
sc_format_apdu_ex(card, &apdu, 0x84, 0x00, 0x00, NULL, 0, challenge, len);
|
||||
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
if (r < 0)
|
||||
|
@ -1449,17 +1418,14 @@ static int eac_verify(sc_card_t *card,
|
|||
goto err;
|
||||
}
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_EXT, 0x2A, 0x00, 0xbe);
|
||||
|
||||
apdu.data = cert;
|
||||
if (0x80 & ASN1_get_object(&apdu.data, &length, &tag, &class, cert_len)) {
|
||||
if (0x80 & ASN1_get_object(&cert, &length, &tag, &class, cert_len)) {
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Error decoding Certificate");
|
||||
ssl_error(card->ctx);
|
||||
r = SC_ERROR_INTERNAL;
|
||||
goto err;
|
||||
}
|
||||
apdu.datalen = length;
|
||||
apdu.lc = length;
|
||||
|
||||
sc_format_apdu_ex(card, &apdu, 0x2A, 0x00, 0xbe, (unsigned char *) cert, length, NULL, 0);
|
||||
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
if (r < 0)
|
||||
|
@ -1483,11 +1449,7 @@ static int eac_external_authenticate(sc_card_t *card,
|
|||
goto err;
|
||||
}
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x82, 0x00, 0x00);
|
||||
|
||||
apdu.data = signature;
|
||||
apdu.datalen = signature_len;
|
||||
apdu.lc = signature_len;
|
||||
sc_format_apdu_ex(card, &apdu, 0x82, 0x00, 0x00, signature, signature_len, NULL, 0);
|
||||
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
if (r < 0)
|
||||
|
@ -1702,10 +1664,7 @@ static int eac_gen_auth_ca(sc_card_t *card, const BUF_MEM *eph_pub_key,
|
|||
EAC_GEN_AUTH_CA_R *r_data = NULL;
|
||||
unsigned char *d = NULL;
|
||||
int r;
|
||||
unsigned char resp[maxresp];
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, ISO_GENERAL_AUTHENTICATE,
|
||||
0, 0);
|
||||
unsigned char resp[SC_MAX_EXT_APDU_RESP_SIZE];
|
||||
|
||||
c_data = EAC_GEN_AUTH_CA_C_new();
|
||||
if (!c_data) {
|
||||
|
@ -1727,14 +1686,10 @@ static int eac_gen_auth_ca(sc_card_t *card, const BUF_MEM *eph_pub_key,
|
|||
r = SC_ERROR_INTERNAL;
|
||||
goto err;
|
||||
}
|
||||
apdu.data = d;
|
||||
apdu.datalen = r;
|
||||
apdu.lc = r;
|
||||
sc_format_apdu_ex(card, &apdu, ISO_GENERAL_AUTHENTICATE, 0, 0, d, r, resp, sizeof resp);
|
||||
|
||||
sc_debug_hex(card->ctx, SC_LOG_DEBUG_SM, "General authenticate (Perform Key Agreement) command data", apdu.data, apdu.datalen);
|
||||
|
||||
apdu.resplen = sizeof resp;
|
||||
apdu.resp = resp;
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
if (r < 0)
|
||||
goto err;
|
||||
|
@ -2476,7 +2431,7 @@ int eac_pace_get_tries_left(sc_card_t *card,
|
|||
r = eac_mse_set_at_pace(card, 0, pin_id, 0, &sw1, &sw2);
|
||||
#else
|
||||
sc_apdu_t apdu;
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, ISO_MSE, 0xC1, 0xA4);
|
||||
sc_format_apdu_ex(card, &apdu, ISO_MSE, 0xC1, 0xA4, NULL, 0, NULL, 0);
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
sw1 = apdu.sw1;
|
||||
sw2 = apdu.sw2;
|
||||
|
|
|
@ -114,11 +114,8 @@ soc_info(sc_context_t *ctx, sc_card_t *card)
|
|||
{ NULL , 0 , 0 , 0 , NULL , NULL }
|
||||
};
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0x61, 0x00, 0x00);
|
||||
|
||||
sc_format_apdu_ex(card, &apdu, 0x61, 0x00, 0x00, NULL, 0, rbuf, sizeof rbuf);
|
||||
apdu.cla = 0x80;
|
||||
apdu.resp = rbuf;
|
||||
apdu.resplen = sizeof rbuf;
|
||||
|
||||
if (sc_transmit_apdu(card, &apdu) != SC_SUCCESS) {
|
||||
return;
|
||||
|
@ -239,7 +236,7 @@ soc_verify(sc_card_t *card, unsigned char p2)
|
|||
{
|
||||
int ok = 0;
|
||||
sc_apdu_t apdu;
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x20, 0x00, p2);
|
||||
sc_format_apdu_ex(card, &apdu, 0x20, 0x00, p2, NULL, 0, NULL, 0);
|
||||
SC_TEST_GOTO_ERR(card->ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
|
||||
sc_transmit_apdu(card, &apdu),
|
||||
"Verification failed");
|
||||
|
@ -275,7 +272,7 @@ soc_change(sc_card_t *card, unsigned char p1, unsigned char p2)
|
|||
{
|
||||
int ok = 0;
|
||||
sc_apdu_t apdu;
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x24, p1, p2);
|
||||
sc_format_apdu_ex(card, &apdu, 0x24, p1, p2, NULL, 0, NULL, 0);
|
||||
SC_TEST_GOTO_ERR(card->ctx, SC_LOG_DEBUG_VERBOSE_TOOL,
|
||||
sc_transmit_apdu(card, &apdu),
|
||||
"Changing secret failed");
|
||||
|
|
|
@ -156,11 +156,8 @@ static void verify(sc_card_t *card, const char *verify_str,
|
|||
sc_apdu_t apdu;
|
||||
int r;
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, ISO_VERIFY, 0x80, 0);
|
||||
sc_format_apdu_ex(card, &apdu, ISO_VERIFY, 0x80, 0, data, data_len, NULL, 0);
|
||||
apdu.cla = 0x80;
|
||||
apdu.data = data;
|
||||
apdu.datalen = data_len;
|
||||
apdu.lc = data_len;
|
||||
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
if (r < 0)
|
||||
|
|
Loading…
Reference in New Issue