From 985590c3a87e9c55482d984ab3cdd7dc2ab737a6 Mon Sep 17 00:00:00 2001 From: frankmorgner Date: Mon, 12 Apr 2010 21:22:39 +0000 Subject: [PATCH] - 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 --- ccid/pace.c | 4 +++- ccid/sm.c | 48 +++++++++++++++++++++++++++++++++++------------- 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/ccid/pace.c b/ccid/pace.c index 2eb1d0e..939f715 100644 --- a/ccid/pace.c +++ b/ccid/pace.c @@ -828,7 +828,7 @@ err: int pace_test(sc_card_t *card) { - __u8 in[16]; + __u8 in[16], buf[SC_MAX_APDU_BUFFER_SIZE - 2]; __u8 *out = NULL; size_t outlen; struct sm_ctx sctx; @@ -863,6 +863,8 @@ int pace_test(sc_card_t *card) apdu.datalen = 2; apdu.lc = apdu.datalen; apdu.le = 0x00; + apdu.resp = buf; + apdu.resplen = sizeof buf; apdu.cse = SC_APDU_CASE_4_SHORT; SC_TEST_RET(card->ctx, pace_transmit_apdu(&sctx, card, &apdu), diff --git a/ccid/sm.c b/ccid/sm.c index 623f6b4..e18a66f 100644 --- a/ccid/sm.c +++ b/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[] = { { "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", - 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", - 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 } }; @@ -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); sm_apdu->sensitive = 0; - sm_apdu->resp = apdu->resp; - sm_apdu->resplen = apdu->resplen; sm_apdu->control = apdu->control; sm_apdu->flags = apdu->flags; sm_apdu->cla = 0x0C; @@ -455,7 +453,7 @@ static int sm_decrypt(const struct sm_ctx *ctx, sc_card_t *card, int r; struct sc_asn1_entry 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, buf_len, asn1_len; 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 + 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); if (r < 0) 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) { + /* 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(&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); if (r < 0) goto err; @@ -488,10 +487,16 @@ static int sm_decrypt(const struct sm_ctx *ctx, sc_card_t *card, goto err; } +#if 0 + /* XXX */ r = ctx->verify_authentication(card, ctx, mac, mac_len, mac_data, r); if (r < 0) 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) goto err; - memcpy(apdu, sm_apdu, sizeof *apdu); - apdu->resp = data; + if (apdu->resplen < r) { + 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; } else { 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", apdu->sw1, apdu->sw2); 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), "Could not encrypt APDU."); SC_TEST_RET(card->ctx, my_transmit_apdu(card, &sm_apdu), - "Could not send SM APDU."); - SC_TEST_RET(card->ctx, sc_check_sw(card, sm_apdu.sw1, sm_apdu.sw2), - "Card returned error."); + "Could not transmit SM APDU."); SC_TEST_RET(card->ctx, sm_decrypt(sctx, card, &sm_apdu, 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); }