From c906c5e3755cece93f75444f20ab0e97814879b6 Mon Sep 17 00:00:00 2001 From: rickyepoderi Date: Sat, 4 Feb 2017 22:32:35 +0100 Subject: [PATCH] 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 --- src/libopensc/card-dnie.c | 6 +- src/libopensc/cwa-dnie.c | 49 +++------ src/libopensc/cwa14890.c | 216 ++++++++++++++------------------------ src/libopensc/cwa14890.h | 50 ++------- 4 files changed, 101 insertions(+), 220 deletions(-) diff --git a/src/libopensc/card-dnie.c b/src/libopensc/card-dnie.c index 0a0e7b6d..dbbefaba 100644 --- a/src/libopensc/card-dnie.c +++ b/src/libopensc/card-dnie.c @@ -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); diff --git a/src/libopensc/cwa-dnie.c b/src/libopensc/cwa-dnie.c index 5669b3c4..9862eb59 100644 --- a/src/libopensc/cwa-dnie.c +++ b/src/libopensc/cwa-dnie.c @@ -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); diff --git a/src/libopensc/cwa14890.c b/src/libopensc/cwa14890.c index bf300a2e..6b978a5c 100644 --- a/src/libopensc/cwa14890.c +++ b/src/libopensc/cwa14890.c @@ -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 *********/ diff --git a/src/libopensc/cwa14890.h b/src/libopensc/cwa14890.h index ad0c3a22..ca74cda4 100644 --- a/src/libopensc/cwa14890.h +++ b/src/libopensc/cwa14890.h @@ -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 #include -/** - * 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;