- checking description against the certificate is now done internally in libnpa, removed hash of certificate description from pace output

- importing terminal certificates to verify terminals signature
- fixed hex dump without sc_context


git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@537 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
frankmorgner
2011-09-23 13:19:59 +00:00
parent 2a59a1806a
commit fd6a13263d
5 changed files with 83 additions and 38 deletions

View File

@@ -160,6 +160,7 @@ struct npa_sm_ctx {
unsigned char *certificate_description;
/** length of \a certificate_description */
size_t certificate_description_length;
BUF_MEM *nonce;
};
static int npa_sm_encrypt(sc_card_t *card, const struct sm_ctx *ctx,
@@ -175,6 +176,8 @@ static int npa_sm_pre_transmit(sc_card_t *card, const struct sm_ctx *ctx,
sc_apdu_t *apdu);
static int npa_sm_post_transmit(sc_card_t *card, const struct sm_ctx *ctx,
sc_apdu_t *sm_apdu);
static int npa_sm_finish(sc_card_t *card, const struct sm_ctx *ctx,
sc_apdu_t *apdu);
static void npa_sm_clear_free(const struct sm_ctx *ctx);
static int increment_ssc(struct npa_sm_ctx *eacsmctx);
@@ -202,6 +205,7 @@ npa_sm_ctx_create(EAC_CTX *ctx, const unsigned char *certificate_description,
out->certificate_description_length = certificate_description_length;
memcpy(out->certificate_description, certificate_description,
certificate_description_length);
out->nonce = NULL;
return out;
@@ -927,7 +931,7 @@ int EstablishPACEChannel(struct sm_ctx *oldnpactx, sc_card_t *card,
EAC_CTX *eac_ctx = NULL;
BUF_MEM *enc_nonce = NULL, *mdata = NULL, *mdata_opp = NULL,
*token_opp = NULL, *token = NULL, *pub = NULL, *pub_opp = NULL,
*comp_pub = NULL, *comp_pub_opp = NULL, *hash_cert_desc = NULL;
*comp_pub = NULL, *comp_pub_opp = NULL;
PACE_SEC *sec = NULL;
CVC_CHAT *chat = NULL;
BIO *bio_stdout = NULL;
@@ -991,25 +995,6 @@ int EstablishPACEChannel(struct sm_ctx *oldnpactx, sc_card_t *card,
goto err;
break;
}
hash_cert_desc = EAC_hash_certificate_description(
pace_input.certificate_description,
pace_input.certificate_description_length);
if (!hash_cert_desc) {
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not hash certificate description.");
ssl_error(card->ctx);
r = SC_ERROR_INTERNAL;
goto err;
}
p = realloc(pace_output->hash_cert_desc, hash_cert_desc->length);
if (!p) {
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Not enough memory for hash of certificate description.\n");
r = SC_ERROR_OUT_OF_MEMORY;
goto err;
}
pace_output->hash_cert_desc = p;
pace_output->hash_cert_desc_len = hash_cert_desc->length;
}
/* show chat in advance to give the user more time to read it...
@@ -1202,7 +1187,8 @@ int EstablishPACEChannel(struct sm_ctx *oldnpactx, sc_card_t *card,
p = realloc(pace_output->id_icc, comp_pub_opp->length);
if (!p) {
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Not enough memory for ID ICC.\n");
return SC_ERROR_OUT_OF_MEMORY;
r = SC_ERROR_OUT_OF_MEMORY;
goto err;
}
pace_output->id_icc = p;
pace_output->id_icc_length = comp_pub_opp->length;
@@ -1213,7 +1199,8 @@ int EstablishPACEChannel(struct sm_ctx *oldnpactx, sc_card_t *card,
p = realloc(pace_output->id_pcd, comp_pub->length);
if (!p) {
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Not enough memory for ID PCD.\n");
return SC_ERROR_OUT_OF_MEMORY;
r = SC_ERROR_OUT_OF_MEMORY;
goto err;
}
pace_output->id_pcd = p;
pace_output->id_pcd_length = comp_pub->length;
@@ -1222,6 +1209,14 @@ 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);
if(!EAC_CTX_init_ta(eac_ctx, NULL, 0, NULL, 0, pace_output->recent_car,
pace_output->recent_car_length)) {
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not initialize TA.\n");
ssl_error(card->ctx);
r = SC_ERROR_INTERNAL;
goto err;
}
sctx->priv_data = npa_sm_ctx_create(eac_ctx,
pace_input.certificate_description,
pace_input.certificate_description_length);
@@ -1235,6 +1230,7 @@ int EstablishPACEChannel(struct sm_ctx *oldnpactx, sc_card_t *card,
sctx->verify_authentication = npa_sm_verify_authentication;
sctx->pre_transmit = npa_sm_pre_transmit;
sctx->post_transmit = npa_sm_post_transmit;
sctx->finish = npa_sm_finish;
sctx->clear_free = npa_sm_clear_free;
sctx->padding_indicator = SM_ISO_PADDING;
sctx->block_length = EVP_CIPHER_block_size(eac_ctx->key_ctx->cipher);
@@ -1259,8 +1255,6 @@ err:
BUF_MEM_free(comp_pub_opp);
if (comp_pub)
BUF_MEM_free(comp_pub);
if (hash_cert_desc)
BUF_MEM_free(hash_cert_desc);
if (sec)
PACE_SEC_clear_free(sec);
if (bio_stdout)
@@ -1543,6 +1537,13 @@ npa_sm_pre_transmit(sc_card_t *card, const struct sm_ctx *ctx,
{
int r;
CVC_CERT *cvc_cert = NULL;
unsigned char *cert = NULL;
int cert_len;
if (!ctx) {
r = SC_ERROR_INVALID_ARGUMENTS;
goto err;
}
if (apdu && apdu->ins == 0x2a && apdu->p1 == 0x00 && apdu->p2 == 0xbe) {
/* PSO:Verify Certificate
@@ -1597,6 +1598,20 @@ npa_sm_pre_transmit(sc_card_t *card, const struct sm_ctx *ctx,
goto err;
break;
}
cert_len = i2d_CVC_CERT(cvc_cert, &cert);
if (cert_len < 0
|| !TA_STEP2_import_certificate(eacsmctx->ctx, cert, cert_len)) {
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
"Error importing certificate");
ssl_error(card->ctx);
r = SC_ERROR_INTERNAL;
goto err;
}
} else if (apdu && apdu->ins == 0x82 && apdu->p1 == 0x00 && apdu->p2 == 0x00) {
/* External Authenticate
* TODO check terminal's signature */
}
r = increment_ssc(ctx->priv_data);
@@ -1604,6 +1619,8 @@ npa_sm_pre_transmit(sc_card_t *card, const struct sm_ctx *ctx,
err:
if (cvc_cert)
CVC_CERT_free(cvc_cert);
if (cert)
OPENSSL_free(cert);
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r);
}
@@ -1616,6 +1633,34 @@ npa_sm_post_transmit(sc_card_t *card, const struct sm_ctx *ctx,
increment_ssc(ctx->priv_data));
}
static int
npa_sm_finish(sc_card_t *card, const struct sm_ctx *ctx,
sc_apdu_t *apdu)
{
if (!ctx || !ctx->priv_data)
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL,
SC_ERROR_INVALID_ARGUMENTS);
if (apdu && apdu->ins == 0x84 && apdu->p1 == 0x00 && apdu->p2 == 0x00 && apdu->le == 8
&& apdu->sw1 == 0x90 && apdu->sw2 == 0x00 && apdu->resplen == 8) {
/* Get Challenge
* copy challenge to EAC context */
struct npa_sm_ctx *eacsmctx = ctx->priv_data;
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Saving MRTD's nonce to later verify Terminal's signature");
if (eacsmctx->nonce)
BUF_MEM_free(eacsmctx->nonce);
eacsmctx->nonce = BUF_MEM_create_init(apdu->resp, apdu->resplen);
if (!eacsmctx->nonce)
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL,
SC_ERROR_OUT_OF_MEMORY);
}
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, 0);
}
static void
npa_sm_clear_free(const struct sm_ctx *ctx)
{
@@ -1625,6 +1670,8 @@ npa_sm_clear_free(const struct sm_ctx *ctx)
if (eacsmctx->ssc)
BN_clear_free(eacsmctx->ssc);
free(eacsmctx->certificate_description);
if (eacsmctx->nonce)
BUF_MEM_free(eacsmctx->nonce);
free(eacsmctx);
}
}

View File

@@ -158,11 +158,6 @@ struct establish_pace_channel_output {
size_t id_pcd_length;
/** PCD identifier */
unsigned char *id_pcd;
/** Length of \a hash_cert_desc */
size_t hash_cert_desc_len;
/** Hash of certificate description */
unsigned char *hash_cert_desc;
};
#ifdef BUERGERCLIENT_WORKAROUND

View File

@@ -67,6 +67,9 @@ struct sm_ctx {
/** Call back function for actions before decryption and decoding of \a sm_apdu */
int (*post_transmit)(sc_card_t *card, const struct sm_ctx *ctx,
sc_apdu_t *sm_apdu);
/** Call back function for actions after decrypting SM protected APDU */
int (*finish)(sc_card_t *card, const struct sm_ctx *ctx,
sc_apdu_t *apdu);
/** Clears and frees private data */
void (*clear_free)(const struct sm_ctx *ctx);

View File

@@ -84,21 +84,18 @@ void _bin_log(sc_context_t *ctx, int type, const char *file, int line,
const char *func, const char *label, const u8 *data, size_t len,
FILE *f)
{
/* this is the maximum supported by sc_do_log_va */
/* Flawfinder: ignore */
char buf[1800];
if (data)
sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL, data, len, buf, sizeof buf);
else
buf[0] = 0;
if (!f) {
char buf[1800];
if (data)
sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL, data, len, buf, sizeof buf);
else
buf[0] = 0;
sc_do_log(ctx, type, file, line, func,
"\n%s (%u byte%s):\n%s",
label, len, len==1?"":"s", buf);
} else {
fprintf(f, "%s (%u byte%s):\n%s",
label, len, len==1?"":"s", buf);
label, len, len==1?"":"s", sc_dump_hex(data, len));
}
}

View File

@@ -609,6 +609,9 @@ int sm_transmit_apdu(struct sm_ctx *sctx, sc_card_t *card,
"Could not complete SM specific post transmit routine");
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, sm_decrypt(sctx, card, &sm_apdu, apdu),
"Could not decrypt APDU");
if (sctx->finish)
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, sctx->finish(card, sctx, apdu),
"Could not complete SM specific post transmit routine");
return SC_SUCCESS;
}