implemented sc_format_apdu_ex

This commit is contained in:
Frank Morgner 2019-01-16 07:35:58 +01:00
parent 155b197932
commit 27526de021
8 changed files with 99 additions and 87 deletions

View File

@ -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;

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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");

View File

@ -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)