diff --git a/ccid/src/ccid.c b/ccid/src/ccid.c index 0614d66..b5fd3c6 100644 --- a/ccid/src/ccid.c +++ b/ccid/src/ccid.c @@ -34,10 +34,7 @@ #include #include #include -#include -static char *certificate_description = NULL; -static size_t certificate_description_length = 0; static struct sm_ctx sctx; #ifdef BUERGERCLIENT_WORKAROUND static char *ef_cardaccess = NULL; @@ -168,9 +165,6 @@ void ccid_shutdown() #ifdef WITH_PACE sm_ctx_clear_free(&sctx); memset(&sctx, 0, sizeof(sctx)); - free(certificate_description); - certificate_description = NULL; - certificate_description_length = 0; #ifdef BUERGERCLIENT_WORKAROUND free(ef_cardaccess); ef_cardaccess = NULL; @@ -571,26 +565,6 @@ perform_PC_to_RDR_XfrBlock(const u8 *in, size_t inlen, __u8** out, size_t *outle else bin_log(ctx, SC_LOG_DEBUG_VERBOSE, "Invalid APDU", abDataIn, __le32_to_cpu(request->dwLength)); - -#ifdef WITH_PACE - /* Note that this is only an approximation to find out if we - * have a nPA */ - if (sctx.active) { - if (apdu.ins == 0x2a && apdu.p1 == 0x00 && apdu.p2 == 0xbe) { - /* PSO:Verify Certificate - * check certificate description to match given certificate */ - CVC_CERT *cvc_cert = NULL; - - cvc_cert = CVC_d2i_CVC_CERT(NULL, &apdu.data, apdu.datalen); - if (!cvc_cert - || !CVC_check_cert(cvc_cert, certificate_description, - certificate_description_length)) { - sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Certificate Description doesn't match Certificate"); - SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA); - } - } - } -#endif } sc_result = get_RDR_to_PC_DataBlock(request->bSeq, sc_result, @@ -894,9 +868,6 @@ perform_PC_to_RDR_Secure_EstablishPACEChannel(sc_card_t *card, __le16 word; __le32 dword; __u8 *p; - BIO *bio_stdout = NULL; - CVC_CERTIFICATE_DESCRIPTION *desc = NULL; - CVC_CHAT *chat = NULL; memset(&pace_input, 0, sizeof pace_input); memset(&pace_output, 0, sizeof pace_output); @@ -911,13 +882,6 @@ perform_PC_to_RDR_Secure_EstablishPACEChannel(sc_card_t *card, bin_log(ctx, SC_LOG_DEBUG_VERBOSE, "EstablishPACEChannel InBuffer", abData, abDatalen); - bio_stdout = BIO_new_fp(stdout, BIO_NOCLOSE); - if (!bio_stdout) { - sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Could not get output buffer"); - sc_result = SC_ERROR_INTERNAL; - goto err; - } - if (abDatalen < parsed+1) { sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Buffer too small, could not get PinID"); sc_result = SC_ERROR_INVALID_ARGUMENTS; @@ -945,21 +909,6 @@ perform_PC_to_RDR_Secure_EstablishPACEChannel(sc_card_t *card, if (pace_input.chat_length) { bin_log(ctx, SC_LOG_DEBUG_VERBOSE, "Card holder authorization template", pace_input.chat, pace_input.chat_length); - - chat = d2i_CVC_CHAT(NULL, - &pace_input.chat, - pace_input.chat_length); - if (!chat) { - sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Could not parse CHAT"); - sc_result = SC_ERROR_INTERNAL; - goto err; - } - - if (!cvc_chat_print(bio_stdout, chat, 4)) { - sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Could not print CHAT"); - sc_result = SC_ERROR_INTERNAL; - goto err; - } } @@ -997,35 +946,10 @@ perform_PC_to_RDR_Secure_EstablishPACEChannel(sc_card_t *card, } pace_input.certificate_description = &abData[parsed]; parsed += pace_input.certificate_description_length; - p = realloc(certificate_description, - pace_input.certificate_description_length); - if (!p) { - sc_result = SC_ERROR_OUT_OF_MEMORY; - goto err; - } - certificate_description = p; - certificate_description_length = pace_input.certificate_description_length; - memcpy(certificate_description, pace_input.certificate_description, - pace_input.certificate_description_length); if (pace_input.certificate_description_length) { bin_log(ctx, SC_LOG_DEBUG_VERBOSE, "Certificate description", pace_input.certificate_description, pace_input.certificate_description_length); - - desc = d2i_CVC_CERTIFICATE_DESCRIPTION(NULL, - &pace_input.certificate_description, - pace_input.certificate_description_length); - if (!desc) { - sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Could not parse Certificate Description"); - sc_result = SC_ERROR_INTERNAL; - goto err; - } - - if (!certificate_description_print(bio_stdout, desc, 4)) { - sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Could not print Certificate Description"); - sc_result = SC_ERROR_INTERNAL; - goto err; - } } @@ -1165,12 +1089,6 @@ err: free(pace_output.previous_car); free(pace_output.id_icc); free(pace_output.id_pcd); - if (bio_stdout) - BIO_free_all(bio_stdout); - if (desc) - CVC_CERTIFICATE_DESCRIPTION_free(desc); - if (chat) - CVC_CHAT_free(chat); return sc_result; } diff --git a/npa/src/npa.c b/npa/src/npa.c index ba10c4a..f12dad3 100644 --- a/npa/src/npa.c +++ b/npa/src/npa.c @@ -27,12 +27,11 @@ #include #include #include +#include #include #include #include -#include #include -#include #include @@ -157,6 +156,10 @@ struct npa_sm_ctx { BIGNUM *ssc; /** EAC context */ EAC_CTX *ctx; + /** Certificate Description given on initialization of PACE */ + unsigned char *certificate_description; + /** length of \a certificate_description */ + size_t certificate_description_length; }; static int npa_sm_encrypt(sc_card_t *card, const struct sm_ctx *ctx, @@ -179,7 +182,8 @@ static int decrement_ssc(struct npa_sm_ctx *eacsmctx); static int reset_ssc(struct npa_sm_ctx *eacsmctx); static struct npa_sm_ctx * -npa_sm_ctx_create(EAC_CTX *ctx) +npa_sm_ctx_create(EAC_CTX *ctx, const unsigned char *certificate_description, + size_t certificate_description_length) { struct npa_sm_ctx *out = malloc(sizeof *out); if (!out) @@ -191,6 +195,13 @@ npa_sm_ctx_create(EAC_CTX *ctx) out->ctx = ctx; + out->certificate_description = realloc(NULL, + certificate_description_length); + if (!out->certificate_description) + goto err; + out->certificate_description_length = certificate_description_length; + memcpy(out->certificate_description, certificate_description, + certificate_description_length); return out; @@ -1206,7 +1217,9 @@ int EstablishPACEChannel(struct sm_ctx *oldnpactx, sc_card_t *card, bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "ID PCD", pace_output->id_pcd, pace_output->id_pcd_length); - sctx->priv_data = npa_sm_ctx_create(eac_ctx); + sctx->priv_data = npa_sm_ctx_create(eac_ctx, + pace_input.certificate_description, + pace_input.certificate_description_length); if (!sctx->priv_data) { r = SC_ERROR_OUT_OF_MEMORY; goto err; @@ -1489,6 +1502,21 @@ static int npa_sm_pre_transmit(sc_card_t *card, const struct sm_ctx *ctx, sc_apdu_t *apdu) { + if (apdu && apdu->ins == 0x2a && apdu->p1 == 0x00 && apdu->p2 == 0xbe) { + /* PSO:Verify Certificate + * check certificate description to match given certificate */ + CVC_CERT *cvc_cert = NULL; + struct npa_sm_ctx *eacsmctx = ctx->priv_data; + + cvc_cert = CVC_d2i_CVC_CERT(NULL, &apdu->data, apdu->datalen); + if (!eacsmctx || !cvc_cert + || !CVC_check_cert(cvc_cert, eacsmctx->certificate_description, + eacsmctx->certificate_description_length)) { + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Certificate Description doesn't match Certificate"); + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA); + } + } + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, increment_ssc(ctx->priv_data)); } @@ -1509,6 +1537,7 @@ npa_sm_clear_free(const struct sm_ctx *ctx) EAC_CTX_clear_free(eacsmctx->ctx); if (eacsmctx->ssc) BN_clear_free(eacsmctx->ssc); + free(eacsmctx->certificate_description); free(eacsmctx); } }