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;
LOG_FUNC_CALLED(card->ctx);
/* 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_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");
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");
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) {
sc_log(card->ctx, "DNIe 3.0 detected => re-establish secure channel");
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);

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};
/**
* 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 **********************************/
/**
@ -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)
* @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;
}
@ -752,13 +747,12 @@ static int dnie_get_sn_ifd(sc_card_t * card, u8 ** buf)
* return SC_SUCCESS
*
* @param card pointer to card structure
* @param buf where to store result (8 bytes)
* @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);
*buf = sn_ifd_pin;
struct sm_cwa_session * sm = &card->sm_ctx.info.session.cwa;
memcpy(sm->ifd.sn, sn_ifd_pin, sizeof(sm->ifd.sn));
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
*
* @param card pointer to card structure
* @param buf where to store result (8 bytes)
* @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;
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);
LOG_TEST_RET(card->ctx, res, "Error in gettting serial number");
/* copy into sn_icc buffer.Remember that dnie sn has 7 bytes length */
memset(&sn_icc[0], 0, sizeof(sn_icc));
memcpy(&sn_icc[1], serial.value, 7);
/* return data */
*buf = &sn_icc[0];
memset(sm->icc.sn, 0, sizeof(sm->icc.sn));
memcpy(&sm->icc.sn[1], serial.value, 7);
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);
}
/**
* 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.
*
@ -842,11 +823,9 @@ cwa_provider_t *dnie_get_cwa_provider(sc_card_t * card)
/* pre and post operations */
res->cwa_create_pre_ops = dnie_create_pre_ops;
res->cwa_create_post_ops = dnie_create_post_ops;
/* Get ICC intermediate CA path */
res->cwa_get_icc_intermediate_ca_cert =
dnie_get_icc_intermediate_ca_cert;
res->cwa_get_icc_intermediate_ca_cert = dnie_get_icc_intermediate_ca_cert;
/* Get ICC certificate path */
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;
/* Get public key reference for IFD intermediate CA certificate */
res->cwa_get_intermediate_ca_pubkey_ref =
dnie_get_intermediate_ca_pubkey_ref;
res->cwa_get_intermediate_ca_pubkey_ref = dnie_get_intermediate_ca_pubkey_ref;
/* Get public key reference for IFD CVC certificate */
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;
ctx=card->ctx;
provider = GET_DNIE_PRIV_DATA(card)->cwa_provider;
if ((provider->status.session.state == CWA_SM_ACTIVE) &&
(card->sm_ctx.sm_mode == SM_MODE_TRANSMIT)) {
if (card->sm_ctx.sm_mode == SM_MODE_TRANSMIT) {
res = sc_transmit_apdu(card, apdu);
LOG_TEST_RET(ctx, res, "Error in dnie_wrap_apdu process");
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.
*
* @param card smart card info structure
* @param sm Secure Message session handling data structure
* @return SC_SUCCESS if ok; else error code
*
* 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;
struct sm_cwa_session * sm = &card->sm_ctx.info.session.cwa;
/* preliminary checks */
if (!card || !card->ctx )
return SC_ERROR_INVALID_ARGUMENTS;
if (!sm )
return SC_ERROR_SM_NOT_INITIALIZED;
LOG_FUNC_CALLED(card->ctx);
/* u8 arithmetic; exit loop if no carry */
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)
*
* @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 datalen length of data to send
* @return SC_SUCCESS if OK: else error code
*/
static int cwa_internal_auth(sc_card_t * card,
cwa_sm_status_t * sm, u8 * data, size_t datalen)
static int cwa_internal_auth(sc_card_t * card, u8 * sig, size_t sig_len, u8 * data, size_t datalen)
{
sc_apdu_t apdu;
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);
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);
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);
}
@ -554,13 +553,15 @@ static int cwa_internal_auth(sc_card_t * card,
* @param icc_pubkey public key of card
* @param ifd_privkey private RSA key of ifd
* @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
*/
static int cwa_prepare_external_auth(sc_card_t * card,
RSA * icc_pubkey,
RSA * ifd_privkey,
u8 * sn_icc, cwa_sm_status_t * sm)
u8 * sig,
size_t sig_len)
{
/* we have to compose following message:
data = E[PK.ICC.AUT](SIGMIN)
@ -594,6 +595,7 @@ static int cwa_prepare_external_auth(sc_card_t * card,
BIGNUM *bnres = NULL;
sc_context_t *ctx = NULL;
const BIGNUM *ifd_privkey_n, *ifd_privkey_e, *ifd_privkey_d;
struct sm_cwa_session * sm = &card->sm_ctx.info.session.cwa;
/* safety check */
if (!card || !card->ctx)
@ -601,7 +603,7 @@ static int cwa_prepare_external_auth(sc_card_t * card,
ctx = card->ctx;
LOG_FUNC_CALLED(ctx);
/* 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);
buf1 = 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 */
buf3[0] = 0x6A; /* iso padding */
RAND_bytes(buf3 + 1, 74); /* pRND */
RAND_bytes(sm->kifd, 32); /* Kifd */
memcpy(buf3 + 1 + 74, sm->kifd, 32); /* copy Kifd into buffer */
RAND_bytes(sm->ifd.k, 32); /* Kifd */
memcpy(buf3 + 1 + 74, sm->ifd.k, 32); /* copy Kifd into buffer */
/* prepare data to be hashed */
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 + 32, sm->rndicc, 8); /* copy 8 byte icc challenge */
memcpy(sha_buf + 74 + 32 + 8, sn_icc, 8); /* copy serialnr, 8 bytes */
memcpy(sha_buf + 74 + 32, sm->icc.rnd, 8); /* copy 8 byte icc challenge */
memcpy(sha_buf + 74 + 32 + 8, sm->icc.sn, 8); /* copy serialnr, 8 bytes */
SHA1(sha_buf, 74 + 32 + 8 + 8, sha_data);
/* copy hashed data into buffer */
memcpy(buf3 + 1 + 74 + 32, sha_data, SHA_DIGEST_LENGTH);
buf3[127] = 0xBC; /* iso padding */
/* encrypt with ifd private key */
len2 =
RSA_private_decrypt(128, buf3, buf2, ifd_privkey, RSA_NO_PADDING);
len2 = RSA_private_decrypt(128, buf3, buf2, ifd_privkey, RSA_NO_PADDING);
if (len2 < 0) {
msg = "Prepare external auth: ifd_privk 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 */
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";
res = SC_ERROR_SM_ENCRYPT_FAILED;
goto prepare_external_auth_end;
}
/* process done: copy result into cwa_internal buffer and return success */
memcpy(sm->sig, buf1, len1);
memcpy(sig, buf1, len1);
res = SC_SUCCESS;
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)
*
* @param data apdu signature content
* @param datalen signature length (128)
* @param card pointer to card data
* @param sig signature buffer
* @param sig signature buffer length
* @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;
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);
/* compose apdu for External Authenticate cmd */
dnie_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x82, 0x00, 0x00, 255, sizeof(sm->sig),
resp, MAX_RESP_BUFFER_SIZE, sm->sig, sizeof(sm->sig));
dnie_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x82, 0x00, 0x00, 255, sig_len,
resp, MAX_RESP_BUFFER_SIZE, sig, sig_len);
/* send composed apdu and parse result */
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
*
* @param card pointer to sc_card_t data
* @param sm pointer to cwa_internal_t data
* @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;
@ -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 kmac[4] = { 0x00, 0x00, 0x00, 0x02 };
sc_context_t *ctx = NULL;
struct sm_cwa_session * sm = &card->sm_ctx.info.session.cwa;
/* safety check */
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) */
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) */
memcpy(data, kseed, 32);
memcpy(data + 32, kenc, 4);
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 */
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 + 32, kmac, 4);
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 */
memcpy(sm->session.ssc, sm->rndicc + 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, sm->icc.rnd + 4, 4); /* 4 least significant bytes of rndicc */
memcpy(sm->ssc + 4, sm->ifd.rnd + 4, 4); /* 4 least significant bytes of rndifd */
/* arriving here means process ok */
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)
sc_log(ctx, msg);
else {
sc_log(ctx, "Kenc: %s", sc_dump_hex(sm->session.kenc, 16));
sc_log(ctx, "Kmac: %s", sc_dump_hex(sm->session.kmac, 16));
sc_log(ctx, "SSC: %s", sc_dump_hex(sm->session.ssc, 8));
sc_log(ctx, "Kenc: %s", sc_dump_hex(sm->session_enc, 16));
sc_log(ctx, "Kmac: %s", sc_dump_hex(sm->session_mac, 16));
sc_log(ctx, "SSC: %s", sc_dump_hex(sm->ssc, 8));
}
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 ifdbuf buffer containing ( RND.IFD || SN.IFD )
* @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
*/
static int cwa_verify_internal_auth(sc_card_t * card,
RSA * icc_pubkey,
RSA * ifd_privkey,
u8 * ifdbuf,
size_t ifdlen, cwa_sm_status_t * sm)
size_t ifdlen,
u8 * sig,
size_t sig_len)
{
int res = SC_SUCCESS;
char *msg = NULL;
@ -898,6 +903,7 @@ static int cwa_verify_internal_auth(sc_card_t * card,
BIGNUM *sigbn = NULL;
sc_context_t *ctx = NULL;
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)
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 */
len1 =
RSA_private_decrypt(sizeof(sm->sig), sm->sig, buf1, ifd_privkey,
RSA_NO_PADDING);
len1 = RSA_private_decrypt(sig_len, sig, buf1, ifd_privkey, RSA_NO_PADDING);
if (len1 <= 0) {
msg = "Verify Signature: decrypt with ifd privk 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 */
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;
verify_internal_done:
if (buf1)
@ -1044,15 +1048,14 @@ int cwa_create_secure_channel(sc_card_t * card,
int res = SC_SUCCESS;
char *msg = "Success";
u8 *sn_icc = NULL;
/* data to get and parse certificates */
X509 *icc_cert = NULL;
X509 *ca_cert = NULL;
EVP_PKEY *icc_pubkey = NULL;
EVP_PKEY *ifd_privkey = 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 */
u8 *buffer = NULL;
@ -1068,34 +1071,17 @@ int cwa_create_secure_channel(sc_card_t * card,
return SC_ERROR_SM_NOT_INITIALIZED;
/* comodity vars */
ctx = card->ctx;
sm = &(provider->status);
LOG_FUNC_CALLED(ctx);
/* check requested initialization method */
switch (flag) {
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;
sc_log(ctx, "Setting CWA SM status to none");
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
case CWA_SM_WARM: /* only initialize if not already done */
if (provider->status.session.state != CWA_SM_NONE) {
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);
}
case CWA_SM_ON: /* force sm initialization process */
sc_log(ctx, "CWA SM initialization requested");
break;
default:
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 */
sc_log(ctx, "Retrieve ICC serial number");
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) {
msg = "Retrieve ICC failed";
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)
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");
res = provider->cwa_get_sn_ifd(card, &buffer);
res = provider->cwa_get_sn_ifd(card);
if (res != SC_SUCCESS) {
msg = "Cannot get ifd serial number from provider";
goto csc_end;
}
RAND_bytes(sm->rndifd, 8); /* generate 8 random bytes */
memcpy(rndbuf, sm->rndifd, 8); /* insert RND.IFD into rndbuf */
memcpy(rndbuf + 8, buffer, 8); /* insert SN.IFD into rndbuf */
res = cwa_internal_auth(card, sm, rndbuf, 16);
RAND_bytes(sm->ifd.rnd, 8); /* generate 8 random bytes */
memcpy(rndbuf, sm->ifd.rnd, 8); /* insert RND.IFD into rndbuf */
memcpy(rndbuf + 8, sm->ifd.sn, 8); /* insert SN.IFD into rndbuf */
res = cwa_internal_auth(card, sig, 128, rndbuf, 16);
if (res != SC_SUCCESS) {
msg = "Internal auth cmd failed";
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 */
rndbuf, /* RND.IFD || SN.IFD */
16, /* rndbuf length; should be 16 */
sm /* sm data */
sig, 128
);
if (res != SC_SUCCESS) {
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 */
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) {
msg = "Get Challenge failed";
goto csc_end;
@ -1354,7 +1340,7 @@ int cwa_create_secure_channel(sc_card_t * card,
/* compose signature data for external auth */
res = cwa_prepare_external_auth(card,
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) {
msg = "Prepare external auth failed";
goto csc_end;
@ -1362,7 +1348,7 @@ int cwa_create_secure_channel(sc_card_t * card,
/* 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) {
msg = "External auth cmd failed";
goto csc_end;
@ -1370,7 +1356,7 @@ int cwa_create_secure_channel(sc_card_t * card,
/* Session key generation */
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) {
msg = "Session Key generation failed";
goto csc_end;
@ -1401,9 +1387,9 @@ int cwa_create_secure_channel(sc_card_t * card,
/* setup SM state according result */
if (res != SC_SUCCESS) {
sc_log(ctx, msg);
provider->status.session.state = CWA_SM_NONE;
card->sm_ctx.sm_mode = SM_MODE_NONE;
} else {
provider->status.session.state = CWA_SM_ACTIVE;
card->sm_ctx.sm_mode = SM_MODE_TRANSMIT;
}
LOG_FUNC_RETURN(ctx, res);
}
@ -1439,7 +1425,7 @@ int cwa_encode_apdu(sc_card_t * card,
size_t i, j; /* for xor loops */
int res = SC_SUCCESS;
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 *cryptbuf = NULL;
@ -1447,13 +1433,12 @@ int cwa_encode_apdu(sc_card_t * card,
if (!card || !card->ctx || !provider)
return SC_ERROR_INVALID_ARGUMENTS;
ctx = card->ctx;
sm_session = &(provider->status.session);
LOG_FUNC_CALLED(ctx);
/* check remaining arguments */
if (!from || !to || !sm_session)
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);
/* reserve extra bytes for padding and tlv header */
@ -1514,9 +1499,9 @@ int cwa_encode_apdu(sc_card_t * card,
/* prepare keys */
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);
DES_set_key_unchecked((const_DES_cblock *) & (sm_session->kenc[8]),
DES_set_key_unchecked((const_DES_cblock *) & (sm_session->session_enc[8]),
&k2);
/* 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)); */
/* 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) {
msg = "Error in computing SSC";
goto encode_end;
}
/* 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->kmac[8]),&k2);
DES_set_key_unchecked((const_DES_cblock *) & (sm_session->session_mac[0]),&k1);
DES_set_key_unchecked((const_DES_cblock *) & (sm_session->session_mac[8]),&k2);
memcpy(macbuf, sm_session->ssc, 8); /* start with computed SSC */
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;
char *msg = NULL; /* to store error messages */
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 */
if (!card || !card->ctx || !provider)
return SC_ERROR_INVALID_ARGUMENTS;
ctx = card->ctx;
sm_session = &(provider->status.session);
LOG_FUNC_CALLED(ctx);
/* check remaining arguments */
if ((apdu == NULL) || (sm_session == NULL))
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);
/* 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 */
/* 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) {
msg = "Error in computing SSC";
goto response_decode_end;
}
/* 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->kmac[8]), &k2);
DES_set_key_unchecked((const_DES_cblock *) & (sm_session->session_mac[0]), &k1);
DES_set_key_unchecked((const_DES_cblock *) & (sm_session->session_mac[8]), &k2);
memcpy(macbuf, sm_session->ssc, 8); /* start with computed SSC */
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;
}
/* 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);
DES_set_key_unchecked((const_DES_cblock *) & (sm_session->kenc[8]),
DES_set_key_unchecked((const_DES_cblock *) & (sm_session->session_enc[8]),
&k2);
/* decrypt into response buffer
* 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) */
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;
}
/* 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;
}
@ -1967,50 +1951,6 @@ static int default_get_sn_icc(sc_card_t * card, u8 ** buf)
static cwa_provider_t default_cwa_provider = {
/************ 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 *********/

View File

@ -27,16 +27,9 @@
#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 */
#define CWA_SM_OFF 0x00 /** Disable SM channel */
#define CWA_SM_COLD 0x01 /** force creation of a new 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 */
#define CWA_SM_ON 0x01 /** Enable SM channel */
/* TAGS for encoded APDU's */
#define CWA_SM_PLAIN_TAG 0x81 /** Plain value (to be protected by CC) */
@ -52,40 +45,11 @@
#include <openssl/x509.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
* Secure Channel.
*/
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 *********/
@ -257,23 +221,23 @@ typedef struct cwa_provider_st {
* Retrieve SN.IFD - Terminal Serial Number.
*
* 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 buf where to store result (8 bytes)
* @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 buf where to store result (8 bytes)
* @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;