- fixed type of auxiliary data in c-apdu
- parsing mse:set for ta - check terminals signature for ta git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@538 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
156
npa/src/npa.c
156
npa/src/npa.c
@@ -46,7 +46,7 @@ typedef struct npa_mse_set_at_cd_st {
|
|||||||
ASN1_OBJECT *cryptographic_mechanism_reference;
|
ASN1_OBJECT *cryptographic_mechanism_reference;
|
||||||
ASN1_INTEGER *key_reference1;
|
ASN1_INTEGER *key_reference1;
|
||||||
ASN1_INTEGER *key_reference2;
|
ASN1_INTEGER *key_reference2;
|
||||||
ASN1_OCTET_STRING *auxiliary_data;
|
CVC_DISCRETIONARY_DATA_TEMPLATE *auxiliary_data;
|
||||||
ASN1_OCTET_STRING *eph_pub_key;
|
ASN1_OCTET_STRING *eph_pub_key;
|
||||||
CVC_CHAT *chat;
|
CVC_CHAT *chat;
|
||||||
} NPA_MSE_SET_AT_C;
|
} NPA_MSE_SET_AT_C;
|
||||||
@@ -62,7 +62,7 @@ ASN1_SEQUENCE(NPA_MSE_SET_AT_C) = {
|
|||||||
ASN1_IMP_OPT(NPA_MSE_SET_AT_C, key_reference2, ASN1_INTEGER, 4),
|
ASN1_IMP_OPT(NPA_MSE_SET_AT_C, key_reference2, ASN1_INTEGER, 4),
|
||||||
/* 0x67
|
/* 0x67
|
||||||
* Auxiliary authenticated data */
|
* Auxiliary authenticated data */
|
||||||
ASN1_APP_IMP_OPT(NPA_MSE_SET_AT_C, auxiliary_data, ASN1_OCTET_STRING, 7),
|
ASN1_APP_IMP_OPT(NPA_MSE_SET_AT_C, auxiliary_data, CVC_DISCRETIONARY_DATA_TEMPLATE, 7),
|
||||||
/* 0x91
|
/* 0x91
|
||||||
* Ephemeral Public Key */
|
* Ephemeral Public Key */
|
||||||
ASN1_IMP_OPT(NPA_MSE_SET_AT_C, eph_pub_key, ASN1_OCTET_STRING, 0x11),
|
ASN1_IMP_OPT(NPA_MSE_SET_AT_C, eph_pub_key, ASN1_OCTET_STRING, 0x11),
|
||||||
@@ -157,9 +157,14 @@ struct npa_sm_ctx {
|
|||||||
/** EAC context */
|
/** EAC context */
|
||||||
EAC_CTX *ctx;
|
EAC_CTX *ctx;
|
||||||
/** Certificate Description given on initialization of PACE */
|
/** Certificate Description given on initialization of PACE */
|
||||||
unsigned char *certificate_description;
|
BUF_MEM *certificate_description;
|
||||||
/** length of \a certificate_description */
|
/** picc's compressed ephemeral public key of PACE */
|
||||||
size_t certificate_description_length;
|
BUF_MEM *id_icc;
|
||||||
|
/** PCD's compressed ephemeral public key of CA */
|
||||||
|
BUF_MEM *eph_pub_key;
|
||||||
|
/** Auxiliary Data */
|
||||||
|
BUF_MEM *auxiliary_data;
|
||||||
|
/** Nonce generated in TA */
|
||||||
BUF_MEM *nonce;
|
BUF_MEM *nonce;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -186,7 +191,9 @@ static int reset_ssc(struct npa_sm_ctx *eacsmctx);
|
|||||||
|
|
||||||
static struct npa_sm_ctx *
|
static struct npa_sm_ctx *
|
||||||
npa_sm_ctx_create(EAC_CTX *ctx, const unsigned char *certificate_description,
|
npa_sm_ctx_create(EAC_CTX *ctx, const unsigned char *certificate_description,
|
||||||
size_t certificate_description_length)
|
size_t certificate_description_length,
|
||||||
|
const unsigned char *id_icc, size_t id_icc_length
|
||||||
|
)
|
||||||
{
|
{
|
||||||
struct npa_sm_ctx *out = malloc(sizeof *out);
|
struct npa_sm_ctx *out = malloc(sizeof *out);
|
||||||
if (!out)
|
if (!out)
|
||||||
@@ -198,14 +205,18 @@ npa_sm_ctx_create(EAC_CTX *ctx, const unsigned char *certificate_description,
|
|||||||
|
|
||||||
out->ctx = ctx;
|
out->ctx = ctx;
|
||||||
|
|
||||||
out->certificate_description = realloc(NULL,
|
out->certificate_description = BUF_MEM_create_init(certificate_description,
|
||||||
certificate_description_length);
|
certificate_description_length);
|
||||||
if (!out->certificate_description)
|
if (!out->certificate_description)
|
||||||
goto err;
|
goto err;
|
||||||
out->certificate_description_length = certificate_description_length;
|
|
||||||
memcpy(out->certificate_description, certificate_description,
|
out->id_icc = BUF_MEM_create_init(id_icc, id_icc_length);
|
||||||
certificate_description_length);
|
if (!out->id_icc)
|
||||||
|
goto err;
|
||||||
|
|
||||||
out->nonce = NULL;
|
out->nonce = NULL;
|
||||||
|
out->eph_pub_key = NULL;
|
||||||
|
out->auxiliary_data = NULL;
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
|
|
||||||
@@ -1219,7 +1230,9 @@ int EstablishPACEChannel(struct sm_ctx *oldnpactx, sc_card_t *card,
|
|||||||
|
|
||||||
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,
|
||||||
pace_input.certificate_description_length);
|
pace_input.certificate_description_length,
|
||||||
|
pace_output->id_icc,
|
||||||
|
pace_output->id_icc_length);
|
||||||
if (!sctx->priv_data) {
|
if (!sctx->priv_data) {
|
||||||
r = SC_ERROR_OUT_OF_MEMORY;
|
r = SC_ERROR_OUT_OF_MEMORY;
|
||||||
goto err;
|
goto err;
|
||||||
@@ -1538,20 +1551,29 @@ npa_sm_pre_transmit(sc_card_t *card, const struct sm_ctx *ctx,
|
|||||||
int r;
|
int r;
|
||||||
CVC_CERT *cvc_cert = NULL;
|
CVC_CERT *cvc_cert = NULL;
|
||||||
unsigned char *cert = NULL;
|
unsigned char *cert = NULL;
|
||||||
int cert_len;
|
int len;
|
||||||
|
BUF_MEM *signature = NULL;
|
||||||
|
unsigned char *sequence = NULL;
|
||||||
|
NPA_MSE_SET_AT_C *msesetat = NULL;
|
||||||
|
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
r = SC_ERROR_INVALID_ARGUMENTS;
|
r = SC_ERROR_INVALID_ARGUMENTS;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct npa_sm_ctx *eacsmctx = ctx->priv_data;
|
||||||
|
if (!ctx) {
|
||||||
|
r = SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
if (apdu && apdu->ins == 0x2a && apdu->p1 == 0x00 && apdu->p2 == 0xbe) {
|
if (apdu && apdu->ins == 0x2a && apdu->p1 == 0x00 && apdu->p2 == 0xbe) {
|
||||||
/* PSO:Verify Certificate
|
/* PSO:Verify Certificate
|
||||||
* check certificate description to match given certificate */
|
* check certificate description to match given certificate
|
||||||
struct npa_sm_ctx *eacsmctx = ctx->priv_data;
|
* TODO take MSE:Set DST (sent before) into account */
|
||||||
cvc_cert = cert_from_apdudata(apdu->data, apdu->datalen);
|
cvc_cert = cert_from_apdudata(apdu->data, apdu->datalen);
|
||||||
|
|
||||||
if (!eacsmctx || !cvc_cert || !cvc_cert->body) {
|
if (!cvc_cert || !cvc_cert->body) {
|
||||||
r = SC_ERROR_INVALID_DATA;
|
r = SC_ERROR_INVALID_DATA;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -1569,9 +1591,16 @@ npa_sm_pre_transmit(sc_card_t *card, const struct sm_ctx *ctx,
|
|||||||
case CVC_Terminal:
|
case CVC_Terminal:
|
||||||
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Processing Terminal certificate");
|
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Processing Terminal certificate");
|
||||||
|
|
||||||
|
if (!eacsmctx->certificate_description) {
|
||||||
|
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
|
||||||
|
"Certificate Description missing");
|
||||||
|
r = SC_ERROR_INVALID_DATA;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
switch (CVC_check_cert(cvc_cert,
|
switch (CVC_check_cert(cvc_cert,
|
||||||
eacsmctx->certificate_description,
|
eacsmctx->certificate_description->data,
|
||||||
eacsmctx->certificate_description_length)) {
|
eacsmctx->certificate_description->length)) {
|
||||||
case 1:
|
case 1:
|
||||||
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
|
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
|
||||||
"Certificate Description matches Certificate");
|
"Certificate Description matches Certificate");
|
||||||
@@ -1599,9 +1628,9 @@ npa_sm_pre_transmit(sc_card_t *card, const struct sm_ctx *ctx,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
cert_len = i2d_CVC_CERT(cvc_cert, &cert);
|
len = i2d_CVC_CERT(cvc_cert, &cert);
|
||||||
if (cert_len < 0
|
if (len < 0
|
||||||
|| !TA_STEP2_import_certificate(eacsmctx->ctx, cert, cert_len)) {
|
|| !TA_STEP2_import_certificate(eacsmctx->ctx, cert, len)) {
|
||||||
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
|
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
|
||||||
"Error importing certificate");
|
"Error importing certificate");
|
||||||
ssl_error(card->ctx);
|
ssl_error(card->ctx);
|
||||||
@@ -1609,9 +1638,81 @@ npa_sm_pre_transmit(sc_card_t *card, const struct sm_ctx *ctx,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (apdu && apdu->ins == 0x22 && apdu->p1 == 0x81 && apdu->p2 == 0xa4) {
|
||||||
|
/* MSE:Set AT
|
||||||
|
* fetch auxiliary data and terminal's compressed ephemeral public key
|
||||||
|
* for CA */
|
||||||
|
len = ASN1_object_size(1, apdu->datalen, V_ASN1_SEQUENCE);
|
||||||
|
sequence = malloc(len);
|
||||||
|
unsigned char *p = sequence;
|
||||||
|
const unsigned char *pp = sequence;
|
||||||
|
ASN1_put_object(&p, 1, apdu->datalen, V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL);
|
||||||
|
memcpy(p, apdu->data, apdu->datalen);
|
||||||
|
if (!d2i_NPA_MSE_SET_AT_C(&msesetat, &pp, len)) {
|
||||||
|
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not parse MSE:Set AT.");
|
||||||
|
r = SC_ERROR_INTERNAL;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (msesetat->auxiliary_data) {
|
||||||
|
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Saving terminal's auxiliary data");
|
||||||
|
if (eacsmctx->auxiliary_data)
|
||||||
|
BUF_MEM_free(eacsmctx->auxiliary_data);
|
||||||
|
eacsmctx->auxiliary_data = BUF_MEM_new();
|
||||||
|
if (!eacsmctx->auxiliary_data) {
|
||||||
|
r = SC_ERROR_OUT_OF_MEMORY;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
eacsmctx->auxiliary_data->length =
|
||||||
|
i2d_CVC_DISCRETIONARY_DATA_TEMPLATE(msesetat->auxiliary_data,
|
||||||
|
(unsigned char **) &eacsmctx->auxiliary_data->data);
|
||||||
|
if ((int) eacsmctx->auxiliary_data->length < 0) {
|
||||||
|
r = SC_ERROR_OUT_OF_MEMORY;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
eacsmctx->auxiliary_data->max = eacsmctx->auxiliary_data->length;
|
||||||
|
}
|
||||||
|
if (msesetat->eph_pub_key) {
|
||||||
|
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Saving terminal's compressed ephemeral public key");
|
||||||
|
if (eacsmctx->eph_pub_key)
|
||||||
|
BUF_MEM_free(eacsmctx->eph_pub_key);
|
||||||
|
eacsmctx->eph_pub_key =
|
||||||
|
BUF_MEM_create_init(msesetat->eph_pub_key->data,
|
||||||
|
msesetat->eph_pub_key->length);
|
||||||
|
if (!eacsmctx->eph_pub_key) {
|
||||||
|
r = SC_ERROR_OUT_OF_MEMORY;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (apdu && apdu->ins == 0x82 && apdu->p1 == 0x00 && apdu->p2 == 0x00) {
|
} else if (apdu && apdu->ins == 0x82 && apdu->p1 == 0x00 && apdu->p2 == 0x00) {
|
||||||
/* External Authenticate
|
/* External Authenticate
|
||||||
* TODO check terminal's signature */
|
* check terminal's signature */
|
||||||
|
|
||||||
|
signature = BUF_MEM_create_init(apdu->data, apdu->datalen);
|
||||||
|
if (!signature) {
|
||||||
|
r = SC_ERROR_OUT_OF_MEMORY;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
switch (TA_STEP6_verify(eacsmctx->ctx, eacsmctx->eph_pub_key,
|
||||||
|
eacsmctx->id_icc, eacsmctx->nonce,
|
||||||
|
eacsmctx->auxiliary_data, signature)) {
|
||||||
|
case 1:
|
||||||
|
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
|
||||||
|
"Verified Terminal's signature");
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
|
||||||
|
"Terminal's signature not verified");
|
||||||
|
r = SC_ERROR_INVALID_DATA;
|
||||||
|
goto err;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
|
||||||
|
"Error verifying terminal's signature");
|
||||||
|
ssl_error(card->ctx);
|
||||||
|
r = SC_ERROR_INTERNAL;
|
||||||
|
goto err;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r = increment_ssc(ctx->priv_data);
|
r = increment_ssc(ctx->priv_data);
|
||||||
@@ -1619,8 +1720,12 @@ npa_sm_pre_transmit(sc_card_t *card, const struct sm_ctx *ctx,
|
|||||||
err:
|
err:
|
||||||
if (cvc_cert)
|
if (cvc_cert)
|
||||||
CVC_CERT_free(cvc_cert);
|
CVC_CERT_free(cvc_cert);
|
||||||
|
if (signature)
|
||||||
|
BUF_MEM_free(signature);
|
||||||
if (cert)
|
if (cert)
|
||||||
OPENSSL_free(cert);
|
OPENSSL_free(cert);
|
||||||
|
if (sequence)
|
||||||
|
free(sequence);
|
||||||
|
|
||||||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r);
|
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r);
|
||||||
}
|
}
|
||||||
@@ -1669,9 +1774,16 @@ npa_sm_clear_free(const struct sm_ctx *ctx)
|
|||||||
EAC_CTX_clear_free(eacsmctx->ctx);
|
EAC_CTX_clear_free(eacsmctx->ctx);
|
||||||
if (eacsmctx->ssc)
|
if (eacsmctx->ssc)
|
||||||
BN_clear_free(eacsmctx->ssc);
|
BN_clear_free(eacsmctx->ssc);
|
||||||
free(eacsmctx->certificate_description);
|
if (eacsmctx->certificate_description)
|
||||||
|
BUF_MEM_free(eacsmctx->certificate_description);
|
||||||
if (eacsmctx->nonce)
|
if (eacsmctx->nonce)
|
||||||
BUF_MEM_free(eacsmctx->nonce);
|
BUF_MEM_free(eacsmctx->nonce);
|
||||||
|
if (eacsmctx->id_icc)
|
||||||
|
BUF_MEM_free(eacsmctx->id_icc);
|
||||||
|
if (eacsmctx->eph_pub_key)
|
||||||
|
BUF_MEM_free(eacsmctx->eph_pub_key);
|
||||||
|
if (eacsmctx->auxiliary_data)
|
||||||
|
BUF_MEM_free(eacsmctx->auxiliary_data);
|
||||||
free(eacsmctx);
|
free(eacsmctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user