Bugfixes:
- ssc is a BIGNUM, since its size can be up to 16 bytes (not 16 bits as before) - protected le is now encoded as octet string (not as unsigned integer anymore) - sc_format_asn1_entry was fet with wrong pointers (lebuf instead of *lebuf and formatted_data instead of *formatted_data Added some debug output. git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@60 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
115
ccid/pace.c
115
ccid/pace.c
@@ -737,18 +737,19 @@ int EstablishPACEChannel(sc_card_t *card, const __u8 *in,
|
||||
|
||||
/* XXX parse CHAT to check role of terminal */
|
||||
|
||||
sctx->authentication_ctx = pace_sm_ctx_create(info->protocol, k_mac,
|
||||
k_enc, pctx);
|
||||
if (!sctx->authentication_ctx) {
|
||||
r = SC_ERROR_INTERNAL;
|
||||
goto err;
|
||||
}
|
||||
sctx->authenticate = pace_sm_authenticate;
|
||||
sctx->cipher_ctx = sctx->authentication_ctx;
|
||||
sctx->encrypt = pace_sm_encrypt;
|
||||
sctx->decrypt = pace_sm_decrypt;
|
||||
sctx->padding_indicator = SM_ISO_PADDING;
|
||||
sctx->block_length = EVP_CIPHER_block_size(pctx->cipher);
|
||||
sctx->authentication_ctx = pace_sm_ctx_create(info->protocol, k_mac,
|
||||
k_enc, pctx);
|
||||
sctx->cipher_ctx = sctx->authentication_ctx;
|
||||
if (!sctx->authentication_ctx) {
|
||||
r = SC_ERROR_OUT_OF_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
r = reset_ssc(sctx);
|
||||
|
||||
err:
|
||||
if (info)
|
||||
@@ -844,31 +845,36 @@ int pace_test(sc_card_t *card)
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
static BUF_MEM *
|
||||
encoded_ssc(const uint16_t ssc, const PACE_CTX *ctx)
|
||||
static int
|
||||
encode_ssc(const BIGNUM *ssc, const PACE_CTX *ctx, u8 **encoded)
|
||||
{
|
||||
BUF_MEM * out = NULL;
|
||||
size_t len;
|
||||
u8 *p;
|
||||
size_t en_len, bn_len;
|
||||
|
||||
if (!ctx)
|
||||
goto err;
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
|
||||
len = EVP_CIPHER_block_size(ctx->cipher);
|
||||
out = BUF_MEM_create(len);
|
||||
if (!out || len < sizeof ssc)
|
||||
goto err;
|
||||
en_len = EVP_CIPHER_block_size(ctx->cipher);
|
||||
p = realloc(*encoded, en_len);
|
||||
if (!p)
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
*encoded = p;
|
||||
|
||||
/* Copy SSC to the end of buffer and fill the rest with 0 */
|
||||
memset(out->data, 0, len);
|
||||
memcpy(out->data + len - sizeof ssc, &ssc, sizeof ssc);
|
||||
bn_len = BN_num_bytes(ssc);
|
||||
|
||||
return out;
|
||||
if (bn_len <= en_len) {
|
||||
memset(*encoded, 0, en_len - bn_len);
|
||||
BN_bn2bin(ssc, *encoded + en_len - bn_len);
|
||||
} else {
|
||||
p = malloc(bn_len);
|
||||
if (!p)
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
BN_bn2bin(ssc, p);
|
||||
memcpy(*encoded, p + bn_len - en_len, en_len);
|
||||
free(p);
|
||||
}
|
||||
|
||||
err:
|
||||
if (out)
|
||||
BUF_MEM_free(out);
|
||||
|
||||
return NULL;
|
||||
return en_len;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -878,6 +884,7 @@ update_iv(struct sm_ctx *ctx)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
|
||||
BUF_MEM *sscbuf = NULL, *ivbuf = NULL;
|
||||
u8 *ssc = NULL;
|
||||
unsigned char *p;
|
||||
struct pace_sm_ctx *psmctx = ctx->cipher_ctx;
|
||||
int r;
|
||||
@@ -897,7 +904,14 @@ update_iv(struct sm_ctx *ctx)
|
||||
case NID_id_PACE_ECDH_IM_AES_CBC_CMAC_256:
|
||||
/* For AES decryption the IV is not needed,
|
||||
* so we always set it to the encryption IV=E(K_Enc, SSC) */
|
||||
sscbuf = encoded_ssc(psmctx->ssc, psmctx->ctx);
|
||||
r = encode_ssc(psmctx->ssc, psmctx->ctx, &ssc);
|
||||
if (r < 0)
|
||||
goto err;
|
||||
sscbuf = BUF_MEM_create_init(ssc, r);
|
||||
if (!sscbuf) {
|
||||
r = SC_ERROR_OUT_OF_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
ivbuf = PACE_encrypt(psmctx->ctx, psmctx->key_enc, sscbuf);
|
||||
if (!ivbuf) {
|
||||
r = SC_ERROR_INTERNAL;
|
||||
@@ -908,8 +922,8 @@ update_iv(struct sm_ctx *ctx)
|
||||
r = SC_ERROR_OUT_OF_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
memcpy(p, ivbuf->data, ivbuf->length);
|
||||
psmctx->ctx->iv = p;
|
||||
memcpy(psmctx->ctx->iv, ivbuf->data, ivbuf->length);
|
||||
break;
|
||||
case NID_id_PACE_DH_GM_3DES_CBC_CBC:
|
||||
case NID_id_PACE_DH_IM_3DES_CBC_CBC:
|
||||
@@ -942,10 +956,10 @@ increment_ssc(struct sm_ctx *ctx)
|
||||
|
||||
struct pace_sm_ctx *psmctx = ctx->cipher_ctx;
|
||||
|
||||
if (psmctx->ssc == 0) {
|
||||
psmctx->ssc = 2;
|
||||
if (BN_is_zero(psmctx->ssc)) {
|
||||
BN_set_word(psmctx->ssc, 2);
|
||||
} else {
|
||||
psmctx->ssc++;
|
||||
BN_add_word(psmctx->ssc, 1);
|
||||
}
|
||||
|
||||
return update_iv(ctx);
|
||||
@@ -958,7 +972,7 @@ reset_ssc(struct sm_ctx *ctx)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
|
||||
struct pace_sm_ctx *psmctx = ctx->cipher_ctx;
|
||||
psmctx->ssc = 0;
|
||||
BN_zero(psmctx->ssc);
|
||||
|
||||
return update_iv(ctx);
|
||||
}
|
||||
@@ -995,9 +1009,8 @@ int pace_sm_encrypt(sc_card_t *card, const struct sm_ctx *ctx,
|
||||
r = SC_ERROR_OUT_OF_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
memcpy(p, encbuf->data, encbuf->length);
|
||||
|
||||
*enc = p;
|
||||
memcpy(*enc, encbuf->data, encbuf->length);
|
||||
r = encbuf->length;
|
||||
|
||||
err:
|
||||
@@ -1036,9 +1049,8 @@ int pace_sm_decrypt(sc_card_t *card, const struct sm_ctx *ctx,
|
||||
r = SC_ERROR_OUT_OF_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
memcpy(p, databuf->data, databuf->length);
|
||||
|
||||
*data = p;
|
||||
memcpy(*data, databuf->data, databuf->length);
|
||||
r = databuf->length;
|
||||
|
||||
err:
|
||||
@@ -1056,9 +1068,8 @@ int pace_sm_authenticate(sc_card_t *card, const struct sm_ctx *ctx,
|
||||
const u8 *data, size_t datalen, u8 **macdata)
|
||||
{
|
||||
BUF_MEM *databuf = NULL, *macbuf = NULL;
|
||||
u8 *p = NULL;
|
||||
u8 *p = NULL, *ssc = NULL;
|
||||
int r;
|
||||
size_t oldlen;
|
||||
|
||||
if (!ctx || !ctx->cipher_ctx) {
|
||||
r = SC_ERROR_INVALID_ARGUMENTS;
|
||||
@@ -1066,22 +1077,29 @@ int pace_sm_authenticate(sc_card_t *card, const struct sm_ctx *ctx,
|
||||
}
|
||||
struct pace_sm_ctx *psmctx = ctx->cipher_ctx;
|
||||
|
||||
databuf = encoded_ssc(psmctx->ssc, psmctx->ctx);
|
||||
r = encode_ssc(psmctx->ssc, psmctx->ctx, &ssc);
|
||||
if (r < 0) {
|
||||
sc_error(card->ctx, "Could not get send sequence counter\n");
|
||||
goto err;
|
||||
}
|
||||
bin_log(card->ctx, "Encoded Send Sequence Counter",
|
||||
ssc, r);
|
||||
|
||||
databuf = BUF_MEM_create(r + datalen);
|
||||
if (!databuf) {
|
||||
r = SC_ERROR_INTERNAL;
|
||||
r = SC_ERROR_OUT_OF_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
oldlen = databuf->length;
|
||||
if (!BUF_MEM_grow(databuf, oldlen + datalen)) {
|
||||
r = SC_ERROR_INTERNAL;
|
||||
goto err;
|
||||
}
|
||||
memcpy(databuf->data + oldlen, data, datalen);
|
||||
databuf->length = oldlen + datalen;
|
||||
memcpy(databuf->data, ssc, r);
|
||||
memcpy(databuf->data + r, data, datalen);
|
||||
databuf->length = r + datalen;
|
||||
bin_log(card->ctx, "Data to authenticate (PACE)",
|
||||
(u8 *) databuf->data, databuf->length);
|
||||
|
||||
macbuf = PACE_authenticate(psmctx->ctx, psmctx->protocol,
|
||||
psmctx->key_mac, databuf);
|
||||
if (!macbuf) {
|
||||
sc_error(card->ctx, "Could not get MAC\n");
|
||||
r = SC_ERROR_INTERNAL;
|
||||
goto err;
|
||||
}
|
||||
@@ -1091,9 +1109,8 @@ int pace_sm_authenticate(sc_card_t *card, const struct sm_ctx *ctx,
|
||||
r = SC_ERROR_OUT_OF_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
memcpy(p, macbuf->data, macbuf->length);
|
||||
|
||||
*macdata = p;
|
||||
memcpy(*macdata, macbuf->data, macbuf->length);
|
||||
r = macbuf->length;
|
||||
|
||||
err:
|
||||
@@ -1103,6 +1120,8 @@ err:
|
||||
}
|
||||
if (macbuf)
|
||||
BUF_MEM_free(macbuf);
|
||||
if (ssc)
|
||||
free(ssc);
|
||||
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_ERROR, r);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <linux/usb/ch9.h>
|
||||
#include <opensc/opensc.h>
|
||||
#include <openssl/pace.h>
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -44,7 +45,7 @@ extern "C" {
|
||||
struct pace_sm_ctx {
|
||||
int protocol;
|
||||
/* XXX SSC is up to 16 Bytes long, not only 16 Bits */
|
||||
uint16_t ssc;
|
||||
BIGNUM *ssc;
|
||||
const BUF_MEM *key_mac;
|
||||
const BUF_MEM *key_enc;
|
||||
PACE_CTX *ctx;
|
||||
|
||||
@@ -28,6 +28,12 @@ pace_sm_ctx_create(int protocol, const BUF_MEM *key_mac,
|
||||
if (!out)
|
||||
return NULL;
|
||||
|
||||
out->ssc = BN_new();
|
||||
if (!out->ssc) {
|
||||
free(out);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
out->key_enc = key_enc;
|
||||
out->key_mac = key_mac;
|
||||
out->protocol = protocol;
|
||||
@@ -40,6 +46,8 @@ void
|
||||
pace_sm_ctx_free(struct pace_sm_ctx *ctx)
|
||||
{
|
||||
if (ctx) {
|
||||
if (ctx->ssc)
|
||||
BN_clear_free(ctx->ssc);
|
||||
free(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
131
ccid/sm.c
131
ccid/sm.c
@@ -26,11 +26,11 @@
|
||||
|
||||
static const struct sc_asn1_entry c_sm_capdu[] = {
|
||||
{ "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 },
|
||||
{ "Protected Le",
|
||||
SC_ASN1_INTEGER , SC_ASN1_CTX|0x17, SC_ASN1_OPTIONAL|SC_ASN1_UNSIGNED, NULL, NULL },
|
||||
SC_ASN1_OCTET_STRING, SC_ASN1_CTX|0x17, SC_ASN1_OPTIONAL, 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 }
|
||||
};
|
||||
|
||||
@@ -49,9 +49,9 @@ void bin_log(sc_context_t *ctx, const char *label, const u8 *data, size_t len)
|
||||
char buf[1024];
|
||||
|
||||
sc_hex_dump(ctx, data, len, buf, sizeof buf);
|
||||
sc_debug(ctx, "%s (%u bytes):\n%s"
|
||||
sc_debug(ctx, "%s (%u byte%s):\n%s"
|
||||
"======================================================================",
|
||||
label, len, buf);
|
||||
label, len, len==1?"":"s", buf);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -73,12 +73,12 @@ add_iso_pad(const u8 *data, size_t datalen, int block_size, u8 **padded)
|
||||
if (*padded != data)
|
||||
memcpy(p, data, datalen);
|
||||
|
||||
*padded = p;
|
||||
|
||||
/* now add iso padding */
|
||||
memset(p + datalen, 0x80, 1);
|
||||
memset(p + datalen + 1, 0, p_len - datalen - 1);
|
||||
|
||||
*padded = p;
|
||||
|
||||
return p_len;
|
||||
}
|
||||
|
||||
@@ -94,8 +94,8 @@ add_padding(const struct sm_ctx *ctx, const u8 *data, size_t datalen,
|
||||
p = realloc(*padded, datalen);
|
||||
if (!p)
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
memcpy(p, data, datalen);
|
||||
*padded = p;
|
||||
memcpy(*padded, data, datalen);
|
||||
}
|
||||
return datalen;
|
||||
case SM_ISO_PADDING:
|
||||
@@ -131,32 +131,39 @@ int no_padding(u8 padding_indicator, const u8 *data, size_t datalen)
|
||||
return len;
|
||||
}
|
||||
|
||||
static u8 * format_le(size_t le_len, size_t le, struct sc_asn1_entry *le_entry)
|
||||
static int format_le(size_t le, struct sc_asn1_entry *le_entry,
|
||||
u8 **lebuf, size_t *le_len)
|
||||
{
|
||||
u8 * lebuf = malloc(le_len);
|
||||
if (lebuf) {
|
||||
switch (le_len) {
|
||||
case 1:
|
||||
lebuf[0] = le;
|
||||
break;
|
||||
case 2:
|
||||
lebuf[0] = htons(le) >> 8;
|
||||
lebuf[1] = htons(le) & 0xff;
|
||||
break;
|
||||
case 3:
|
||||
lebuf[0] = 0x00;
|
||||
lebuf[1] = htons(le) >> 8;
|
||||
lebuf[2] = htons(le) & 0xff;
|
||||
break;
|
||||
default:
|
||||
free(lebuf);
|
||||
return NULL;
|
||||
}
|
||||
u8 *p;
|
||||
|
||||
sc_format_asn1_entry(le_entry, lebuf, &le_len, SC_ASN1_PRESENT);
|
||||
if (!lebuf || !le_len)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
|
||||
p = realloc(*lebuf, *le_len);
|
||||
if (!p)
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
switch (*le_len) {
|
||||
case 1:
|
||||
p[0] = le;
|
||||
break;
|
||||
case 2:
|
||||
p[0] = htons(le) >> 8;
|
||||
p[1] = htons(le) & 0xff;
|
||||
break;
|
||||
case 3:
|
||||
p[0] = 0x00;
|
||||
p[1] = htons(le) >> 8;
|
||||
p[2] = htons(le) & 0xff;
|
||||
break;
|
||||
default:
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
*lebuf = p;
|
||||
|
||||
return lebuf;
|
||||
sc_format_asn1_entry(le_entry, *lebuf, le_len, SC_ASN1_PRESENT);
|
||||
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
static int prefix_buf(u8 prefix, u8 *buf, size_t buflen, u8 **cat)
|
||||
@@ -198,7 +205,6 @@ static int format_data(sc_card_t *card, const struct sm_ctx *ctx,
|
||||
goto err;
|
||||
pad_data_len = r;
|
||||
|
||||
printf("%d\n", pad_data_len);
|
||||
r = ctx->encrypt(card, ctx, pad_data, pad_data_len, formatted_data);
|
||||
if (r < 0) {
|
||||
sc_error(card->ctx, "Could not encrypt the data");
|
||||
@@ -211,7 +217,7 @@ static int format_data(sc_card_t *card, const struct sm_ctx *ctx,
|
||||
|
||||
*formatted_data_len = r;
|
||||
sc_format_asn1_entry(formatted_encrypted_data_entry,
|
||||
formatted_data, formatted_data_len, SC_ASN1_PRESENT);
|
||||
*formatted_data, formatted_data_len, SC_ASN1_PRESENT);
|
||||
|
||||
r = SC_SUCCESS;
|
||||
|
||||
@@ -249,7 +255,7 @@ static int sm_encrypt(const struct sm_ctx *ctx, sc_card_t *card,
|
||||
struct sc_asn1_entry sm_capdu[4];
|
||||
u8 *p, *le = NULL, *sm_data = NULL, *fdata = NULL, *mac_data = NULL,
|
||||
*asn1 = NULL, *mac = NULL;
|
||||
size_t sm_data_len, fdata_len, mac_data_len, asn1_len, mac_len;
|
||||
size_t sm_data_len, fdata_len, mac_data_len, asn1_len, mac_len, le_len;
|
||||
int r;
|
||||
|
||||
if (!apdu || !ctx || !card || !card->slot || !sm_apdu) {
|
||||
@@ -280,31 +286,33 @@ static int sm_encrypt(const struct sm_ctx *ctx, sc_card_t *card,
|
||||
case SC_APDU_CASE_1:
|
||||
break;
|
||||
case SC_APDU_CASE_2_SHORT:
|
||||
le = format_le(1, apdu->le, sm_capdu + 1);
|
||||
if (!le) {
|
||||
le_len = 1;
|
||||
r = format_le(apdu->le, sm_capdu + 1, &le, &le_len);
|
||||
if (r < 0) {
|
||||
sc_error(card->ctx, "Could not format Le of SM apdu");
|
||||
r = SC_ERROR_WRONG_LENGTH;
|
||||
goto err;
|
||||
}
|
||||
bin_log(card->ctx, "Protected Le (plain)", le, le_len);
|
||||
break;
|
||||
case SC_APDU_CASE_2_EXT:
|
||||
if (card->slot->active_protocol == SC_PROTO_T0) {
|
||||
/* T0 extended APDUs look just like short APDUs */
|
||||
le = format_le(1, apdu->le, sm_capdu + 1);
|
||||
if (!le) {
|
||||
le_len = 1;
|
||||
r = format_le(apdu->le, sm_capdu + 1, &le, &le_len);
|
||||
if (r < 0) {
|
||||
sc_error(card->ctx, "Could not format Le of SM apdu");
|
||||
r = SC_ERROR_WRONG_LENGTH;
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
/* in case of T1 always use 3 bytes for length */
|
||||
le = format_le(3, apdu->le, sm_capdu + 1);
|
||||
if (!le) {
|
||||
le_len = 3;
|
||||
r = format_le(apdu->le, sm_capdu + 1, &le, &le_len);
|
||||
if (r < 0) {
|
||||
sc_error(card->ctx, "Could not format Le of SM apdu");
|
||||
r = SC_ERROR_WRONG_LENGTH;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
bin_log(card->ctx, "Protected Le (plain)", le, le_len);
|
||||
break;
|
||||
case SC_APDU_CASE_3_SHORT:
|
||||
case SC_APDU_CASE_3_EXT:
|
||||
@@ -314,16 +322,19 @@ static int sm_encrypt(const struct sm_ctx *ctx, sc_card_t *card,
|
||||
sc_error(card->ctx, "Could not format data of SM apdu");
|
||||
goto err;
|
||||
}
|
||||
bin_log(card->ctx, "Padding-content indicator followed by cryptogram (plain)",
|
||||
fdata, fdata_len);
|
||||
break;
|
||||
case SC_APDU_CASE_4_SHORT:
|
||||
/* in case of T0 no Le byte is added */
|
||||
if (card->slot->active_protocol != SC_PROTO_T0) {
|
||||
le = format_le(1, apdu->le, sm_capdu + 1);
|
||||
if (!le) {
|
||||
le_len = 1;
|
||||
r = format_le(apdu->le, sm_capdu + 1, &le, &le_len);
|
||||
if (r < 0) {
|
||||
sc_error(card->ctx, "Could not format Le of SM apdu");
|
||||
r = SC_ERROR_WRONG_LENGTH;
|
||||
goto err;
|
||||
}
|
||||
bin_log(card->ctx, "Protected Le (plain)", le, le_len);
|
||||
}
|
||||
|
||||
r = format_data(card, ctx, apdu->data, apdu->datalen,
|
||||
@@ -332,6 +343,8 @@ static int sm_encrypt(const struct sm_ctx *ctx, sc_card_t *card,
|
||||
sc_error(card->ctx, "Could not format data of SM apdu");
|
||||
goto err;
|
||||
}
|
||||
bin_log(card->ctx, "Padding-content indicator followed by cryptogram (plain)",
|
||||
fdata, fdata_len);
|
||||
break;
|
||||
case SC_APDU_CASE_4_EXT:
|
||||
if (card->slot->active_protocol == SC_PROTO_T0) {
|
||||
@@ -341,12 +354,13 @@ static int sm_encrypt(const struct sm_ctx *ctx, sc_card_t *card,
|
||||
} else {
|
||||
/* only 2 bytes are use to specify the length of the
|
||||
* expected data */
|
||||
le = format_le(2, apdu->le, sm_capdu + 1);
|
||||
if (!le) {
|
||||
le_len = 2;
|
||||
r = format_le(apdu->le, sm_capdu + 1, &le, &le_len);
|
||||
if (r < 0) {
|
||||
sc_error(card->ctx, "Could not format Le of SM apdu");
|
||||
r = SC_ERROR_WRONG_LENGTH;
|
||||
goto err;
|
||||
}
|
||||
bin_log(card->ctx, "Protected Le (plain)", le, le_len);
|
||||
}
|
||||
|
||||
r = format_data(card, ctx, apdu->data, apdu->datalen,
|
||||
@@ -355,6 +369,8 @@ static int sm_encrypt(const struct sm_ctx *ctx, sc_card_t *card,
|
||||
sc_error(card->ctx, "Could not format data of SM apdu");
|
||||
goto err;
|
||||
}
|
||||
bin_log(card->ctx, "Padding-content indicator followed by cryptogram (plain)",
|
||||
fdata, fdata_len);
|
||||
break;
|
||||
default:
|
||||
sc_error(card->ctx, "Unhandled apdu case");
|
||||
@@ -376,6 +392,12 @@ static int sm_encrypt(const struct sm_ctx *ctx, sc_card_t *card,
|
||||
memcpy(mac_data + mac_data_len, asn1, asn1_len);
|
||||
mac_data_len += asn1_len;
|
||||
r = add_padding(ctx, mac_data, mac_data_len, &mac_data);
|
||||
if (r < 0) {
|
||||
goto err;
|
||||
}
|
||||
mac_data_len = r;
|
||||
bin_log(card->ctx, "Data to authenticate", mac_data, mac_data_len);
|
||||
|
||||
r = ctx->authenticate(card, ctx, mac_data, mac_data_len,
|
||||
&mac);
|
||||
if (r < 0) {
|
||||
@@ -383,9 +405,9 @@ static int sm_encrypt(const struct sm_ctx *ctx, sc_card_t *card,
|
||||
goto err;
|
||||
}
|
||||
mac_len = r;
|
||||
bin_log(card->ctx, "mac", mac, mac_len);
|
||||
sc_format_asn1_entry(sm_capdu + 2, mac, &mac_len,
|
||||
SC_ASN1_PRESENT);
|
||||
bin_log(card->ctx, "Cryptographic Checksum (plain)", mac, mac_len);
|
||||
|
||||
|
||||
/* format SM apdu */
|
||||
@@ -397,7 +419,7 @@ static int sm_encrypt(const struct sm_ctx *ctx, sc_card_t *card,
|
||||
sm_apdu->lc = sm_apdu->datalen;
|
||||
sm_apdu->le = 0;
|
||||
sm_apdu->cse = SC_APDU_CASE_4;
|
||||
bin_log(card->ctx, "sm apdu data", sm_apdu->data, sm_apdu->datalen);
|
||||
bin_log(card->ctx, "ASN.1 encoded APDU data", sm_apdu->data, sm_apdu->datalen);
|
||||
|
||||
err:
|
||||
if (fdata) {
|
||||
@@ -483,9 +505,14 @@ static int sm_decrypt(const struct sm_ctx *ctx, sc_card_t *card,
|
||||
apdu->resp = data;
|
||||
apdu->resplen = r;
|
||||
} else {
|
||||
apdu->resplen = r;
|
||||
apdu->resplen = 0;
|
||||
}
|
||||
|
||||
sc_debug(card->ctx, "Decrypted APDU sw1=%02x sw2=%02x",
|
||||
apdu->sw1, apdu->sw2);
|
||||
bin_log(card->ctx, "Decrypted APDU response data",
|
||||
apdu->resp, apdu->resplen);
|
||||
|
||||
/* XXX verify mac */
|
||||
|
||||
r = SC_SUCCESS;
|
||||
@@ -509,7 +536,6 @@ 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.");
|
||||
bin_log(card->ctx, "SM APDU data", sm_apdu.data, sm_apdu.datalen);
|
||||
|
||||
sm_apdu.resplen = sizeof *buf;
|
||||
sm_apdu.resp = buf;
|
||||
@@ -520,7 +546,6 @@ int sm_transmit_apdu(const struct sm_ctx *sctx, sc_card_t *card,
|
||||
"Card returned error.");
|
||||
SC_TEST_RET(card->ctx, sm_decrypt(sctx, card, &sm_apdu, apdu),
|
||||
"Could not decrypt APDU.");
|
||||
bin_log(card->ctx, "SM APDU response", apdu->resp, apdu->resplen);
|
||||
|
||||
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_ERROR, SC_SUCCESS);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user