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:
rickyepoderi 2017-02-04 22:32:35 +01:00 committed by Frank Morgner
parent 68f8f0bfa7
commit c906c5e375
4 changed files with 101 additions and 220 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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 *********/

View File

@ -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;