Use struct sm_cwa_session from sm.h in dnie (#955)
* Use cm_ctx instead of a custom cwa struct. Get rid of sc_reset. * Use ifd.sn and icc.sn from sm_cwa_session struct too * Minor typo with sizeof closes https://github.com/OpenSC/OpenSC/issues/930
This commit is contained in:
parent
68f8f0bfa7
commit
c906c5e375
|
@ -2147,7 +2147,7 @@ static int dnie_pin_change(struct sc_card *card, struct sc_pin_cmd_data * data)
|
||||||
int res=SC_SUCCESS;
|
int res=SC_SUCCESS;
|
||||||
LOG_FUNC_CALLED(card->ctx);
|
LOG_FUNC_CALLED(card->ctx);
|
||||||
/* Ensure that secure channel is established from reset */
|
/* Ensure that secure channel is established from reset */
|
||||||
res = cwa_create_secure_channel(card, GET_DNIE_PRIV_DATA(card)->cwa_provider, CWA_SM_COLD);
|
res = cwa_create_secure_channel(card, GET_DNIE_PRIV_DATA(card)->cwa_provider, CWA_SM_ON);
|
||||||
LOG_TEST_RET(card->ctx, res, "Establish SM failed");
|
LOG_TEST_RET(card->ctx, res, "Establish SM failed");
|
||||||
LOG_FUNC_RETURN(card->ctx,SC_ERROR_NOT_SUPPORTED);
|
LOG_FUNC_RETURN(card->ctx,SC_ERROR_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
@ -2180,7 +2180,7 @@ static int dnie_pin_verify(struct sc_card *card,
|
||||||
sc_log(card->ctx, "DNIe 3.0 detected doing PIN initialization");
|
sc_log(card->ctx, "DNIe 3.0 detected doing PIN initialization");
|
||||||
dnie_change_cwa_provider_to_pin(card);
|
dnie_change_cwa_provider_to_pin(card);
|
||||||
}
|
}
|
||||||
res = cwa_create_secure_channel(card, GET_DNIE_PRIV_DATA(card)->cwa_provider, CWA_SM_COLD);
|
res = cwa_create_secure_channel(card, GET_DNIE_PRIV_DATA(card)->cwa_provider, CWA_SM_ON);
|
||||||
LOG_TEST_RET(card->ctx, res, "Establish SM failed");
|
LOG_TEST_RET(card->ctx, res, "Establish SM failed");
|
||||||
|
|
||||||
data->apdu = &apdu; /* prepare apdu struct */
|
data->apdu = &apdu; /* prepare apdu struct */
|
||||||
|
@ -2222,7 +2222,7 @@ static int dnie_pin_verify(struct sc_card *card,
|
||||||
if (card->atr.value[15] >= DNIE_30_VERSION) {
|
if (card->atr.value[15] >= DNIE_30_VERSION) {
|
||||||
sc_log(card->ctx, "DNIe 3.0 detected => re-establish secure channel");
|
sc_log(card->ctx, "DNIe 3.0 detected => re-establish secure channel");
|
||||||
dnie_change_cwa_provider_to_secure(card);
|
dnie_change_cwa_provider_to_secure(card);
|
||||||
res = cwa_create_secure_channel(card, GET_DNIE_PRIV_DATA(card)->cwa_provider, CWA_SM_OVER);
|
res = cwa_create_secure_channel(card, GET_DNIE_PRIV_DATA(card)->cwa_provider, CWA_SM_ON);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_FUNC_RETURN(card->ctx, res);
|
LOG_FUNC_RETURN(card->ctx, res);
|
||||||
|
|
|
@ -266,12 +266,6 @@ static u8 sn_ifd[] = { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
|
||||||
*/
|
*/
|
||||||
static u8 sn_ifd_pin[] = { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
|
static u8 sn_ifd_pin[] = { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
|
||||||
|
|
||||||
/**
|
|
||||||
* Serial number for ICC card.
|
|
||||||
* This buffer is to be filled at runtime
|
|
||||||
*/
|
|
||||||
static u8 sn_icc[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
|
||||||
|
|
||||||
/************ internal functions **********************************/
|
/************ internal functions **********************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -738,9 +732,10 @@ static int dnie_get_icc_privkey_ref(sc_card_t * card, u8 ** buf, size_t * len)
|
||||||
* @param buf where to store result (8 bytes)
|
* @param buf where to store result (8 bytes)
|
||||||
* @return SC_SUCCESS if ok; else error
|
* @return SC_SUCCESS if ok; else error
|
||||||
*/
|
*/
|
||||||
static int dnie_get_sn_ifd(sc_card_t * card, u8 ** buf)
|
static int dnie_get_sn_ifd(sc_card_t * card)
|
||||||
{
|
{
|
||||||
*buf = sn_ifd;
|
struct sm_cwa_session * sm = &card->sm_ctx.info.session.cwa;
|
||||||
|
memcpy(sm->ifd.sn, sn_ifd, sizeof(sm->ifd.sn));
|
||||||
return SC_SUCCESS;
|
return SC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -752,13 +747,12 @@ static int dnie_get_sn_ifd(sc_card_t * card, u8 ** buf)
|
||||||
* return SC_SUCCESS
|
* return SC_SUCCESS
|
||||||
*
|
*
|
||||||
* @param card pointer to card structure
|
* @param card pointer to card structure
|
||||||
* @param buf where to store result (8 bytes)
|
|
||||||
* @return SC_SUCCESS if ok; else error
|
* @return SC_SUCCESS if ok; else error
|
||||||
*/
|
*/
|
||||||
static int dnie_get_sn_ifd_pin(sc_card_t * card, u8 ** buf)
|
static int dnie_get_sn_ifd_pin(sc_card_t * card)
|
||||||
{
|
{
|
||||||
LOG_FUNC_CALLED(card->ctx);
|
struct sm_cwa_session * sm = &card->sm_ctx.info.session.cwa;
|
||||||
*buf = sn_ifd_pin;
|
memcpy(sm->ifd.sn, sn_ifd_pin, sizeof(sm->ifd.sn));
|
||||||
return SC_SUCCESS;
|
return SC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -768,21 +762,19 @@ static int dnie_get_sn_ifd_pin(sc_card_t * card, u8 ** buf)
|
||||||
* Just retrieve it from cache and return success
|
* Just retrieve it from cache and return success
|
||||||
*
|
*
|
||||||
* @param card pointer to card structure
|
* @param card pointer to card structure
|
||||||
* @param buf where to store result (8 bytes)
|
|
||||||
* @return SC_SUCCESS if ok; else error
|
* @return SC_SUCCESS if ok; else error
|
||||||
*/
|
*/
|
||||||
static int dnie_get_sn_icc(sc_card_t * card, u8 ** buf)
|
static int dnie_get_sn_icc(sc_card_t * card)
|
||||||
{
|
{
|
||||||
int res=SC_SUCCESS;
|
int res=SC_SUCCESS;
|
||||||
sc_serial_number_t serial;
|
sc_serial_number_t serial;
|
||||||
|
struct sm_cwa_session * sm = &card->sm_ctx.info.session.cwa;
|
||||||
|
|
||||||
res = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial);
|
res = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial);
|
||||||
LOG_TEST_RET(card->ctx, res, "Error in gettting serial number");
|
LOG_TEST_RET(card->ctx, res, "Error in gettting serial number");
|
||||||
/* copy into sn_icc buffer.Remember that dnie sn has 7 bytes length */
|
/* copy into sn_icc buffer.Remember that dnie sn has 7 bytes length */
|
||||||
memset(&sn_icc[0], 0, sizeof(sn_icc));
|
memset(sm->icc.sn, 0, sizeof(sm->icc.sn));
|
||||||
memcpy(&sn_icc[1], serial.value, 7);
|
memcpy(&sm->icc.sn[1], serial.value, 7);
|
||||||
/* return data */
|
|
||||||
*buf = &sn_icc[0];
|
|
||||||
return SC_SUCCESS;
|
return SC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -812,17 +804,6 @@ static int dnie_create_pre_ops(sc_card_t * card, cwa_provider_t * provider)
|
||||||
return sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial);
|
return sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Now in DNIe the channel mode is changed to SM_MODE_TRANSMIT
|
|
||||||
* after CWA initialization to be consistent with OpenSC
|
|
||||||
*/
|
|
||||||
static int dnie_create_post_ops(sc_card_t * card, cwa_provider_t * provider)
|
|
||||||
{
|
|
||||||
card->sm_ctx.sm_mode = SM_MODE_TRANSMIT;
|
|
||||||
|
|
||||||
return SC_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main entry point for DNIe CWA14890 SM data provider.
|
* Main entry point for DNIe CWA14890 SM data provider.
|
||||||
*
|
*
|
||||||
|
@ -842,11 +823,9 @@ cwa_provider_t *dnie_get_cwa_provider(sc_card_t * card)
|
||||||
|
|
||||||
/* pre and post operations */
|
/* pre and post operations */
|
||||||
res->cwa_create_pre_ops = dnie_create_pre_ops;
|
res->cwa_create_pre_ops = dnie_create_pre_ops;
|
||||||
res->cwa_create_post_ops = dnie_create_post_ops;
|
|
||||||
|
|
||||||
/* Get ICC intermediate CA path */
|
/* Get ICC intermediate CA path */
|
||||||
res->cwa_get_icc_intermediate_ca_cert =
|
res->cwa_get_icc_intermediate_ca_cert = dnie_get_icc_intermediate_ca_cert;
|
||||||
dnie_get_icc_intermediate_ca_cert;
|
|
||||||
/* Get ICC certificate path */
|
/* Get ICC certificate path */
|
||||||
res->cwa_get_icc_cert = dnie_get_icc_cert;
|
res->cwa_get_icc_cert = dnie_get_icc_cert;
|
||||||
|
|
||||||
|
@ -864,8 +843,7 @@ cwa_provider_t *dnie_get_cwa_provider(sc_card_t * card)
|
||||||
res->cwa_get_root_ca_pubkey_ref = dnie_get_root_ca_pubkey_ref;
|
res->cwa_get_root_ca_pubkey_ref = dnie_get_root_ca_pubkey_ref;
|
||||||
|
|
||||||
/* Get public key reference for IFD intermediate CA certificate */
|
/* Get public key reference for IFD intermediate CA certificate */
|
||||||
res->cwa_get_intermediate_ca_pubkey_ref =
|
res->cwa_get_intermediate_ca_pubkey_ref = dnie_get_intermediate_ca_pubkey_ref;
|
||||||
dnie_get_intermediate_ca_pubkey_ref;
|
|
||||||
|
|
||||||
/* Get public key reference for IFD CVC certificate */
|
/* Get public key reference for IFD CVC certificate */
|
||||||
res->cwa_get_ifd_pubkey_ref = dnie_get_ifd_pubkey_ref;
|
res->cwa_get_ifd_pubkey_ref = dnie_get_ifd_pubkey_ref;
|
||||||
|
@ -923,8 +901,7 @@ int dnie_transmit_apdu(sc_card_t * card, sc_apdu_t * apdu)
|
||||||
cwa_provider_t *provider = NULL;
|
cwa_provider_t *provider = NULL;
|
||||||
ctx=card->ctx;
|
ctx=card->ctx;
|
||||||
provider = GET_DNIE_PRIV_DATA(card)->cwa_provider;
|
provider = GET_DNIE_PRIV_DATA(card)->cwa_provider;
|
||||||
if ((provider->status.session.state == CWA_SM_ACTIVE) &&
|
if (card->sm_ctx.sm_mode == SM_MODE_TRANSMIT) {
|
||||||
(card->sm_ctx.sm_mode == SM_MODE_TRANSMIT)) {
|
|
||||||
res = sc_transmit_apdu(card, apdu);
|
res = sc_transmit_apdu(card, apdu);
|
||||||
LOG_TEST_RET(ctx, res, "Error in dnie_wrap_apdu process");
|
LOG_TEST_RET(ctx, res, "Error in dnie_wrap_apdu process");
|
||||||
res = cwa_decode_response(card, provider, apdu);
|
res = cwa_decode_response(card, provider, apdu);
|
||||||
|
|
|
@ -143,19 +143,18 @@ static void cwa_trace_apdu(sc_card_t * card, sc_apdu_t * apdu, int flag)
|
||||||
* Increase send sequence counter SSC.
|
* Increase send sequence counter SSC.
|
||||||
*
|
*
|
||||||
* @param card smart card info structure
|
* @param card smart card info structure
|
||||||
* @param sm Secure Message session handling data structure
|
|
||||||
* @return SC_SUCCESS if ok; else error code
|
* @return SC_SUCCESS if ok; else error code
|
||||||
*
|
*
|
||||||
* TODO: to further study: what about using bignum arithmetics?
|
* TODO: to further study: what about using bignum arithmetics?
|
||||||
*/
|
*/
|
||||||
static int cwa_increase_ssc(sc_card_t * card, cwa_sm_session_t * sm)
|
static int cwa_increase_ssc(sc_card_t * card)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
|
struct sm_cwa_session * sm = &card->sm_ctx.info.session.cwa;
|
||||||
|
|
||||||
/* preliminary checks */
|
/* preliminary checks */
|
||||||
if (!card || !card->ctx )
|
if (!card || !card->ctx )
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
if (!sm )
|
|
||||||
return SC_ERROR_SM_NOT_INITIALIZED;
|
|
||||||
LOG_FUNC_CALLED(card->ctx);
|
LOG_FUNC_CALLED(card->ctx);
|
||||||
/* u8 arithmetic; exit loop if no carry */
|
/* u8 arithmetic; exit loop if no carry */
|
||||||
sc_log(card->ctx, "Curr SSC: '%s'", sc_dump_hex(sm->ssc, 8));
|
sc_log(card->ctx, "Curr SSC: '%s'", sc_dump_hex(sm->ssc, 8));
|
||||||
|
@ -504,13 +503,13 @@ static int cwa_set_security_env(sc_card_t * card,
|
||||||
* Internal (Card) authentication (let the card verify sent ifd certs)
|
* Internal (Card) authentication (let the card verify sent ifd certs)
|
||||||
*
|
*
|
||||||
* @param card pointer to card data
|
* @param card pointer to card data
|
||||||
* @param sm secure message data pointer
|
* @param sig signature buffer
|
||||||
|
* @param dig_len signature buffer length
|
||||||
* @param data data to be sent in apdu
|
* @param data data to be sent in apdu
|
||||||
* @param datalen length of data to send
|
* @param datalen length of data to send
|
||||||
* @return SC_SUCCESS if OK: else error code
|
* @return SC_SUCCESS if OK: else error code
|
||||||
*/
|
*/
|
||||||
static int cwa_internal_auth(sc_card_t * card,
|
static int cwa_internal_auth(sc_card_t * card, u8 * sig, size_t sig_len, u8 * data, size_t datalen)
|
||||||
cwa_sm_status_t * sm, u8 * data, size_t datalen)
|
|
||||||
{
|
{
|
||||||
sc_apdu_t apdu;
|
sc_apdu_t apdu;
|
||||||
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
|
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||||
|
@ -536,9 +535,9 @@ static int cwa_internal_auth(sc_card_t * card,
|
||||||
result = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
result = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||||
LOG_TEST_RET(ctx, result, "SM internal auth invalid response");
|
LOG_TEST_RET(ctx, result, "SM internal auth invalid response");
|
||||||
|
|
||||||
if (apdu.resplen != sizeof(sm->sig)) /* invalid number of bytes received */
|
if (apdu.resplen != sig_len) /* invalid number of bytes received */
|
||||||
LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
|
LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
|
||||||
memcpy(sm->sig, apdu.resp, apdu.resplen); /* copy result to buffer */
|
memcpy(sig, apdu.resp, apdu.resplen); /* copy result to buffer */
|
||||||
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -554,13 +553,15 @@ static int cwa_internal_auth(sc_card_t * card,
|
||||||
* @param icc_pubkey public key of card
|
* @param icc_pubkey public key of card
|
||||||
* @param ifd_privkey private RSA key of ifd
|
* @param ifd_privkey private RSA key of ifd
|
||||||
* @param sn_icc card serial number
|
* @param sn_icc card serial number
|
||||||
* @param sm pointer to cwa_internal_t data
|
* @param sig signature buffer
|
||||||
|
* @param sig_len signature buffer length
|
||||||
* @return SC_SUCCESS if ok; else errorcode
|
* @return SC_SUCCESS if ok; else errorcode
|
||||||
*/
|
*/
|
||||||
static int cwa_prepare_external_auth(sc_card_t * card,
|
static int cwa_prepare_external_auth(sc_card_t * card,
|
||||||
RSA * icc_pubkey,
|
RSA * icc_pubkey,
|
||||||
RSA * ifd_privkey,
|
RSA * ifd_privkey,
|
||||||
u8 * sn_icc, cwa_sm_status_t * sm)
|
u8 * sig,
|
||||||
|
size_t sig_len)
|
||||||
{
|
{
|
||||||
/* we have to compose following message:
|
/* we have to compose following message:
|
||||||
data = E[PK.ICC.AUT](SIGMIN)
|
data = E[PK.ICC.AUT](SIGMIN)
|
||||||
|
@ -594,6 +595,7 @@ static int cwa_prepare_external_auth(sc_card_t * card,
|
||||||
BIGNUM *bnres = NULL;
|
BIGNUM *bnres = NULL;
|
||||||
sc_context_t *ctx = NULL;
|
sc_context_t *ctx = NULL;
|
||||||
const BIGNUM *ifd_privkey_n, *ifd_privkey_e, *ifd_privkey_d;
|
const BIGNUM *ifd_privkey_n, *ifd_privkey_e, *ifd_privkey_d;
|
||||||
|
struct sm_cwa_session * sm = &card->sm_ctx.info.session.cwa;
|
||||||
|
|
||||||
/* safety check */
|
/* safety check */
|
||||||
if (!card || !card->ctx)
|
if (!card || !card->ctx)
|
||||||
|
@ -601,7 +603,7 @@ static int cwa_prepare_external_auth(sc_card_t * card,
|
||||||
ctx = card->ctx;
|
ctx = card->ctx;
|
||||||
LOG_FUNC_CALLED(ctx);
|
LOG_FUNC_CALLED(ctx);
|
||||||
/* check received arguments */
|
/* check received arguments */
|
||||||
if (!icc_pubkey || !ifd_privkey || !sn_icc || !sm)
|
if (!icc_pubkey || !ifd_privkey || !sm)
|
||||||
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
|
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
buf1 = calloc(128, sizeof(u8));
|
buf1 = calloc(128, sizeof(u8));
|
||||||
buf2 = calloc(128, sizeof(u8));
|
buf2 = calloc(128, sizeof(u8));
|
||||||
|
@ -618,21 +620,20 @@ static int cwa_prepare_external_auth(sc_card_t * card,
|
||||||
/* compose buffer data */
|
/* compose buffer data */
|
||||||
buf3[0] = 0x6A; /* iso padding */
|
buf3[0] = 0x6A; /* iso padding */
|
||||||
RAND_bytes(buf3 + 1, 74); /* pRND */
|
RAND_bytes(buf3 + 1, 74); /* pRND */
|
||||||
RAND_bytes(sm->kifd, 32); /* Kifd */
|
RAND_bytes(sm->ifd.k, 32); /* Kifd */
|
||||||
memcpy(buf3 + 1 + 74, sm->kifd, 32); /* copy Kifd into buffer */
|
memcpy(buf3 + 1 + 74, sm->ifd.k, 32); /* copy Kifd into buffer */
|
||||||
/* prepare data to be hashed */
|
/* prepare data to be hashed */
|
||||||
memcpy(sha_buf, buf3 + 1, 74); /* copy pRND into sha_buf */
|
memcpy(sha_buf, buf3 + 1, 74); /* copy pRND into sha_buf */
|
||||||
memcpy(sha_buf + 74, buf3 + 1 + 74, 32); /* copy kifd into sha_buf */
|
memcpy(sha_buf + 74, buf3 + 1 + 74, 32); /* copy kifd into sha_buf */
|
||||||
memcpy(sha_buf + 74 + 32, sm->rndicc, 8); /* copy 8 byte icc challenge */
|
memcpy(sha_buf + 74 + 32, sm->icc.rnd, 8); /* copy 8 byte icc challenge */
|
||||||
memcpy(sha_buf + 74 + 32 + 8, sn_icc, 8); /* copy serialnr, 8 bytes */
|
memcpy(sha_buf + 74 + 32 + 8, sm->icc.sn, 8); /* copy serialnr, 8 bytes */
|
||||||
SHA1(sha_buf, 74 + 32 + 8 + 8, sha_data);
|
SHA1(sha_buf, 74 + 32 + 8 + 8, sha_data);
|
||||||
/* copy hashed data into buffer */
|
/* copy hashed data into buffer */
|
||||||
memcpy(buf3 + 1 + 74 + 32, sha_data, SHA_DIGEST_LENGTH);
|
memcpy(buf3 + 1 + 74 + 32, sha_data, SHA_DIGEST_LENGTH);
|
||||||
buf3[127] = 0xBC; /* iso padding */
|
buf3[127] = 0xBC; /* iso padding */
|
||||||
|
|
||||||
/* encrypt with ifd private key */
|
/* encrypt with ifd private key */
|
||||||
len2 =
|
len2 = RSA_private_decrypt(128, buf3, buf2, ifd_privkey, RSA_NO_PADDING);
|
||||||
RSA_private_decrypt(128, buf3, buf2, ifd_privkey, RSA_NO_PADDING);
|
|
||||||
if (len2 < 0) {
|
if (len2 < 0) {
|
||||||
msg = "Prepare external auth: ifd_privk encrypt failed";
|
msg = "Prepare external auth: ifd_privk encrypt failed";
|
||||||
res = SC_ERROR_SM_ENCRYPT_FAILED;
|
res = SC_ERROR_SM_ENCRYPT_FAILED;
|
||||||
|
@ -669,14 +670,14 @@ static int cwa_prepare_external_auth(sc_card_t * card,
|
||||||
|
|
||||||
/* re-encrypt result with icc public key */
|
/* re-encrypt result with icc public key */
|
||||||
len1 = RSA_public_encrypt(len3, buf3, buf1, icc_pubkey, RSA_NO_PADDING);
|
len1 = RSA_public_encrypt(len3, buf3, buf1, icc_pubkey, RSA_NO_PADDING);
|
||||||
if (len1 <= 0) {
|
if (len1 <= 0 || (size_t) len1 != sig_len) {
|
||||||
msg = "Prepare external auth: icc_pubk encrypt failed";
|
msg = "Prepare external auth: icc_pubk encrypt failed";
|
||||||
res = SC_ERROR_SM_ENCRYPT_FAILED;
|
res = SC_ERROR_SM_ENCRYPT_FAILED;
|
||||||
goto prepare_external_auth_end;
|
goto prepare_external_auth_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* process done: copy result into cwa_internal buffer and return success */
|
/* process done: copy result into cwa_internal buffer and return success */
|
||||||
memcpy(sm->sig, buf1, len1);
|
memcpy(sig, buf1, len1);
|
||||||
res = SC_SUCCESS;
|
res = SC_SUCCESS;
|
||||||
|
|
||||||
prepare_external_auth_end:
|
prepare_external_auth_end:
|
||||||
|
@ -715,11 +716,12 @@ static int cwa_prepare_external_auth(sc_card_t * card,
|
||||||
*
|
*
|
||||||
* Perform external (IFD) authenticate procedure (8.4.1.2)
|
* Perform external (IFD) authenticate procedure (8.4.1.2)
|
||||||
*
|
*
|
||||||
* @param data apdu signature content
|
* @param card pointer to card data
|
||||||
* @param datalen signature length (128)
|
* @param sig signature buffer
|
||||||
|
* @param sig signature buffer length
|
||||||
* @return SC_SUCCESS if OK: else error code
|
* @return SC_SUCCESS if OK: else error code
|
||||||
*/
|
*/
|
||||||
static int cwa_external_auth(sc_card_t * card, cwa_sm_status_t * sm)
|
static int cwa_external_auth(sc_card_t * card, u8 * sig, size_t sig_len)
|
||||||
{
|
{
|
||||||
sc_apdu_t apdu;
|
sc_apdu_t apdu;
|
||||||
int result = SC_SUCCESS;
|
int result = SC_SUCCESS;
|
||||||
|
@ -733,8 +735,8 @@ static int cwa_external_auth(sc_card_t * card, cwa_sm_status_t * sm)
|
||||||
LOG_FUNC_CALLED(ctx);
|
LOG_FUNC_CALLED(ctx);
|
||||||
|
|
||||||
/* compose apdu for External Authenticate cmd */
|
/* compose apdu for External Authenticate cmd */
|
||||||
dnie_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x82, 0x00, 0x00, 255, sizeof(sm->sig),
|
dnie_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x82, 0x00, 0x00, 255, sig_len,
|
||||||
resp, MAX_RESP_BUFFER_SIZE, sm->sig, sizeof(sm->sig));
|
resp, MAX_RESP_BUFFER_SIZE, sig, sig_len);
|
||||||
|
|
||||||
/* send composed apdu and parse result */
|
/* send composed apdu and parse result */
|
||||||
result = dnie_transmit_apdu(card, &apdu);
|
result = dnie_transmit_apdu(card, &apdu);
|
||||||
|
@ -750,10 +752,9 @@ static int cwa_external_auth(sc_card_t * card, cwa_sm_status_t * sm)
|
||||||
* Compute Kenc,Kmac, and SSC and store it into sm data
|
* Compute Kenc,Kmac, and SSC and store it into sm data
|
||||||
*
|
*
|
||||||
* @param card pointer to sc_card_t data
|
* @param card pointer to sc_card_t data
|
||||||
* @param sm pointer to cwa_internal_t data
|
|
||||||
* @return SC_SUCCESS if ok; else error code
|
* @return SC_SUCCESS if ok; else error code
|
||||||
*/
|
*/
|
||||||
static int cwa_compute_session_keys(sc_card_t * card, cwa_sm_status_t * sm)
|
static int cwa_compute_session_keys(sc_card_t * card)
|
||||||
{
|
{
|
||||||
|
|
||||||
char *msg = NULL;
|
char *msg = NULL;
|
||||||
|
@ -765,6 +766,7 @@ static int cwa_compute_session_keys(sc_card_t * card, cwa_sm_status_t * sm)
|
||||||
u8 kenc[4] = { 0x00, 0x00, 0x00, 0x01 };
|
u8 kenc[4] = { 0x00, 0x00, 0x00, 0x01 };
|
||||||
u8 kmac[4] = { 0x00, 0x00, 0x00, 0x02 };
|
u8 kmac[4] = { 0x00, 0x00, 0x00, 0x02 };
|
||||||
sc_context_t *ctx = NULL;
|
sc_context_t *ctx = NULL;
|
||||||
|
struct sm_cwa_session * sm = &card->sm_ctx.info.session.cwa;
|
||||||
|
|
||||||
/* safety check */
|
/* safety check */
|
||||||
if (!card || !card->ctx)
|
if (!card || !card->ctx)
|
||||||
|
@ -782,13 +784,13 @@ static int cwa_compute_session_keys(sc_card_t * card, cwa_sm_status_t * sm)
|
||||||
}
|
}
|
||||||
/* compose kseed (cwa-14890-1 sect 8.7.2) */
|
/* compose kseed (cwa-14890-1 sect 8.7.2) */
|
||||||
for (n = 0; n < 32; n++)
|
for (n = 0; n < 32; n++)
|
||||||
*(kseed + n) = sm->kicc[n] ^ sm->kifd[n];
|
*(kseed + n) = sm->icc.k[n] ^ sm->ifd.k[n];
|
||||||
|
|
||||||
/* evaluate kenc (cwa-14890-1 sect 8.8) */
|
/* evaluate kenc (cwa-14890-1 sect 8.8) */
|
||||||
memcpy(data, kseed, 32);
|
memcpy(data, kseed, 32);
|
||||||
memcpy(data + 32, kenc, 4);
|
memcpy(data + 32, kenc, 4);
|
||||||
SHA1(data, 32 + 4, sha_data);
|
SHA1(data, 32 + 4, sha_data);
|
||||||
memcpy(sm->session.kenc, sha_data, 16); /* kenc=16 fsb sha((kifd^kicc)||00000001) */
|
memcpy(sm->session_enc, sha_data, 16); /* kenc=16 fsb sha((kifd^kicc)||00000001) */
|
||||||
|
|
||||||
/* evaluate kmac */
|
/* evaluate kmac */
|
||||||
memset(data, 0, 32 + 4);
|
memset(data, 0, 32 + 4);
|
||||||
|
@ -797,11 +799,11 @@ static int cwa_compute_session_keys(sc_card_t * card, cwa_sm_status_t * sm)
|
||||||
memcpy(data, kseed, 32);
|
memcpy(data, kseed, 32);
|
||||||
memcpy(data + 32, kmac, 4);
|
memcpy(data + 32, kmac, 4);
|
||||||
SHA1(data, 32 + 4, sha_data);
|
SHA1(data, 32 + 4, sha_data);
|
||||||
memcpy(sm->session.kmac, sha_data, 16); /* kmac=16 fsb sha((kifd^kicc)||00000002) */
|
memcpy(sm->session_mac, sha_data, 16); /* kmac=16 fsb sha((kifd^kicc)||00000002) */
|
||||||
|
|
||||||
/* evaluate send sequence counter (cwa-14890-1 sect 8.9 & 9.6 */
|
/* evaluate send sequence counter (cwa-14890-1 sect 8.9 & 9.6 */
|
||||||
memcpy(sm->session.ssc, sm->rndicc + 4, 4); /* 4 least significant bytes of rndicc */
|
memcpy(sm->ssc, sm->icc.rnd + 4, 4); /* 4 least significant bytes of rndicc */
|
||||||
memcpy(sm->session.ssc + 4, sm->rndifd + 4, 4); /* 4 least significant bytes of rndifd */
|
memcpy(sm->ssc + 4, sm->ifd.rnd + 4, 4); /* 4 least significant bytes of rndifd */
|
||||||
|
|
||||||
/* arriving here means process ok */
|
/* arriving here means process ok */
|
||||||
res = SC_SUCCESS;
|
res = SC_SUCCESS;
|
||||||
|
@ -822,9 +824,9 @@ static int cwa_compute_session_keys(sc_card_t * card, cwa_sm_status_t * sm)
|
||||||
if (res != SC_SUCCESS)
|
if (res != SC_SUCCESS)
|
||||||
sc_log(ctx, msg);
|
sc_log(ctx, msg);
|
||||||
else {
|
else {
|
||||||
sc_log(ctx, "Kenc: %s", sc_dump_hex(sm->session.kenc, 16));
|
sc_log(ctx, "Kenc: %s", sc_dump_hex(sm->session_enc, 16));
|
||||||
sc_log(ctx, "Kmac: %s", sc_dump_hex(sm->session.kmac, 16));
|
sc_log(ctx, "Kmac: %s", sc_dump_hex(sm->session_mac, 16));
|
||||||
sc_log(ctx, "SSC: %s", sc_dump_hex(sm->session.ssc, 8));
|
sc_log(ctx, "SSC: %s", sc_dump_hex(sm->ssc, 8));
|
||||||
}
|
}
|
||||||
LOG_FUNC_RETURN(ctx, res);
|
LOG_FUNC_RETURN(ctx, res);
|
||||||
}
|
}
|
||||||
|
@ -877,14 +879,17 @@ static int cwa_compare_signature(u8 * data, size_t dlen, u8 * ifd_data)
|
||||||
* @param ifd_privkey ifd private key
|
* @param ifd_privkey ifd private key
|
||||||
* @param ifdbuf buffer containing ( RND.IFD || SN.IFD )
|
* @param ifdbuf buffer containing ( RND.IFD || SN.IFD )
|
||||||
* @param ifdlen buffer length; should be 16
|
* @param ifdlen buffer length; should be 16
|
||||||
* @param sm secure messaging internal data
|
* @param sig signature buffer
|
||||||
|
* @param sig_len signature buffer length
|
||||||
* @return SC_SUCCESS if ok; else error code
|
* @return SC_SUCCESS if ok; else error code
|
||||||
*/
|
*/
|
||||||
static int cwa_verify_internal_auth(sc_card_t * card,
|
static int cwa_verify_internal_auth(sc_card_t * card,
|
||||||
RSA * icc_pubkey,
|
RSA * icc_pubkey,
|
||||||
RSA * ifd_privkey,
|
RSA * ifd_privkey,
|
||||||
u8 * ifdbuf,
|
u8 * ifdbuf,
|
||||||
size_t ifdlen, cwa_sm_status_t * sm)
|
size_t ifdlen,
|
||||||
|
u8 * sig,
|
||||||
|
size_t sig_len)
|
||||||
{
|
{
|
||||||
int res = SC_SUCCESS;
|
int res = SC_SUCCESS;
|
||||||
char *msg = NULL;
|
char *msg = NULL;
|
||||||
|
@ -898,6 +903,7 @@ static int cwa_verify_internal_auth(sc_card_t * card,
|
||||||
BIGNUM *sigbn = NULL;
|
BIGNUM *sigbn = NULL;
|
||||||
sc_context_t *ctx = NULL;
|
sc_context_t *ctx = NULL;
|
||||||
const BIGNUM *icc_pubkey_n, *icc_pubkey_e, *icc_pubkey_d;
|
const BIGNUM *icc_pubkey_n, *icc_pubkey_e, *icc_pubkey_d;
|
||||||
|
struct sm_cwa_session * sm = &card->sm_ctx.info.session.cwa;
|
||||||
|
|
||||||
if (!card || !card->ctx)
|
if (!card || !card->ctx)
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
@ -937,9 +943,7 @@ static int cwa_verify_internal_auth(sc_card_t * card,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* decrypt data with our ifd priv key */
|
/* decrypt data with our ifd priv key */
|
||||||
len1 =
|
len1 = RSA_private_decrypt(sig_len, sig, buf1, ifd_privkey, RSA_NO_PADDING);
|
||||||
RSA_private_decrypt(sizeof(sm->sig), sm->sig, buf1, ifd_privkey,
|
|
||||||
RSA_NO_PADDING);
|
|
||||||
if (len1 <= 0) {
|
if (len1 <= 0) {
|
||||||
msg = "Verify Signature: decrypt with ifd privk failed";
|
msg = "Verify Signature: decrypt with ifd privk failed";
|
||||||
res = SC_ERROR_SM_ENCRYPT_FAILED;
|
res = SC_ERROR_SM_ENCRYPT_FAILED;
|
||||||
|
@ -997,7 +1001,7 @@ static int cwa_verify_internal_auth(sc_card_t * card,
|
||||||
}
|
}
|
||||||
/* arriving here means OK: complete data structures */
|
/* arriving here means OK: complete data structures */
|
||||||
verify_internal_ok:
|
verify_internal_ok:
|
||||||
memcpy(sm->kicc, buf3 + 1 + 74, 32); /* extract Kicc from buf3 */
|
memcpy(sm->icc.k, buf3 + 1 + 74, 32); /* extract Kicc from buf3 */
|
||||||
res = SC_SUCCESS;
|
res = SC_SUCCESS;
|
||||||
verify_internal_done:
|
verify_internal_done:
|
||||||
if (buf1)
|
if (buf1)
|
||||||
|
@ -1044,15 +1048,14 @@ int cwa_create_secure_channel(sc_card_t * card,
|
||||||
int res = SC_SUCCESS;
|
int res = SC_SUCCESS;
|
||||||
char *msg = "Success";
|
char *msg = "Success";
|
||||||
|
|
||||||
u8 *sn_icc = NULL;
|
|
||||||
|
|
||||||
/* data to get and parse certificates */
|
/* data to get and parse certificates */
|
||||||
X509 *icc_cert = NULL;
|
X509 *icc_cert = NULL;
|
||||||
X509 *ca_cert = NULL;
|
X509 *ca_cert = NULL;
|
||||||
EVP_PKEY *icc_pubkey = NULL;
|
EVP_PKEY *icc_pubkey = NULL;
|
||||||
EVP_PKEY *ifd_privkey = NULL;
|
EVP_PKEY *ifd_privkey = NULL;
|
||||||
sc_context_t *ctx = NULL;
|
sc_context_t *ctx = NULL;
|
||||||
cwa_sm_status_t *sm = NULL;
|
struct sm_cwa_session * sm = &card->sm_ctx.info.session.cwa;
|
||||||
|
u8 sig[128];
|
||||||
|
|
||||||
/* several buffer and buffer pointers */
|
/* several buffer and buffer pointers */
|
||||||
u8 *buffer = NULL;
|
u8 *buffer = NULL;
|
||||||
|
@ -1068,34 +1071,17 @@ int cwa_create_secure_channel(sc_card_t * card,
|
||||||
return SC_ERROR_SM_NOT_INITIALIZED;
|
return SC_ERROR_SM_NOT_INITIALIZED;
|
||||||
/* comodity vars */
|
/* comodity vars */
|
||||||
ctx = card->ctx;
|
ctx = card->ctx;
|
||||||
sm = &(provider->status);
|
|
||||||
|
|
||||||
LOG_FUNC_CALLED(ctx);
|
LOG_FUNC_CALLED(ctx);
|
||||||
|
|
||||||
/* check requested initialization method */
|
/* check requested initialization method */
|
||||||
switch (flag) {
|
switch (flag) {
|
||||||
case CWA_SM_OFF: /* disable SM */
|
case CWA_SM_OFF: /* disable SM */
|
||||||
provider->status.session.state = CWA_SM_NONE; /* just mark channel inactive */
|
|
||||||
card->sm_ctx.sm_mode = SM_MODE_NONE;
|
card->sm_ctx.sm_mode = SM_MODE_NONE;
|
||||||
sc_log(ctx, "Setting CWA SM status to none");
|
sc_log(ctx, "Setting CWA SM status to none");
|
||||||
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
||||||
case CWA_SM_WARM: /* only initialize if not already done */
|
case CWA_SM_ON: /* force sm initialization process */
|
||||||
if (provider->status.session.state != CWA_SM_NONE) {
|
sc_log(ctx, "CWA SM initialization requested");
|
||||||
sc_log(ctx,
|
|
||||||
"Warm CWA SM requested: already in SM state");
|
|
||||||
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
|
||||||
}
|
|
||||||
case CWA_SM_COLD: /* force sm initialization process */
|
|
||||||
sc_log(ctx, "CWA SM initialization requested => reset and re-initialize");
|
|
||||||
sc_reset(card, 0);
|
|
||||||
provider->status.session.state = CWA_SM_INPROGRESS;
|
|
||||||
card->sm_ctx.sm_mode = SM_MODE_NONE;
|
|
||||||
break;
|
|
||||||
case CWA_SM_OVER: /* create another channel over an existing one */
|
|
||||||
if (provider->status.session.state != CWA_SM_ACTIVE) {
|
|
||||||
sc_log(ctx, "CWA SM over requested => not in active state");
|
|
||||||
LOG_FUNC_RETURN(ctx, SC_ERROR_SM_INVALID_LEVEL);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sc_log(ctx, "Invalid provided SM initialization flag");
|
sc_log(ctx, "Invalid provided SM initialization flag");
|
||||||
|
@ -1118,7 +1104,7 @@ int cwa_create_secure_channel(sc_card_t * card,
|
||||||
/* retrieve icc serial number */
|
/* retrieve icc serial number */
|
||||||
sc_log(ctx, "Retrieve ICC serial number");
|
sc_log(ctx, "Retrieve ICC serial number");
|
||||||
if (provider->cwa_get_sn_icc) {
|
if (provider->cwa_get_sn_icc) {
|
||||||
res = provider->cwa_get_sn_icc(card, &sn_icc);
|
res = provider->cwa_get_sn_icc(card);
|
||||||
if (res != SC_SUCCESS) {
|
if (res != SC_SUCCESS) {
|
||||||
msg = "Retrieve ICC failed";
|
msg = "Retrieve ICC failed";
|
||||||
sc_log(ctx, msg);
|
sc_log(ctx, msg);
|
||||||
|
@ -1308,15 +1294,15 @@ int cwa_create_secure_channel(sc_card_t * card,
|
||||||
/* Internal (Card) authentication (let the card verify sent ifd certs)
|
/* Internal (Card) authentication (let the card verify sent ifd certs)
|
||||||
SN.IFD equals 8 lsb bytes of ifd.pubk ref according cwa14890 sec 8.4.1 */
|
SN.IFD equals 8 lsb bytes of ifd.pubk ref according cwa14890 sec 8.4.1 */
|
||||||
sc_log(ctx, "Step 8.4.1.10: Perform Internal authentication");
|
sc_log(ctx, "Step 8.4.1.10: Perform Internal authentication");
|
||||||
res = provider->cwa_get_sn_ifd(card, &buffer);
|
res = provider->cwa_get_sn_ifd(card);
|
||||||
if (res != SC_SUCCESS) {
|
if (res != SC_SUCCESS) {
|
||||||
msg = "Cannot get ifd serial number from provider";
|
msg = "Cannot get ifd serial number from provider";
|
||||||
goto csc_end;
|
goto csc_end;
|
||||||
}
|
}
|
||||||
RAND_bytes(sm->rndifd, 8); /* generate 8 random bytes */
|
RAND_bytes(sm->ifd.rnd, 8); /* generate 8 random bytes */
|
||||||
memcpy(rndbuf, sm->rndifd, 8); /* insert RND.IFD into rndbuf */
|
memcpy(rndbuf, sm->ifd.rnd, 8); /* insert RND.IFD into rndbuf */
|
||||||
memcpy(rndbuf + 8, buffer, 8); /* insert SN.IFD into rndbuf */
|
memcpy(rndbuf + 8, sm->ifd.sn, 8); /* insert SN.IFD into rndbuf */
|
||||||
res = cwa_internal_auth(card, sm, rndbuf, 16);
|
res = cwa_internal_auth(card, sig, 128, rndbuf, 16);
|
||||||
if (res != SC_SUCCESS) {
|
if (res != SC_SUCCESS) {
|
||||||
msg = "Internal auth cmd failed";
|
msg = "Internal auth cmd failed";
|
||||||
goto csc_end;
|
goto csc_end;
|
||||||
|
@ -1336,7 +1322,7 @@ int cwa_create_secure_channel(sc_card_t * card,
|
||||||
EVP_PKEY_get0_RSA(ifd_privkey), /* evaluated from DGP's Manual Annex 3 Data */
|
EVP_PKEY_get0_RSA(ifd_privkey), /* evaluated from DGP's Manual Annex 3 Data */
|
||||||
rndbuf, /* RND.IFD || SN.IFD */
|
rndbuf, /* RND.IFD || SN.IFD */
|
||||||
16, /* rndbuf length; should be 16 */
|
16, /* rndbuf length; should be 16 */
|
||||||
sm /* sm data */
|
sig, 128
|
||||||
);
|
);
|
||||||
if (res != SC_SUCCESS) {
|
if (res != SC_SUCCESS) {
|
||||||
msg = "Internal Auth Verify failed";
|
msg = "Internal Auth Verify failed";
|
||||||
|
@ -1345,7 +1331,7 @@ int cwa_create_secure_channel(sc_card_t * card,
|
||||||
|
|
||||||
/* get challenge: retrieve 8 random bytes from card */
|
/* get challenge: retrieve 8 random bytes from card */
|
||||||
sc_log(ctx, "Step 8.4.1.11: Prepare External Auth: Get Challenge");
|
sc_log(ctx, "Step 8.4.1.11: Prepare External Auth: Get Challenge");
|
||||||
res = card->ops->get_challenge(card, sm->rndicc, sizeof(sm->rndicc));
|
res = card->ops->get_challenge(card, sm->icc.rnd, sizeof(sm->icc.rnd));
|
||||||
if (res != SC_SUCCESS) {
|
if (res != SC_SUCCESS) {
|
||||||
msg = "Get Challenge failed";
|
msg = "Get Challenge failed";
|
||||||
goto csc_end;
|
goto csc_end;
|
||||||
|
@ -1354,7 +1340,7 @@ int cwa_create_secure_channel(sc_card_t * card,
|
||||||
/* compose signature data for external auth */
|
/* compose signature data for external auth */
|
||||||
res = cwa_prepare_external_auth(card,
|
res = cwa_prepare_external_auth(card,
|
||||||
EVP_PKEY_get0_RSA(icc_pubkey),
|
EVP_PKEY_get0_RSA(icc_pubkey),
|
||||||
EVP_PKEY_get0_RSA(ifd_privkey), sn_icc, sm);
|
EVP_PKEY_get0_RSA(ifd_privkey), sig, 128);
|
||||||
if (res != SC_SUCCESS) {
|
if (res != SC_SUCCESS) {
|
||||||
msg = "Prepare external auth failed";
|
msg = "Prepare external auth failed";
|
||||||
goto csc_end;
|
goto csc_end;
|
||||||
|
@ -1362,7 +1348,7 @@ int cwa_create_secure_channel(sc_card_t * card,
|
||||||
|
|
||||||
/* External (IFD) authentication */
|
/* External (IFD) authentication */
|
||||||
sc_log(ctx, "Step 8.4.1.12: Perform External (IFD) Authentication");
|
sc_log(ctx, "Step 8.4.1.12: Perform External (IFD) Authentication");
|
||||||
res = cwa_external_auth(card, sm);
|
res = cwa_external_auth(card, sig, 128);
|
||||||
if (res != SC_SUCCESS) {
|
if (res != SC_SUCCESS) {
|
||||||
msg = "External auth cmd failed";
|
msg = "External auth cmd failed";
|
||||||
goto csc_end;
|
goto csc_end;
|
||||||
|
@ -1370,7 +1356,7 @@ int cwa_create_secure_channel(sc_card_t * card,
|
||||||
|
|
||||||
/* Session key generation */
|
/* Session key generation */
|
||||||
sc_log(ctx, "Step 8.4.2: Compute Session Keys");
|
sc_log(ctx, "Step 8.4.2: Compute Session Keys");
|
||||||
res = cwa_compute_session_keys(card, sm);
|
res = cwa_compute_session_keys(card);
|
||||||
if (res != SC_SUCCESS) {
|
if (res != SC_SUCCESS) {
|
||||||
msg = "Session Key generation failed";
|
msg = "Session Key generation failed";
|
||||||
goto csc_end;
|
goto csc_end;
|
||||||
|
@ -1401,9 +1387,9 @@ int cwa_create_secure_channel(sc_card_t * card,
|
||||||
/* setup SM state according result */
|
/* setup SM state according result */
|
||||||
if (res != SC_SUCCESS) {
|
if (res != SC_SUCCESS) {
|
||||||
sc_log(ctx, msg);
|
sc_log(ctx, msg);
|
||||||
provider->status.session.state = CWA_SM_NONE;
|
card->sm_ctx.sm_mode = SM_MODE_NONE;
|
||||||
} else {
|
} else {
|
||||||
provider->status.session.state = CWA_SM_ACTIVE;
|
card->sm_ctx.sm_mode = SM_MODE_TRANSMIT;
|
||||||
}
|
}
|
||||||
LOG_FUNC_RETURN(ctx, res);
|
LOG_FUNC_RETURN(ctx, res);
|
||||||
}
|
}
|
||||||
|
@ -1439,7 +1425,7 @@ int cwa_encode_apdu(sc_card_t * card,
|
||||||
size_t i, j; /* for xor loops */
|
size_t i, j; /* for xor loops */
|
||||||
int res = SC_SUCCESS;
|
int res = SC_SUCCESS;
|
||||||
sc_context_t *ctx = NULL;
|
sc_context_t *ctx = NULL;
|
||||||
cwa_sm_session_t *sm_session = NULL;
|
struct sm_cwa_session * sm_session = &card->sm_ctx.info.session.cwa;
|
||||||
u8 *msgbuf = NULL; /* to encrypt apdu data */
|
u8 *msgbuf = NULL; /* to encrypt apdu data */
|
||||||
u8 *cryptbuf = NULL;
|
u8 *cryptbuf = NULL;
|
||||||
|
|
||||||
|
@ -1447,13 +1433,12 @@ int cwa_encode_apdu(sc_card_t * card,
|
||||||
if (!card || !card->ctx || !provider)
|
if (!card || !card->ctx || !provider)
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
ctx = card->ctx;
|
ctx = card->ctx;
|
||||||
sm_session = &(provider->status.session);
|
|
||||||
|
|
||||||
LOG_FUNC_CALLED(ctx);
|
LOG_FUNC_CALLED(ctx);
|
||||||
/* check remaining arguments */
|
/* check remaining arguments */
|
||||||
if (!from || !to || !sm_session)
|
if (!from || !to || !sm_session)
|
||||||
LOG_FUNC_RETURN(ctx, SC_ERROR_SM_NOT_INITIALIZED);
|
LOG_FUNC_RETURN(ctx, SC_ERROR_SM_NOT_INITIALIZED);
|
||||||
if (sm_session->state != CWA_SM_ACTIVE)
|
if (card->sm_ctx.sm_mode != SM_MODE_TRANSMIT)
|
||||||
LOG_FUNC_RETURN(ctx, SC_ERROR_SM_INVALID_LEVEL);
|
LOG_FUNC_RETURN(ctx, SC_ERROR_SM_INVALID_LEVEL);
|
||||||
|
|
||||||
/* reserve extra bytes for padding and tlv header */
|
/* reserve extra bytes for padding and tlv header */
|
||||||
|
@ -1514,9 +1499,9 @@ int cwa_encode_apdu(sc_card_t * card,
|
||||||
|
|
||||||
/* prepare keys */
|
/* prepare keys */
|
||||||
DES_cblock iv = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
DES_cblock iv = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||||
DES_set_key_unchecked((const_DES_cblock *) & (sm_session->kenc[0]),
|
DES_set_key_unchecked((const_DES_cblock *) & (sm_session->session_enc[0]),
|
||||||
&k1);
|
&k1);
|
||||||
DES_set_key_unchecked((const_DES_cblock *) & (sm_session->kenc[8]),
|
DES_set_key_unchecked((const_DES_cblock *) & (sm_session->session_enc[8]),
|
||||||
&k2);
|
&k2);
|
||||||
|
|
||||||
/* pad message */
|
/* pad message */
|
||||||
|
@ -1562,14 +1547,14 @@ int cwa_encode_apdu(sc_card_t * card,
|
||||||
|
|
||||||
/* sc_log(ctx,"data to compose mac: %s",sc_dump_hex(ccbuf,cclen)); */
|
/* sc_log(ctx,"data to compose mac: %s",sc_dump_hex(ccbuf,cclen)); */
|
||||||
/* compute MAC Cryptographic Checksum using kmac and increased SSC */
|
/* compute MAC Cryptographic Checksum using kmac and increased SSC */
|
||||||
res = cwa_increase_ssc(card, sm_session); /* increase send sequence counter */
|
res = cwa_increase_ssc(card); /* increase send sequence counter */
|
||||||
if (res != SC_SUCCESS) {
|
if (res != SC_SUCCESS) {
|
||||||
msg = "Error in computing SSC";
|
msg = "Error in computing SSC";
|
||||||
goto encode_end;
|
goto encode_end;
|
||||||
}
|
}
|
||||||
/* set up keys for mac computing */
|
/* set up keys for mac computing */
|
||||||
DES_set_key_unchecked((const_DES_cblock *) & (sm_session->kmac[0]),&k1);
|
DES_set_key_unchecked((const_DES_cblock *) & (sm_session->session_mac[0]),&k1);
|
||||||
DES_set_key_unchecked((const_DES_cblock *) & (sm_session->kmac[8]),&k2);
|
DES_set_key_unchecked((const_DES_cblock *) & (sm_session->session_mac[8]),&k2);
|
||||||
|
|
||||||
memcpy(macbuf, sm_session->ssc, 8); /* start with computed SSC */
|
memcpy(macbuf, sm_session->ssc, 8); /* start with computed SSC */
|
||||||
for (i = 0; i < cclen; i += 8) { /* divide data in 8 byte blocks */
|
for (i = 0; i < cclen; i += 8) { /* divide data in 8 byte blocks */
|
||||||
|
@ -1649,19 +1634,18 @@ int cwa_decode_response(sc_card_t * card,
|
||||||
int res = SC_SUCCESS;
|
int res = SC_SUCCESS;
|
||||||
char *msg = NULL; /* to store error messages */
|
char *msg = NULL; /* to store error messages */
|
||||||
sc_context_t *ctx = NULL;
|
sc_context_t *ctx = NULL;
|
||||||
cwa_sm_session_t *sm_session = NULL;
|
struct sm_cwa_session * sm_session = &card->sm_ctx.info.session.cwa;
|
||||||
|
|
||||||
/* mandatory check */
|
/* mandatory check */
|
||||||
if (!card || !card->ctx || !provider)
|
if (!card || !card->ctx || !provider)
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
ctx = card->ctx;
|
ctx = card->ctx;
|
||||||
sm_session = &(provider->status.session);
|
|
||||||
|
|
||||||
LOG_FUNC_CALLED(ctx);
|
LOG_FUNC_CALLED(ctx);
|
||||||
/* check remaining arguments */
|
/* check remaining arguments */
|
||||||
if ((apdu == NULL) || (sm_session == NULL))
|
if ((apdu == NULL) || (sm_session == NULL))
|
||||||
LOG_FUNC_RETURN(ctx, SC_ERROR_SM_NOT_INITIALIZED);
|
LOG_FUNC_RETURN(ctx, SC_ERROR_SM_NOT_INITIALIZED);
|
||||||
if (sm_session->state != CWA_SM_ACTIVE)
|
if (card->sm_ctx.sm_mode != SM_MODE_TRANSMIT)
|
||||||
LOG_FUNC_RETURN(ctx, SC_ERROR_SM_INVALID_LEVEL);
|
LOG_FUNC_RETURN(ctx, SC_ERROR_SM_INVALID_LEVEL);
|
||||||
|
|
||||||
/* cwa14890 sect 9.3: check SW1 or SW2 for SM related errors */
|
/* cwa14890 sect 9.3: check SW1 or SW2 for SM related errors */
|
||||||
|
@ -1766,14 +1750,14 @@ int cwa_decode_response(sc_card_t * card,
|
||||||
/* evaluate mac by mean of kmac and increased SendSequence Counter SSC */
|
/* evaluate mac by mean of kmac and increased SendSequence Counter SSC */
|
||||||
|
|
||||||
/* increase SSC */
|
/* increase SSC */
|
||||||
res = cwa_increase_ssc(card, sm_session); /* increase send sequence counter */
|
res = cwa_increase_ssc(card); /* increase send sequence counter */
|
||||||
if (res != SC_SUCCESS) {
|
if (res != SC_SUCCESS) {
|
||||||
msg = "Error in computing SSC";
|
msg = "Error in computing SSC";
|
||||||
goto response_decode_end;
|
goto response_decode_end;
|
||||||
}
|
}
|
||||||
/* set up keys for mac computing */
|
/* set up keys for mac computing */
|
||||||
DES_set_key_unchecked((const_DES_cblock *) & (sm_session->kmac[0]), &k1);
|
DES_set_key_unchecked((const_DES_cblock *) & (sm_session->session_mac[0]), &k1);
|
||||||
DES_set_key_unchecked((const_DES_cblock *) & (sm_session->kmac[8]), &k2);
|
DES_set_key_unchecked((const_DES_cblock *) & (sm_session->session_mac[8]), &k2);
|
||||||
|
|
||||||
memcpy(macbuf, sm_session->ssc, 8); /* start with computed SSC */
|
memcpy(macbuf, sm_session->ssc, 8); /* start with computed SSC */
|
||||||
for (i = 0; i < cclen; i += 8) { /* divide data in 8 byte blocks */
|
for (i = 0; i < cclen; i += 8) { /* divide data in 8 byte blocks */
|
||||||
|
@ -1834,9 +1818,9 @@ int cwa_decode_response(sc_card_t * card,
|
||||||
goto response_decode_end;
|
goto response_decode_end;
|
||||||
}
|
}
|
||||||
/* prepare keys to decode */
|
/* prepare keys to decode */
|
||||||
DES_set_key_unchecked((const_DES_cblock *) & (sm_session->kenc[0]),
|
DES_set_key_unchecked((const_DES_cblock *) & (sm_session->session_enc[0]),
|
||||||
&k1);
|
&k1);
|
||||||
DES_set_key_unchecked((const_DES_cblock *) & (sm_session->kenc[8]),
|
DES_set_key_unchecked((const_DES_cblock *) & (sm_session->session_enc[8]),
|
||||||
&k2);
|
&k2);
|
||||||
/* decrypt into response buffer
|
/* decrypt into response buffer
|
||||||
* by using 3DES CBC by mean of kenc and iv={0,...0} */
|
* by using 3DES CBC by mean of kenc and iv={0,...0} */
|
||||||
|
@ -1953,13 +1937,13 @@ static int default_get_icc_privkey_ref(sc_card_t * card, u8 ** buf,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Retrieve SN.IFD (8 bytes left padded with zeroes if needed) */
|
/* Retrieve SN.IFD (8 bytes left padded with zeroes if needed) */
|
||||||
static int default_get_sn_ifd(sc_card_t * card, u8 ** buf)
|
static int default_get_sn_ifd(sc_card_t * card)
|
||||||
{
|
{
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Retrieve SN.ICC (8 bytes left padded with zeroes if needed) */
|
/* Retrieve SN.ICC (8 bytes left padded with zeroes if needed) */
|
||||||
static int default_get_sn_icc(sc_card_t * card, u8 ** buf)
|
static int default_get_sn_icc(sc_card_t * card)
|
||||||
{
|
{
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
@ -1967,50 +1951,6 @@ static int default_get_sn_icc(sc_card_t * card, u8 ** buf)
|
||||||
static cwa_provider_t default_cwa_provider = {
|
static cwa_provider_t default_cwa_provider = {
|
||||||
|
|
||||||
/************ data related with SM operations *************************/
|
/************ data related with SM operations *************************/
|
||||||
{
|
|
||||||
{ /* KICC */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
{ /* KIFD */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
{ /* RND.ICC */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
{ /* RND.IFD */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
{ /* SigBuf */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
{ /* sm session */
|
|
||||||
CWA_SM_NONE, /* state */
|
|
||||||
{ /* Kenc */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
{ /* Kmac */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
{ /* SSC Send Sequence counter */
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/************ operations related with secure channel creation *********/
|
/************ operations related with secure channel creation *********/
|
||||||
|
|
||||||
|
|
|
@ -27,16 +27,9 @@
|
||||||
|
|
||||||
#if defined(ENABLE_OPENSSL) && defined(ENABLE_SM)
|
#if defined(ENABLE_OPENSSL) && defined(ENABLE_SM)
|
||||||
|
|
||||||
/* Secure Messaging state indicator */
|
|
||||||
#define CWA_SM_NONE 0x00 /** No SM channel defined */
|
|
||||||
#define CWA_SM_INPROGRESS 0x01 /** SM channel is being created: don't use */
|
|
||||||
#define CWA_SM_ACTIVE 0x02 /** SM channel is active */
|
|
||||||
|
|
||||||
/* Flags for setting SM status */
|
/* Flags for setting SM status */
|
||||||
#define CWA_SM_OFF 0x00 /** Disable SM channel */
|
#define CWA_SM_OFF 0x00 /** Disable SM channel */
|
||||||
#define CWA_SM_COLD 0x01 /** force creation of a new SM channel */
|
#define CWA_SM_ON 0x01 /** Enable SM channel */
|
||||||
#define CWA_SM_WARM 0x02 /** Create new SM channel only if state is NONE */
|
|
||||||
#define CWA_SM_OVER 0x03 /** Create new SM channel only over another channel */
|
|
||||||
|
|
||||||
/* TAGS for encoded APDU's */
|
/* TAGS for encoded APDU's */
|
||||||
#define CWA_SM_PLAIN_TAG 0x81 /** Plain value (to be protected by CC) */
|
#define CWA_SM_PLAIN_TAG 0x81 /** Plain value (to be protected by CC) */
|
||||||
|
@ -52,40 +45,11 @@
|
||||||
#include <openssl/x509.h>
|
#include <openssl/x509.h>
|
||||||
#include <openssl/des.h>
|
#include <openssl/des.h>
|
||||||
|
|
||||||
/**
|
|
||||||
* Structure used to handle keys and sequence counter once SM session
|
|
||||||
* is stablished
|
|
||||||
*/
|
|
||||||
typedef struct cwa_sm_session_st {
|
|
||||||
/* variables used once SM is started */
|
|
||||||
int state; /** one of NONE, INPROGRESS, or ACTIVE */
|
|
||||||
u8 kenc[16]; /** key used for data encoding */
|
|
||||||
u8 kmac[16]; /** key for mac checksum calculation */
|
|
||||||
u8 ssc[8]; /** send sequence counter */
|
|
||||||
} cwa_sm_session_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Estructure used to compose and store variables related to SM setting
|
|
||||||
* and encode/decode apdu messages.
|
|
||||||
*/
|
|
||||||
typedef struct cwa_sm_status_st {
|
|
||||||
/* variables used in SM establishment */
|
|
||||||
u8 kicc[32];
|
|
||||||
u8 kifd[32];
|
|
||||||
u8 rndicc[8]; /** 8 bytes random number generated by card */
|
|
||||||
u8 rndifd[8]; /** 8 bytes random number generated by application */
|
|
||||||
u8 sig[128]; /** buffer to store & compute signatures (1024 bits) */
|
|
||||||
cwa_sm_session_t session; /** current session data */
|
|
||||||
} cwa_sm_status_t;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data and function pointers to provide information to create and handle
|
* Data and function pointers to provide information to create and handle
|
||||||
* Secure Channel.
|
* Secure Channel.
|
||||||
*/
|
*/
|
||||||
typedef struct cwa_provider_st {
|
typedef struct cwa_provider_st {
|
||||||
/************ data related with SM operations *************************/
|
|
||||||
|
|
||||||
cwa_sm_status_t status; /** sm status for this provider */
|
|
||||||
|
|
||||||
/************ operations related with secure channel creation *********/
|
/************ operations related with secure channel creation *********/
|
||||||
|
|
||||||
|
@ -257,23 +221,23 @@ typedef struct cwa_provider_st {
|
||||||
* Retrieve SN.IFD - Terminal Serial Number.
|
* Retrieve SN.IFD - Terminal Serial Number.
|
||||||
*
|
*
|
||||||
* Result SN is 8 bytes long left padded with zeroes if required.
|
* Result SN is 8 bytes long left padded with zeroes if required.
|
||||||
|
* The result should stored in card->sm_ctx.info.session.cwa.ifd.sn
|
||||||
*
|
*
|
||||||
* @param card pointer to card structure
|
* @param card pointer to card structure
|
||||||
* @param buf where to store result (8 bytes)
|
|
||||||
* @return SC_SUCCESS if ok; else error
|
* @return SC_SUCCESS if ok; else error
|
||||||
*/
|
*/
|
||||||
int (*cwa_get_sn_ifd) (sc_card_t * card, u8 ** buf);
|
int (*cwa_get_sn_ifd) (sc_card_t * card);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get SN.ICC - Card Serial Number.
|
* Get SN.ICC - Card Serial Number.
|
||||||
*
|
*
|
||||||
* Result value is 8 bytes long left padded with zeroes if needed)
|
* Result value is 8 bytes long left padded with zeroes if needed)
|
||||||
|
* The result should stored in card->sm_ctx.info.session.cwa.icc.sn
|
||||||
*
|
*
|
||||||
* @param card pointer to card structure
|
* @param card pointer to card structure
|
||||||
* @param buf where to store result (8 bytes)
|
|
||||||
* @return SC_SUCCESS if ok; else error
|
* @return SC_SUCCESS if ok; else error
|
||||||
*/
|
*/
|
||||||
int (*cwa_get_sn_icc) (sc_card_t * card, u8 ** buf);
|
int (*cwa_get_sn_icc) (sc_card_t * card);
|
||||||
|
|
||||||
|
|
||||||
} cwa_provider_t;
|
} cwa_provider_t;
|
||||||
|
|
Loading…
Reference in New Issue