- decryption of sm apdu now working. verification of mac still missing.
git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@71 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
@@ -828,7 +828,7 @@ err:
|
|||||||
|
|
||||||
int pace_test(sc_card_t *card)
|
int pace_test(sc_card_t *card)
|
||||||
{
|
{
|
||||||
__u8 in[16];
|
__u8 in[16], buf[SC_MAX_APDU_BUFFER_SIZE - 2];
|
||||||
__u8 *out = NULL;
|
__u8 *out = NULL;
|
||||||
size_t outlen;
|
size_t outlen;
|
||||||
struct sm_ctx sctx;
|
struct sm_ctx sctx;
|
||||||
@@ -863,6 +863,8 @@ int pace_test(sc_card_t *card)
|
|||||||
apdu.datalen = 2;
|
apdu.datalen = 2;
|
||||||
apdu.lc = apdu.datalen;
|
apdu.lc = apdu.datalen;
|
||||||
apdu.le = 0x00;
|
apdu.le = 0x00;
|
||||||
|
apdu.resp = buf;
|
||||||
|
apdu.resplen = sizeof buf;
|
||||||
apdu.cse = SC_APDU_CASE_4_SHORT;
|
apdu.cse = SC_APDU_CASE_4_SHORT;
|
||||||
|
|
||||||
SC_TEST_RET(card->ctx, pace_transmit_apdu(&sctx, card, &apdu),
|
SC_TEST_RET(card->ctx, pace_transmit_apdu(&sctx, card, &apdu),
|
||||||
|
|||||||
48
ccid/sm.c
48
ccid/sm.c
@@ -36,11 +36,11 @@ static const struct sc_asn1_entry c_sm_capdu[] = {
|
|||||||
|
|
||||||
static const struct sc_asn1_entry c_sm_rapdu[] = {
|
static const struct sc_asn1_entry c_sm_rapdu[] = {
|
||||||
{ "Padding-content indicator followed by cryptogram" ,
|
{ "Padding-content indicator followed by cryptogram" ,
|
||||||
SC_ASN1_OCTET_STRING, SC_ASN1_CTX|0x07, SC_ASN1_OPTIONAL , NULL, NULL },
|
SC_ASN1_OCTET_STRING, SC_ASN1_CTX|0x07, SC_ASN1_OPTIONAL, NULL, NULL },
|
||||||
{ "Processing Status",
|
{ "Processing Status",
|
||||||
SC_ASN1_INTEGER , SC_ASN1_CTX|0x19, SC_ASN1_OPTIONAL|SC_ASN1_UNSIGNED, NULL, NULL },
|
SC_ASN1_OCTET_STRING, SC_ASN1_CTX|0x19, 0 , NULL, NULL },
|
||||||
{ "Cryptographic Checksum",
|
{ "Cryptographic Checksum",
|
||||||
SC_ASN1_OCTET_STRING, SC_ASN1_CTX|0x0E, SC_ASN1_OPTIONAL , NULL, NULL },
|
SC_ASN1_OCTET_STRING, SC_ASN1_CTX|0x0E, SC_ASN1_OPTIONAL, NULL, NULL },
|
||||||
{ NULL, 0, 0, 0, NULL, NULL }
|
{ NULL, 0, 0, 0, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -270,8 +270,6 @@ static int sm_encrypt(const struct sm_ctx *ctx, sc_card_t *card,
|
|||||||
sc_copy_asn1_entry(c_sm_capdu, sm_capdu);
|
sc_copy_asn1_entry(c_sm_capdu, sm_capdu);
|
||||||
|
|
||||||
sm_apdu->sensitive = 0;
|
sm_apdu->sensitive = 0;
|
||||||
sm_apdu->resp = apdu->resp;
|
|
||||||
sm_apdu->resplen = apdu->resplen;
|
|
||||||
sm_apdu->control = apdu->control;
|
sm_apdu->control = apdu->control;
|
||||||
sm_apdu->flags = apdu->flags;
|
sm_apdu->flags = apdu->flags;
|
||||||
sm_apdu->cla = 0x0C;
|
sm_apdu->cla = 0x0C;
|
||||||
@@ -455,7 +453,7 @@ static int sm_decrypt(const struct sm_ctx *ctx, sc_card_t *card,
|
|||||||
int r;
|
int r;
|
||||||
struct sc_asn1_entry sm_rapdu[4];
|
struct sc_asn1_entry sm_rapdu[4];
|
||||||
struct sc_asn1_entry my_sm_rapdu[4];
|
struct sc_asn1_entry my_sm_rapdu[4];
|
||||||
u8 sw[2], mac[256], fdata[1024];
|
u8 sw[2], mac[8], fdata[SC_MAX_APDU_BUFFER_SIZE];
|
||||||
size_t sw_len = sizeof sw, mac_len = sizeof mac, fdata_len = sizeof fdata,
|
size_t sw_len = sizeof sw, mac_len = sizeof mac, fdata_len = sizeof fdata,
|
||||||
buf_len, asn1_len;
|
buf_len, asn1_len;
|
||||||
const u8 *buf;
|
const u8 *buf;
|
||||||
@@ -466,7 +464,7 @@ static int sm_decrypt(const struct sm_ctx *ctx, sc_card_t *card,
|
|||||||
sc_format_asn1_entry(sm_rapdu + 1, sw, &sw_len, 0);
|
sc_format_asn1_entry(sm_rapdu + 1, sw, &sw_len, 0);
|
||||||
sc_format_asn1_entry(sm_rapdu + 2, mac, &mac_len, 0);
|
sc_format_asn1_entry(sm_rapdu + 2, mac, &mac_len, 0);
|
||||||
|
|
||||||
r = sc_asn1_decode(card->ctx, sm_rapdu, apdu->resp, apdu->resplen,
|
r = sc_asn1_decode(card->ctx, sm_rapdu, sm_apdu->resp, sm_apdu->resplen,
|
||||||
&buf, &buf_len);
|
&buf, &buf_len);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto err;
|
goto err;
|
||||||
@@ -477,9 +475,10 @@ static int sm_decrypt(const struct sm_ctx *ctx, sc_card_t *card,
|
|||||||
|
|
||||||
|
|
||||||
if (sm_rapdu[2].flags & SC_ASN1_PRESENT) {
|
if (sm_rapdu[2].flags & SC_ASN1_PRESENT) {
|
||||||
|
/* copy from sm_apdu to my_sm_apdu, but leave mac at default */
|
||||||
sc_copy_asn1_entry(sm_rapdu, my_sm_rapdu);
|
sc_copy_asn1_entry(sm_rapdu, my_sm_rapdu);
|
||||||
|
sc_copy_asn1_entry(&c_sm_rapdu[2], &my_sm_rapdu[2]);
|
||||||
|
|
||||||
sc_format_asn1_entry(my_sm_rapdu + 2, NULL, NULL, 0);
|
|
||||||
r = sc_asn1_encode(card->ctx, my_sm_rapdu, &asn1, &asn1_len);
|
r = sc_asn1_encode(card->ctx, my_sm_rapdu, &asn1, &asn1_len);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto err;
|
goto err;
|
||||||
@@ -488,10 +487,16 @@ static int sm_decrypt(const struct sm_ctx *ctx, sc_card_t *card,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* XXX */
|
||||||
r = ctx->verify_authentication(card, ctx, mac, mac_len,
|
r = ctx->verify_authentication(card, ctx, mac, mac_len,
|
||||||
mac_data, r);
|
mac_data, r);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
r = SC_ERROR_ASN1_OBJECT_NOT_FOUND;
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -509,13 +514,30 @@ static int sm_decrypt(const struct sm_ctx *ctx, sc_card_t *card,
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
memcpy(apdu, sm_apdu, sizeof *apdu);
|
if (apdu->resplen < r) {
|
||||||
apdu->resp = data;
|
sc_error(card->ctx, "Response of SM APDU too long");
|
||||||
|
r = SC_ERROR_OUT_OF_MEMORY;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
memcpy(apdu->resp, data, r);
|
||||||
apdu->resplen = r;
|
apdu->resplen = r;
|
||||||
} else {
|
} else {
|
||||||
apdu->resplen = 0;
|
apdu->resplen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sm_rapdu[1].flags & SC_ASN1_PRESENT) {
|
||||||
|
if (sw_len != 2) {
|
||||||
|
sc_error(card->ctx, "Length of processing status bytes must be 2");
|
||||||
|
r = SC_ERROR_ASN1_END_OF_CONTENTS;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
apdu->sw1 = sw[0];
|
||||||
|
apdu->sw2 = sw[1];
|
||||||
|
} else {
|
||||||
|
r = SC_ERROR_ASN1_OBJECT_NOT_FOUND;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
sc_debug(card->ctx, "Decrypted APDU sw1=%02x sw2=%02x",
|
sc_debug(card->ctx, "Decrypted APDU sw1=%02x sw2=%02x",
|
||||||
apdu->sw1, apdu->sw2);
|
apdu->sw1, apdu->sw2);
|
||||||
bin_log(card->ctx, "Decrypted APDU response data",
|
bin_log(card->ctx, "Decrypted APDU response data",
|
||||||
@@ -550,11 +572,11 @@ int sm_transmit_apdu(const struct sm_ctx *sctx, sc_card_t *card,
|
|||||||
SC_TEST_RET(card->ctx, sm_encrypt(sctx, card, apdu, &sm_apdu),
|
SC_TEST_RET(card->ctx, sm_encrypt(sctx, card, apdu, &sm_apdu),
|
||||||
"Could not encrypt APDU.");
|
"Could not encrypt APDU.");
|
||||||
SC_TEST_RET(card->ctx, my_transmit_apdu(card, &sm_apdu),
|
SC_TEST_RET(card->ctx, my_transmit_apdu(card, &sm_apdu),
|
||||||
"Could not send SM APDU.");
|
"Could not transmit SM APDU.");
|
||||||
SC_TEST_RET(card->ctx, sc_check_sw(card, sm_apdu.sw1, sm_apdu.sw2),
|
|
||||||
"Card returned error.");
|
|
||||||
SC_TEST_RET(card->ctx, sm_decrypt(sctx, card, &sm_apdu, apdu),
|
SC_TEST_RET(card->ctx, sm_decrypt(sctx, card, &sm_apdu, apdu),
|
||||||
"Could not decrypt APDU.");
|
"Could not decrypt APDU.");
|
||||||
|
SC_TEST_RET(card->ctx, sc_check_sw(card, apdu->sw1, apdu->sw2),
|
||||||
|
"Card returned error.");
|
||||||
|
|
||||||
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_ERROR, SC_SUCCESS);
|
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_ERROR, SC_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user