- dropped pace_transmit_apdu in favour of a solution with sm_transmit_apdu.
post_transmit and pre_transmit can be used to perform actions before encrypting/decrypting a sm apdu (such as incrementing the ssc for pace). - fixed ssc problems. encrypted communication with more than one apdu (e.g. resuming the pin) is now working. - fixed uninitialized pointer in sm_decrypt git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@131 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
@@ -166,7 +166,7 @@ int pace_translate_apdus(struct sm_ctx *sctx, sc_card_t *card)
|
|||||||
apdu.resp = buf;
|
apdu.resp = buf;
|
||||||
apdu.resplen = sizeof(buf);
|
apdu.resplen = sizeof(buf);
|
||||||
|
|
||||||
r = pace_transmit_apdu(sctx, card, &apdu);
|
r = sm_transmit_apdu(sctx, card, &apdu);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
sc_error(card->ctx, "Could not send APDU: %s", sc_strerror(r));
|
sc_error(card->ctx, "Could not send APDU: %s", sc_strerror(r));
|
||||||
continue;
|
continue;
|
||||||
@@ -307,18 +307,13 @@ main (int argc, char **argv)
|
|||||||
printf("Established PACE channel with CAN in %.0fs.\n",
|
printf("Established PACE channel with CAN in %.0fs.\n",
|
||||||
difftime(t_end, t_start));
|
difftime(t_end, t_start));
|
||||||
|
|
||||||
/*i = pace_reset_retry_counter(&tmpctx, card, PACE_PIN, 0, NULL, 0);*/
|
|
||||||
/*if (i < 0)*/
|
|
||||||
/*goto err;*/
|
|
||||||
/*printf("Resumed PIN.\n");*/
|
|
||||||
|
|
||||||
i = pace_get_channel(&tmpctx, card,
|
i = pace_get_channel(&tmpctx, card,
|
||||||
PACE_PIN, pin, pin ? strlen(pin) : 0,
|
PACE_PIN, pin, pin ? strlen(pin) : 0,
|
||||||
&channeldata, &channeldatalen, &sctx);
|
&channeldata, &channeldatalen, &sctx);
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
goto err;
|
goto err;
|
||||||
t_start = time(NULL);
|
t_start = time(NULL);
|
||||||
printf("Established PACE channel with PIN in %.0fs.\n",
|
printf("Established PACE channel with PIN in %.0fs. PIN resumed.\n",
|
||||||
difftime(t_start, t_end));
|
difftime(t_start, t_end));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -295,7 +295,7 @@ static int pace_mse_set_at(const struct sm_ctx *oldpacectx, sc_card_t *card,
|
|||||||
bin_log(card->ctx, "MSE:Set AT command data", apdu.data, apdu.datalen);
|
bin_log(card->ctx, "MSE:Set AT command data", apdu.data, apdu.datalen);
|
||||||
|
|
||||||
if (oldpacectx)
|
if (oldpacectx)
|
||||||
r = pace_transmit_apdu(oldpacectx, card, &apdu);
|
r = sm_transmit_apdu(oldpacectx, card, &apdu);
|
||||||
else
|
else
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@@ -423,7 +423,7 @@ static int pace_gen_auth(const struct sm_ctx *oldpacectx, sc_card_t *card,
|
|||||||
apdu.resplen = maxresp;
|
apdu.resplen = maxresp;
|
||||||
apdu.resp = malloc(apdu.resplen);
|
apdu.resp = malloc(apdu.resplen);
|
||||||
if (oldpacectx)
|
if (oldpacectx)
|
||||||
r = pace_transmit_apdu(oldpacectx, card, &apdu);
|
r = sm_transmit_apdu(oldpacectx, card, &apdu);
|
||||||
else
|
else
|
||||||
r = sc_transmit_apdu(card, &apdu);
|
r = sc_transmit_apdu(card, &apdu);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@@ -586,7 +586,7 @@ pace_reset_retry_counter(struct sm_ctx *ctx, sc_card_t *card,
|
|||||||
apdu.cse = SC_APDU_CASE_1;
|
apdu.cse = SC_APDU_CASE_1;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = pace_transmit_apdu(ctx, card, &apdu);
|
r = sm_transmit_apdu(ctx, card, &apdu);
|
||||||
|
|
||||||
if (p) {
|
if (p) {
|
||||||
OPENSSL_cleanse(p, new_len);
|
OPENSSL_cleanse(p, new_len);
|
||||||
@@ -788,7 +788,7 @@ int EstablishPACEChannel(const struct sm_ctx *oldpacectx, sc_card_t *card,
|
|||||||
}
|
}
|
||||||
pub_opp->max = pub_opp->length;
|
pub_opp->max = pub_opp->length;
|
||||||
if (card->ctx->debug >= SC_LOG_TYPE_DEBUG)
|
if (card->ctx->debug >= SC_LOG_TYPE_DEBUG)
|
||||||
bin_log(card->ctx, "Public key from MRTD", (u8 *) pub_opp->data, pub_opp->length);
|
bin_log(card->ctx, "Ephemeral public key from MRTD", (u8 *) pub_opp->data, pub_opp->length);
|
||||||
|
|
||||||
key = PACE_STEP3B_compute_ephemeral_key(eph_dp, pctx, pub_opp);
|
key = PACE_STEP3B_compute_ephemeral_key(eph_dp, pctx, pub_opp);
|
||||||
if (!key ||
|
if (!key ||
|
||||||
@@ -834,6 +834,8 @@ int EstablishPACEChannel(const struct sm_ctx *oldpacectx, sc_card_t *card,
|
|||||||
sctx->encrypt = pace_sm_encrypt;
|
sctx->encrypt = pace_sm_encrypt;
|
||||||
sctx->decrypt = pace_sm_decrypt;
|
sctx->decrypt = pace_sm_decrypt;
|
||||||
sctx->verify_authentication = pace_sm_verify_authentication;
|
sctx->verify_authentication = pace_sm_verify_authentication;
|
||||||
|
sctx->pre_transmit = pace_sm_pre_transmit;
|
||||||
|
sctx->post_transmit = pace_sm_post_transmit;
|
||||||
sctx->padding_indicator = SM_ISO_PADDING;
|
sctx->padding_indicator = SM_ISO_PADDING;
|
||||||
sctx->block_length = EVP_CIPHER_block_size(pctx->cipher);
|
sctx->block_length = EVP_CIPHER_block_size(pctx->cipher);
|
||||||
|
|
||||||
@@ -1078,14 +1080,10 @@ int pace_sm_verify_authentication(sc_card_t *card, const struct sm_ctx *ctx,
|
|||||||
|
|
||||||
if (!ctx || !ctx->cipher_ctx) {
|
if (!ctx || !ctx->cipher_ctx) {
|
||||||
r = SC_ERROR_INVALID_ARGUMENTS;
|
r = SC_ERROR_INVALID_ARGUMENTS;
|
||||||
goto incerr;
|
goto err;
|
||||||
}
|
}
|
||||||
struct pace_sm_ctx *psmctx = ctx->cipher_ctx;
|
struct pace_sm_ctx *psmctx = ctx->cipher_ctx;
|
||||||
|
|
||||||
r = increment_ssc(psmctx);
|
|
||||||
if (r < 0)
|
|
||||||
goto incerr;
|
|
||||||
|
|
||||||
my_mac = PACE_authenticate(psmctx->ctx, psmctx->ssc, psmctx->key_mac,
|
my_mac = PACE_authenticate(psmctx->ctx, psmctx->ssc, psmctx->key_mac,
|
||||||
macdata, macdatalen);
|
macdata, macdatalen);
|
||||||
if (!my_mac) {
|
if (!my_mac) {
|
||||||
@@ -1103,55 +1101,25 @@ int pace_sm_verify_authentication(sc_card_t *card, const struct sm_ctx *ctx,
|
|||||||
if (card->ctx->debug > SC_LOG_TYPE_DEBUG)
|
if (card->ctx->debug > SC_LOG_TYPE_DEBUG)
|
||||||
sc_debug(card->ctx, "Authentication data verified");
|
sc_debug(card->ctx, "Authentication data verified");
|
||||||
|
|
||||||
|
r = SC_SUCCESS;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
if (my_mac)
|
if (my_mac)
|
||||||
BUF_MEM_free(my_mac);
|
BUF_MEM_free(my_mac);
|
||||||
if (r >= 0)
|
|
||||||
decrement_ssc(psmctx);
|
|
||||||
else
|
|
||||||
r = decrement_ssc(psmctx);
|
|
||||||
|
|
||||||
incerr:
|
|
||||||
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_ERROR, r);
|
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_ERROR, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
int pace_transmit_apdu(const struct sm_ctx *ctx, sc_card_t *card,
|
int pace_sm_pre_transmit(sc_card_t *card, const struct sm_ctx *ctx,
|
||||||
sc_apdu_t *apdu)
|
sc_apdu_t *apdu)
|
||||||
{
|
{
|
||||||
int r;
|
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG,
|
||||||
|
increment_ssc(ctx->cipher_ctx));
|
||||||
if ((apdu->cla & 0x0C) == 0x0C) {
|
|
||||||
sc_debug(card->ctx, "Given APDU is already protected with some secure messaging.");
|
|
||||||
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, sc_transmit_apdu(card, apdu));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ctx || !ctx->cipher_ctx) {
|
int pace_sm_post_transmit(sc_card_t *card, const struct sm_ctx *ctx,
|
||||||
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, SC_ERROR_INVALID_ARGUMENTS);
|
sc_apdu_t *sm_apdu)
|
||||||
}
|
{
|
||||||
|
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG,
|
||||||
/* SW1 and SW2 are used to determine if really something has been sent and
|
increment_ssc(ctx->cipher_ctx));
|
||||||
* received. Only if this is the case, the send sequence counter needs to
|
|
||||||
* be incremented. */
|
|
||||||
|
|
||||||
apdu->sw1 = 0;
|
|
||||||
apdu->sw2 = 0;
|
|
||||||
|
|
||||||
SC_TEST_RET(card->ctx, increment_ssc(ctx->cipher_ctx),
|
|
||||||
"Could not increment send sequence counter");
|
|
||||||
|
|
||||||
r = sm_transmit_apdu(ctx, card, apdu);
|
|
||||||
|
|
||||||
if (apdu->sw1 || apdu->sw2) {
|
|
||||||
if (r < 0) {
|
|
||||||
if (increment_ssc(ctx->cipher_ctx) < 0)
|
|
||||||
sc_error(card->ctx,
|
|
||||||
"Could not increment send sequence counter");
|
|
||||||
} else
|
|
||||||
r = increment_ssc(ctx->cipher_ctx);
|
|
||||||
} else
|
|
||||||
if (decrement_ssc(ctx->cipher_ctx) < 0)
|
|
||||||
sc_error(card->ctx,
|
|
||||||
"Could not decrement send sequence counter");
|
|
||||||
|
|
||||||
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, r);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,14 +58,16 @@ int pace_sm_authenticate(sc_card_t *card, const struct sm_ctx *ctx,
|
|||||||
int pace_sm_verify_authentication(sc_card_t *card, const struct sm_ctx *ctx,
|
int pace_sm_verify_authentication(sc_card_t *card, const struct sm_ctx *ctx,
|
||||||
const u8 *mac, size_t maclen,
|
const u8 *mac, size_t maclen,
|
||||||
const u8 *macdata, size_t macdatalen);
|
const u8 *macdata, size_t macdatalen);
|
||||||
|
int pace_sm_pre_transmit(sc_card_t *card, const struct sm_ctx *ctx,
|
||||||
|
sc_apdu_t *apdu);
|
||||||
|
int pace_sm_post_transmit(sc_card_t *card, const struct sm_ctx *ctx,
|
||||||
|
sc_apdu_t *sm_apdu);
|
||||||
|
|
||||||
int GetReadersPACECapabilities(sc_card_t *card, const unsigned char *in,
|
int GetReadersPACECapabilities(sc_card_t *card, const unsigned char *in,
|
||||||
unsigned char **out, size_t *outlen);
|
unsigned char **out, size_t *outlen);
|
||||||
int EstablishPACEChannel(const struct sm_ctx *oldpacectx, sc_card_t *card,
|
int EstablishPACEChannel(const struct sm_ctx *oldpacectx, sc_card_t *card,
|
||||||
const unsigned char *in, unsigned char **out, size_t *outlen, struct sm_ctx *sctx);
|
const unsigned char *in, unsigned char **out, size_t *outlen, struct sm_ctx *sctx);
|
||||||
|
|
||||||
int pace_transmit_apdu(const struct sm_ctx *sctx, sc_card_t *card,
|
|
||||||
sc_apdu_t *apdu);
|
|
||||||
int pace_reset_retry_counter(struct sm_ctx *ctx, sc_card_t *card,
|
int pace_reset_retry_counter(struct sm_ctx *ctx, sc_card_t *card,
|
||||||
enum s_type pin_id, int ask_for_secret,
|
enum s_type pin_id, int ask_for_secret,
|
||||||
const char *new, size_t new_len);
|
const char *new, size_t new_len);
|
||||||
|
|||||||
@@ -578,10 +578,21 @@ int sm_transmit_apdu(const struct sm_ctx *sctx, sc_card_t *card,
|
|||||||
sm_apdu.resp = rbuf;
|
sm_apdu.resp = rbuf;
|
||||||
sm_apdu.resplen = sizeof rbuf;
|
sm_apdu.resplen = sizeof rbuf;
|
||||||
|
|
||||||
|
if ((apdu->cla & 0x0C) == 0x0C) {
|
||||||
|
sc_debug(card->ctx, "Given APDU is already protected with some secure messaging.");
|
||||||
|
SC_FUNC_RETURN(card->ctx, SC_LOG_TYPE_DEBUG, sc_transmit_apdu(card, apdu));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sctx->pre_transmit)
|
||||||
|
SC_TEST_RET(card->ctx, sctx->pre_transmit(card, sctx, apdu),
|
||||||
|
"Could not complete SM specific pre transmit routine");
|
||||||
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, sc_transmit_apdu(card, &sm_apdu),
|
SC_TEST_RET(card->ctx, sc_transmit_apdu(card, &sm_apdu),
|
||||||
"Could not transmit SM APDU");
|
"Could not transmit SM APDU");
|
||||||
|
if (sctx->post_transmit)
|
||||||
|
SC_TEST_RET(card->ctx, sctx->post_transmit(card, sctx, &sm_apdu),
|
||||||
|
"Could not complete SM specific post transmit routine");
|
||||||
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");
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,11 @@ struct sm_ctx {
|
|||||||
const u8 *data, size_t datalen, u8 **enc);
|
const u8 *data, size_t datalen, u8 **enc);
|
||||||
int (*decrypt)(sc_card_t *card, const struct sm_ctx *ctx,
|
int (*decrypt)(sc_card_t *card, const struct sm_ctx *ctx,
|
||||||
const u8 *enc, size_t enclen, u8 **data);
|
const u8 *enc, size_t enclen, u8 **data);
|
||||||
|
|
||||||
|
int (*pre_transmit)(sc_card_t *card, const struct sm_ctx *ctx,
|
||||||
|
sc_apdu_t *apdu);
|
||||||
|
int (*post_transmit)(sc_card_t *card, const struct sm_ctx *ctx,
|
||||||
|
sc_apdu_t *sm_apdu);
|
||||||
};
|
};
|
||||||
|
|
||||||
int sm_transmit_apdu(const struct sm_ctx *sctx, sc_card_t *card,
|
int sm_transmit_apdu(const struct sm_ctx *sctx, sc_card_t *card,
|
||||||
|
|||||||
Reference in New Issue
Block a user