sm: change SM data types, thanks to Frank Morgner for revision

http://www.opensc-project.org/pipermail/opensc-devel/2012-July/018232.html
This commit is contained in:
Viktor Tarasov 2012-07-29 21:41:44 +02:00
parent 7301715624
commit c7827e5e4b
9 changed files with 172 additions and 168 deletions

View File

@ -2151,7 +2151,7 @@ authentic_sm_acl_init (struct sc_card *card, struct sm_info *sm_info, int cmd,
unsigned char *resp, size_t *resp_len)
{
struct sc_context *ctx = card->ctx;
struct sm_type_params_gp *params_gp = &sm_info->sm_params.gp;
struct sm_type_params_gp *params_gp = &sm_info->session.gp.params;
struct sc_remote_data rdata;
int rv;

View File

@ -2,7 +2,7 @@
* iasecc.h Support for IAS/ECC smart cards
*
* Copyright (C) 2010 Viktor Tarasov <vtarasov@opentrust.com>
* OpenTrust <www.opentrust.com>
* OpenTrust <www.opentrust.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -157,6 +157,7 @@ iasecc_sm_external_authentication(struct sc_card *card, unsigned skey_ref, int *
struct sc_context *ctx = card->ctx;
#ifdef ENABLE_SM
struct sm_info *sm_info = &card->sm_ctx.info;
struct sm_cwa_session *cwa_session = &sm_info->session.cwa;
struct sc_remote_data rdata;
struct sc_apdu apdu;
unsigned char sbuf[0x100];
@ -173,9 +174,9 @@ iasecc_sm_external_authentication(struct sc_card *card, unsigned skey_ref, int *
sm_info->serialnr = card->serialnr;
sm_info->card_type = card->type;
sm_info->sm_type = SM_TYPE_CWA14890;
sm_info->sm_params.cwa.crt_at.usage = IASECC_UQB_AT_EXTERNAL_AUTHENTICATION;
sm_info->sm_params.cwa.crt_at.algo = IASECC_ALGORITHM_ROLE_AUTH;
sm_info->sm_params.cwa.crt_at.refs[0] = skey_ref;
cwa_session->params.crt_at.usage = IASECC_UQB_AT_EXTERNAL_AUTHENTICATION;
cwa_session->params.crt_at.algo = IASECC_ALGORITHM_ROLE_AUTH;
cwa_session->params.crt_at.refs[0] = skey_ref;
offs = 0;
sbuf[offs++] = IASECC_CRT_TAG_ALGO;
@ -195,7 +196,7 @@ iasecc_sm_external_authentication(struct sc_card *card, unsigned skey_ref, int *
rv = sc_check_sw(card, apdu.sw1, apdu.sw2);
LOG_TEST_RET(ctx, rv, "iasecc_sm_external_authentication(): set SE error");
rv = sc_get_challenge(card, sm_info->schannel.card_challenge, sizeof(sm_info->schannel.card_challenge));
rv = sc_get_challenge(card, cwa_session->card_challenge, sizeof(cwa_session->card_challenge));
LOG_TEST_RET(ctx, rv, "iasecc_sm_external_authentication(): set SE error");
sc_remote_data_init(&rdata);
@ -227,7 +228,7 @@ iasecc_sm_se_mutual_authentication(struct sc_card *card, unsigned se_num)
#ifdef ENABLE_SM
struct sm_info *sm_info = &card->sm_ctx.info;
struct iasecc_se_info se;
struct sc_crt *crt = &sm_info->sm_params.cwa.crt_at;
struct sc_crt *crt = &sm_info->session.cwa.params.crt_at;
struct sc_apdu apdu;
unsigned char sbuf[0x100];
int rv, offs;
@ -305,7 +306,7 @@ iasecc_sm_initialize(struct sc_card *card, unsigned se_num, unsigned cmd)
struct sc_context *ctx = card->ctx;
#ifdef ENABLE_SM
struct sm_info *sm_info = &card->sm_ctx.info;
struct sm_cwa_session *cwa_session = &sm_info->schannel.session.cwa;
struct sm_cwa_session *cwa_session = &sm_info->session.cwa;
struct sc_remote_data rdata;
int rv;
@ -320,7 +321,7 @@ iasecc_sm_initialize(struct sc_card *card, unsigned se_num, unsigned cmd)
rv = iasecc_sm_se_mutual_authentication(card, se_num);
LOG_TEST_RET(ctx, rv, "iasecc_sm_initialize() MUTUAL AUTHENTICATION failed");
rv = iasecc_sm_get_challenge(card, sm_info->schannel.card_challenge, SM_SMALL_CHALLENGE_LEN);
rv = iasecc_sm_get_challenge(card, cwa_session->card_challenge, SM_SMALL_CHALLENGE_LEN);
LOG_TEST_RET(ctx, rv, "iasecc_sm_initialize() GET CHALLENGE failed");
sc_remote_data_init(&rdata);
@ -351,7 +352,7 @@ iasecc_sm_initialize(struct sc_card *card, unsigned se_num, unsigned cmd)
rdata.free(&rdata);
sc_log(ctx, "MA data(len:%i) '%s'", cwa_session->mdata_len, sc_dump_hex(cwa_session->mdata, cwa_session->mdata_len));
if (sm_info->schannel.session.cwa.mdata_len != 0x48)
if (cwa_session->mdata_len != 0x48)
LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "iasecc_sm_initialize() invalid MUTUAL AUTHENTICATE result data");
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
@ -370,7 +371,7 @@ iasecc_sm_cmd(struct sc_card *card, struct sc_remote_data *rdata)
struct sc_context *ctx = card->ctx;
#ifdef ENABLE_SM
struct sm_info *sm_info = &card->sm_ctx.info;
struct sm_cwa_session *session = &sm_info->schannel.session.cwa;
struct sm_cwa_session *session = &sm_info->session.cwa;
struct sc_remote_apdu *rapdu = NULL;
int rv;

View File

@ -60,9 +60,9 @@ extern "C" {
#define SM_CMD_FILE_CREATE 0x203
#define SM_CMD_FILE_DELETE 0x204
#define SM_CMD_PIN 0x300
#define SM_CMD_PIN_VERIFY 0x301
#define SM_CMD_PIN_VERIFY 0x301
#define SM_CMD_PIN_RESET 0x302
#define SM_CMD_PIN_SET_PIN 0x303
#define SM_CMD_PIN_SET_PIN 0x303
#define SM_CMD_PSO 0x400
#define SM_CMD_PSO_DST 0x401
#define SM_CMD_APDU 0x500
@ -93,7 +93,7 @@ extern "C" {
/* Global Platform (SCP01) data types */
/*
* @struct sm_type_params_gp
* Global Platform SM channel parameters
* Global Platform SM channel parameters
*/
struct sm_type_params_gp {
unsigned level;
@ -105,9 +105,9 @@ struct sm_type_params_gp {
/*
* @struct sm_gp_keyset
* Global Platform keyset:
* - version, index;
* - keyset presented in three parts: 'ENC', 'MAC' and 'KEK';
* Global Platform keyset:
* - version, index;
* - keyset presented in three parts: 'ENC', 'MAC' and 'KEK';
* - keyset presented in continuous manner - raw or 'to be diversified'.
*/
struct sm_gp_keyset {
@ -123,9 +123,16 @@ struct sm_gp_keyset {
/*
* @struct sm_gp_session
* Global Platform SM session data
* Global Platform SM session data
*/
struct sm_gp_session {
struct sm_gp_keyset gp_keyset;
struct sm_type_params_gp params;
unsigned char host_challenge[SM_SMALL_CHALLENGE_LEN];
unsigned char card_challenge[SM_SMALL_CHALLENGE_LEN];
unsigned char *session_enc, *session_mac, *session_kek;
unsigned char mac_icv[8];
};
@ -142,9 +149,9 @@ struct sm_type_params_cwa {
/*
* @struct sm_cwa_keyset
* CWA keyset:
* - SDO reference;
* - 'ENC' and 'MAC' 3DES keys.
* CWA keyset:
* - SDO reference;
* - 'ENC' and 'MAC' 3DES keys.
*/
struct sm_cwa_keyset {
unsigned sdo_reference;
@ -154,9 +161,9 @@ struct sm_cwa_keyset {
/*
* @struct sm_cwa_token_data
* CWA token data:
* - serial;
* - 'small' random;
* CWA token data:
* - serial;
* - 'small' random;
* - 'big' random.
*/
struct sm_cwa_token_data {
@ -167,13 +174,17 @@ struct sm_cwa_token_data {
/*
* @struct sm_cwa_session
* CWA working SM session data:
* - ICC and IFD token data;
* - ENC and MAC session keys;
* - SSC (SM Sequence Counter);
* - 'mutual authentication' data.
* CWA working SM session data:
* - ICC and IFD token data;
* - ENC and MAC session keys;
* - SSC (SM Sequence Counter);
* - 'mutual authentication' data.
*/
struct sm_cwa_session {
struct sm_cwa_keyset cwa_keyset;
struct sm_type_params_cwa params;
struct sm_cwa_token_data icc;
struct sm_cwa_token_data ifd;
@ -182,37 +193,20 @@ struct sm_cwa_session {
unsigned char ssc[8];
unsigned char host_challenge[SM_SMALL_CHALLENGE_LEN];
unsigned char card_challenge[SM_SMALL_CHALLENGE_LEN];
unsigned char mdata[0x48];
size_t mdata_len;
};
/*
* @struct sc_secure channel
* data type to open and maintain the Secure Messaging session.
*/
struct sm_secure_channel {
union {
struct sm_gp_keyset gp;
struct sm_cwa_keyset cwa;
} keyset;
union {
struct sm_gp_session gp;
struct sm_cwa_session cwa;
} session;
unsigned char host_challenge[SM_SMALL_CHALLENGE_LEN];
unsigned char card_challenge[SM_SMALL_CHALLENGE_LEN];
};
/*
* @struct sc_info is the
* placehold for the secure messaging working data:
* - SM type;
* - SM session state;
* - command to execute by external SM module;
* - data related to the current card context.
* placehold for the secure messaging working data:
* - SM type;
* - SM session state;
* - command to execute by external SM module;
* - data related to the current card context.
*/
struct sm_info {
char config_section[64];
@ -223,9 +217,9 @@ struct sm_info {
unsigned sm_type;
union {
struct sm_type_params_gp gp;
struct sm_type_params_cwa cwa;
} sm_params;
struct sm_gp_session gp;
struct sm_cwa_session cwa;
} session;
struct sc_serial_number serialnr;
@ -237,13 +231,11 @@ struct sm_info {
unsigned char *rdata;
size_t rdata_len;
struct sm_secure_channel schannel;
};
/*
* @struct sm_card_response
* data type to return card response.
* data type to return card response.
*/
typedef struct sm_card_response {
int num;
@ -265,11 +257,11 @@ struct sc_card;
/*
* @struct sm_card_operations
* card driver handlers related to secure messaging (in 'APDU TRANSMIT' mode)
* - 'open' - initialize SM session;
* - 'encode apdu' - SM encoding of the raw APDU;
* - 'decrypt response' - decode card answer;
* - 'close' - close SM session.
* card driver handlers related to secure messaging (in 'APDU TRANSMIT' mode)
* - 'open' - initialize SM session;
* - 'encode apdu' - SM encoding of the raw APDU;
* - 'decrypt response' - decode card answer;
* - 'close' - close SM session.
*/
struct sm_card_operations {
int (*open)(struct sc_card *card);
@ -285,12 +277,12 @@ struct sm_card_operations {
/*
* @struct sm_module_operations
* API to use external SM modules:
* - 'initiliaze' - get APDU(s) to initialize SM session;
* - 'get apdus' - get secured APDUs to execute particular command;
* - 'finalize' - get APDU(s) to finalize SM session;
* - 'module init' - initialize external module (allocate data, read configuration, ...);
* - 'module cleanup' - free resources allocated by external module.
* API to use external SM modules:
* - 'initiliaze' - get APDU(s) to initialize SM session;
* - 'get apdus' - get secured APDUs to execute particular command;
* - 'finalize' - get APDU(s) to finalize SM session;
* - 'module init' - initialize external module (allocate data, read configuration, ...);
* - 'module cleanup' - free resources allocated by external module.
*/
struct sm_module_operations {
int (*initialize)(struct sc_context *ctx, struct sm_info *info,
@ -314,8 +306,8 @@ typedef struct sm_module {
} sm_module_t;
/* @struct sm_context
* SM context -- top level of the SM data type
* - SM mode ('ACL' or 'APDU TRANSMIT'), flags;
* SM context -- top level of the SM data type
* - SM mode ('ACL' or 'APDU TRANSMIT'), flags;
* - working SM data;
* - card operations related to SM in 'APDU TRANSMIT' mode;
* - external SM module;

View File

@ -48,25 +48,27 @@ static int
sm_oberthur_diversify_keyset(struct sc_context *ctx, struct sm_info *sm_info,
unsigned char *idata, size_t idata_len)
{
struct sm_secure_channel *schannel = &sm_info->schannel;
struct sm_gp_keyset *keyset = &schannel->keyset.gp;
struct sm_gp_session *gp_session = &sm_info->session.gp;
struct sm_gp_keyset *gp_keyset = &sm_info->session.gp.gp_keyset;
unsigned char master_key[16] = {
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
};
unsigned char *keys[3] = {
keyset->enc,keyset->mac,keyset->kek
gp_keyset->enc,
gp_keyset->mac,
gp_keyset->kek
};
unsigned char key_buff[16];
unsigned char *tmp;
unsigned char *tmp;
int rv = 0, ii, tmp_len;
if (keyset->kmc_len == 48) {
if (gp_keyset->kmc_len == 48) {
for (ii=0; ii<3; ii++)
memcpy(keys[ii], keyset->kmc + 16*ii, 16);
memcpy(keys[ii], gp_keyset->kmc + 16*ii, 16);
}
else if (keyset->kmc_len == 16 || keyset->kmc_len == 0) {
if (keyset->kmc_len == 16)
memcpy(master_key, keyset->kmc, 16);
else if (gp_keyset->kmc_len == 16 || gp_keyset->kmc_len == 0) {
if (gp_keyset->kmc_len == 16)
memcpy(master_key, gp_keyset->kmc, 16);
sc_log(ctx, "KMC: %s", sc_dump_hex(master_key, sizeof(master_key)));
for (ii=0; ii<3; ii++) {
key_buff[0] = key_buff[8] = 0;
@ -83,7 +85,7 @@ sm_oberthur_diversify_keyset(struct sc_context *ctx, struct sm_info *sm_info,
rv = sm_encrypt_des_ecb3(master_key, key_buff, sizeof(key_buff), &tmp, &tmp_len);
LOG_TEST_RET(ctx, rv, "GP init session: cannot derivate key");
memcpy(keys[ii], tmp, sizeof(keyset->enc));
memcpy(keys[ii], tmp, sizeof(gp_keyset->enc));
free(tmp);
}
}
@ -95,20 +97,20 @@ sm_oberthur_diversify_keyset(struct sc_context *ctx, struct sm_info *sm_info,
char dump_buf[2048];
sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL,
schannel->card_challenge, sizeof(schannel->card_challenge), dump_buf, sizeof(dump_buf));
gp_session->card_challenge, sizeof(gp_session->card_challenge), dump_buf, sizeof(dump_buf));
sc_log(ctx, "Card challenge: %s", dump_buf);
sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL,
schannel->host_challenge, sizeof(schannel->host_challenge), dump_buf, sizeof(dump_buf));
gp_session->host_challenge, sizeof(gp_session->host_challenge), dump_buf, sizeof(dump_buf));
sc_log(ctx, "Host challenge: %s", dump_buf);
sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL, keyset->enc, sizeof(keyset->enc), dump_buf, sizeof(dump_buf));
sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL, gp_keyset->enc, sizeof(gp_keyset->enc), dump_buf, sizeof(dump_buf));
sc_log(ctx, "ENC: %s", dump_buf);
sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL, keyset->mac, sizeof(keyset->mac), dump_buf, sizeof(dump_buf));
sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL, gp_keyset->mac, sizeof(gp_keyset->mac), dump_buf, sizeof(dump_buf));
sc_log(ctx, "MAC: %s", dump_buf);
sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL, keyset->kek, sizeof(keyset->kek), dump_buf, sizeof(dump_buf));
sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL, gp_keyset->kek, sizeof(gp_keyset->kek), dump_buf, sizeof(dump_buf));
sc_log(ctx, "KEK: %s", dump_buf);
}
@ -328,7 +330,7 @@ sm_authentic_get_apdus(struct sc_context *ctx, struct sm_info *sm_info,
rv = sm_authentic_get_apdu_release(ctx, sm_info, init_data, init_len, out, out_num);
LOG_TEST_RET(ctx, rv, "SM get APDUs: add 'release' failed");
sm_gp_close_session(ctx, &sm_info->schannel);
sm_gp_close_session(ctx, &sm_info->session.gp);
}
#endif
LOG_FUNC_RETURN(ctx, rv);

View File

@ -597,8 +597,8 @@ int
sm_iasecc_get_apdus(struct sc_context *ctx, struct sm_info *sm_info,
unsigned char *init_data, size_t init_len, struct sc_remote_data *rdata, int release_sm)
{
struct sm_cwa_session *session_data = &sm_info->schannel.session.cwa;
struct sm_cwa_keyset *keyset = &sm_info->schannel.keyset.cwa;
struct sm_cwa_session *cwa_session = &sm_info->session.cwa;
struct sm_cwa_keyset *cwa_keyset = &sm_info->session.cwa.cwa_keyset;
int rv;
LOG_FUNC_CALLED(ctx);
@ -609,15 +609,15 @@ sm_iasecc_get_apdus(struct sc_context *ctx, struct sm_info *sm_info,
sc_log(ctx, "SM IAS/ECC get APDUs: rdata:%p", rdata);
sc_log(ctx, "SM IAS/ECC get APDUs: serial %s", sc_dump_hex(sm_info->serialnr.value, sm_info->serialnr.len));
rv = sm_cwa_decode_authentication_data(ctx, keyset, session_data, init_data);
rv = sm_cwa_decode_authentication_data(ctx, cwa_keyset, cwa_session, init_data);
LOG_TEST_RET(ctx, rv, "SM IAS/ECC get APDUs: decode authentication data error");
rv = sm_cwa_init_session_keys(ctx, session_data, sm_info->sm_params.cwa.crt_at.algo);
rv = sm_cwa_init_session_keys(ctx, cwa_session, cwa_session->params.crt_at.algo);
LOG_TEST_RET(ctx, rv, "SM IAS/ECC get APDUs: cannot get session keys");
sc_log(ctx, "SKENC %s", sc_dump_hex(session_data->session_enc, sizeof(session_data->session_enc)));
sc_log(ctx, "SKMAC %s", sc_dump_hex(session_data->session_mac, sizeof(session_data->session_mac)));
sc_log(ctx, "SSC %s", sc_dump_hex(session_data->ssc, sizeof(session_data->ssc)));
sc_log(ctx, "SKENC %s", sc_dump_hex(cwa_session->session_enc, sizeof(cwa_session->session_enc)));
sc_log(ctx, "SKMAC %s", sc_dump_hex(cwa_session->session_mac, sizeof(cwa_session->session_mac)));
sc_log(ctx, "SSC %s", sc_dump_hex(cwa_session->ssc, sizeof(cwa_session->ssc)));
switch (sm_info->cmd) {
case SM_CMD_FILE_READ:
@ -682,7 +682,7 @@ int
sm_iasecc_decode_card_data(struct sc_context *ctx, struct sm_info *sm_info, struct sc_remote_data *rdata,
unsigned char *out, size_t out_len)
{
struct sm_cwa_session *session_data = &sm_info->schannel.session.cwa;
struct sm_cwa_session *session_data = &sm_info->session.cwa;
struct sc_asn1_entry asn1_iasecc_sm_data_object[4];
struct sc_remote_apdu *rapdu = NULL;
int rv, offs = 0;

View File

@ -248,10 +248,10 @@ sm_cwa_incr_ssc(struct sm_cwa_session *session_data)
int
sm_cwa_initialize(struct sc_context *ctx, struct sm_info *sm_info, struct sc_remote_data *rdata)
{
struct sm_cwa_session *session_data = &sm_info->schannel.session.cwa;
struct sm_cwa_keyset *keyset = &sm_info->schannel.keyset.cwa;
struct sm_cwa_session *cwa_session = &sm_info->session.cwa;
struct sm_cwa_keyset *cwa_keyset = &sm_info->session.cwa.cwa_keyset;
struct sc_serial_number sn = sm_info->serialnr;
size_t icc_sn_len = sizeof(session_data->icc.sn);
size_t icc_sn_len = sizeof(cwa_session->icc.sn);
struct sc_remote_apdu *new_rapdu = NULL;
struct sc_apdu *apdu = NULL;
unsigned char buf[0x100], *encrypted;
@ -261,9 +261,9 @@ sm_cwa_initialize(struct sc_context *ctx, struct sm_info *sm_info, struct sc_rem
LOG_FUNC_CALLED(ctx);
sc_log(ctx, "SM IAS/ECC initialize: serial %s", sc_dump_hex(sm_info->serialnr.value, sm_info->serialnr.len));
sc_log(ctx, "SM IAS/ECC initialize: card challenge %s", sc_dump_hex(sm_info->schannel.card_challenge, 8));
sc_log(ctx, "SM IAS/ECC initialize: card challenge %s", sc_dump_hex(cwa_session->card_challenge, 8));
sc_log(ctx, "SM IAS/ECC initialize: current_df_path %s", sc_print_path(&sm_info->current_path_df));
sc_log(ctx, "SM IAS/ECC initialize: CRT_AT reference 0x%X", sm_info->sm_params.cwa.crt_at.refs[0]);
sc_log(ctx, "SM IAS/ECC initialize: CRT_AT reference 0x%X", cwa_session->params.crt_at.refs[0]);
if (!rdata || !rdata->alloc)
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
@ -272,27 +272,27 @@ sm_cwa_initialize(struct sc_context *ctx, struct sm_info *sm_info, struct sc_rem
LOG_TEST_RET(ctx, rv, "SM GP decode card answer: cannot allocate remote APDU");
apdu = &new_rapdu->apdu;
memcpy(&session_data->icc.rnd[0], sm_info->schannel.card_challenge, 8);
memcpy(&cwa_session->icc.rnd[0], cwa_session->card_challenge, 8);
if (sn.len > icc_sn_len)
memcpy(&session_data->icc.sn[0], &sn.value[sn.len - icc_sn_len], icc_sn_len);
memcpy(&cwa_session->icc.sn[0], &sn.value[sn.len - icc_sn_len], icc_sn_len);
else
memcpy(&session_data->icc.sn[icc_sn_len - sn.len], &sn.value[0], sn.len);
memcpy(&cwa_session->icc.sn[icc_sn_len - sn.len], &sn.value[0], sn.len);
if (sm_info->cmd == SM_CMD_EXTERNAL_AUTH) {
offs = sm_cwa_encode_external_auth_data(ctx, session_data, buf, sizeof(buf));
offs = sm_cwa_encode_external_auth_data(ctx, cwa_session, buf, sizeof(buf));
if (offs != 0x10)
LOG_FUNC_RETURN(ctx, offs);
}
else {
offs = sm_cwa_encode_mutual_auth_data(ctx, session_data, buf, sizeof(buf));
offs = sm_cwa_encode_mutual_auth_data(ctx, cwa_session, buf, sizeof(buf));
if (offs != 0x40)
LOG_FUNC_RETURN(ctx, offs);
}
sc_log(ctx, "S(%i) %s", offs, sc_dump_hex(buf, offs));
rv = sm_encrypt_des_cbc3(ctx, keyset->enc, buf, offs, &encrypted, &encrypted_len, 1);
rv = sm_encrypt_des_cbc3(ctx, cwa_keyset->enc, buf, offs, &encrypted, &encrypted_len, 1);
LOG_TEST_RET(ctx, rv, "_encrypt_des_cbc3() failed");
sc_log(ctx, "ENCed(%i) %s", encrypted_len, sc_dump_hex(encrypted, encrypted_len));
@ -300,7 +300,7 @@ sm_cwa_initialize(struct sc_context *ctx, struct sm_info *sm_info, struct sc_rem
memcpy(buf, encrypted, encrypted_len);
offs = encrypted_len;
rv = sm_cwa_get_mac(ctx, keyset->mac, &icv, buf, offs, &cblock, 1);
rv = sm_cwa_get_mac(ctx, cwa_keyset->mac, &icv, buf, offs, &cblock, 1);
LOG_TEST_RET(ctx, rv, "sm_ecc_get_mac() failed");
sc_log(ctx, "MACed(%i) %s", sizeof(cblock), sc_dump_hex(cblock, sizeof(cblock)));
@ -323,7 +323,7 @@ sm_cwa_initialize(struct sc_context *ctx, struct sm_info *sm_info, struct sc_rem
int
sm_cwa_securize_apdu(struct sc_context *ctx, struct sm_info *sm_info, struct sc_remote_apdu *rapdu)
{
struct sm_cwa_session *session_data = &sm_info->schannel.session.cwa;
struct sm_cwa_session *session_data = &sm_info->session.cwa;
struct sc_apdu *apdu = &rapdu->apdu;
unsigned char sbuf[0x400];
DES_cblock cblock, icv;

View File

@ -109,7 +109,7 @@ sm_gp_decode_card_answer(struct sc_context *ctx, struct sc_remote_data *rdata, u
sc_format_asn1_entry(asn1_authentic_card_response + 2, &card_data, &card_data_len, 0);
sc_format_asn1_entry(asn1_card_response + 0, asn1_authentic_card_response, NULL, 0);
rv = sc_asn1_decode(ctx, asn1_card_response, hex + hex_len - len_left, len_left, NULL, &len_left);
rv = sc_asn1_decode(ctx, asn1_card_response, hex + hex_len - len_left, len_left, NULL, &len_left);
if (rv) {
sc_log(ctx, "SM GP decode card answer: ASN.1 parse error: %s", sc_strerror(rv));
return rv;
@ -141,6 +141,8 @@ int
sm_gp_initialize(struct sc_context *ctx, struct sm_info *sm_info, struct sc_remote_data *rdata)
{
struct sc_serial_number sn = sm_info->serialnr;
struct sm_gp_session *gp_session = &sm_info->session.gp;
struct sm_gp_keyset *gp_keyset = &sm_info->session.gp.gp_keyset;
struct sc_remote_apdu *new_rapdu = NULL;
struct sc_apdu *apdu = NULL;
int rv;
@ -148,7 +150,7 @@ sm_gp_initialize(struct sc_context *ctx, struct sm_info *sm_info, struct sc_rem
LOG_FUNC_CALLED(ctx);
sc_log(ctx, "SM GP initialize: serial:%s", sc_dump_hex(sn.value, sn.len));
sc_log(ctx, "SM GP initialize: current_df_path %s", sc_print_path(&sm_info->current_path_df));
sc_log(ctx, "SM GP initialize: KMC length %i", sm_info->schannel.keyset.gp.kmc_len);
sc_log(ctx, "SM GP initialize: KMC length %i", gp_keyset->kmc_len);
if (!rdata || !rdata->alloc)
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
@ -157,7 +159,7 @@ sm_gp_initialize(struct sc_context *ctx, struct sm_info *sm_info, struct sc_rem
LOG_TEST_RET(ctx, rv, "SM GP decode card answer: cannot allocate remote APDU");
apdu = &new_rapdu->apdu;
rv = RAND_bytes(sm_info->schannel.host_challenge, SM_SMALL_CHALLENGE_LEN);
rv = RAND_bytes(gp_session->host_challenge, SM_SMALL_CHALLENGE_LEN);
if (!rv)
LOG_FUNC_RETURN(ctx, SC_ERROR_SM_RAND_FAILED);
@ -169,24 +171,24 @@ sm_gp_initialize(struct sc_context *ctx, struct sm_info *sm_info, struct sc_rem
apdu->lc = SM_SMALL_CHALLENGE_LEN;
apdu->le = 0x1C;
apdu->datalen = SM_SMALL_CHALLENGE_LEN;
memcpy(&new_rapdu->sbuf[0], sm_info->schannel.host_challenge, SM_SMALL_CHALLENGE_LEN);
memcpy(&new_rapdu->sbuf[0], gp_session->host_challenge, SM_SMALL_CHALLENGE_LEN);
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}
static unsigned char *
sc_gp_get_session_key(struct sc_context *ctx, struct sm_secure_channel *sc,
sc_gp_get_session_key(struct sc_context *ctx, struct sm_gp_session *gp_session,
unsigned char *key)
{
int out_len;
unsigned char *out;
unsigned char deriv[16];
memcpy(deriv, sc->card_challenge + 4, 4);
memcpy(deriv + 4, sc->host_challenge, 4);
memcpy(deriv + 8, sc->card_challenge, 4);
memcpy(deriv + 12, sc->host_challenge + 4, 4);
memcpy(deriv, gp_session->card_challenge + 4, 4);
memcpy(deriv + 4, gp_session->host_challenge, 4);
memcpy(deriv + 8, gp_session->card_challenge, 4);
memcpy(deriv + 12, gp_session->host_challenge + 4, 4);
if (sm_encrypt_des_ecb3(key, deriv, 16, &out, &out_len)) {
if (ctx)
@ -266,24 +268,27 @@ sm_gp_get_mac(unsigned char *key, DES_cblock *icv,
static int
sm_gp_parse_init_data(struct sc_context *ctx, struct sm_secure_channel *sc,
sm_gp_parse_init_data(struct sc_context *ctx, struct sm_gp_session *gp_session,
unsigned char *init_data, size_t init_len)
{
struct sm_gp_keyset *gp_keyset = &gp_session->gp_keyset;
if(init_len != 0x1C)
return SC_ERROR_INVALID_DATA;
sc->keyset.gp.version = *(init_data + 10);
sc->keyset.gp.index = *(init_data + 11);
memcpy(sc->card_challenge, init_data + 12, SM_SMALL_CHALLENGE_LEN);
gp_keyset->version = *(init_data + 10);
gp_keyset->index = *(init_data + 11);
memcpy(gp_session->card_challenge, init_data + 12, SM_SMALL_CHALLENGE_LEN);
return SC_SUCCESS;
}
static int
sm_gp_init_session(struct sc_context *ctx, struct sm_secure_channel *sc,
sm_gp_init_session(struct sc_context *ctx, struct sm_gp_session *gp_session,
unsigned char *adata, size_t adata_len)
{
struct sm_gp_keyset *gp_keyset = &gp_session->gp_keyset;
unsigned char cksum[8];
int rv;
@ -293,19 +298,19 @@ sm_gp_init_session(struct sc_context *ctx, struct sm_secure_channel *sc,
sc_log(ctx, "SM GP init session: auth.data %s", sc_dump_hex(adata, 8));
sc->session.gp.session_enc = sc_gp_get_session_key(ctx, sc, sc->keyset.gp.enc);
sc->session.gp.session_mac = sc_gp_get_session_key(ctx, sc, sc->keyset.gp.mac);
sc->session.gp.session_kek = sc_gp_get_session_key(ctx, sc, sc->keyset.gp.kek);
if (!sc->session.gp.session_enc || !sc->session.gp.session_mac || !sc->session.gp.session_kek)
gp_session->session_enc = sc_gp_get_session_key(ctx, gp_session, gp_keyset->enc);
gp_session->session_mac = sc_gp_get_session_key(ctx, gp_session, gp_keyset->mac);
gp_session->session_kek = sc_gp_get_session_key(ctx, gp_session, gp_keyset->kek);
if (!gp_session->session_enc || !gp_session->session_mac || !gp_session->session_kek)
LOG_TEST_RET(ctx, SC_ERROR_SM_NO_SESSION_KEYS, "SM GP init session: get session keys error");
memcpy(sc->session.gp.session_kek, sc->keyset.gp.kek, 16);
memcpy(gp_session->session_kek, gp_keyset->kek, 16);
sc_log(ctx, "SM GP init session: session ENC: %s", sc_dump_hex(sc->session.gp.session_enc, 16));
sc_log(ctx, "SM GP init session: session MAC: %s", sc_dump_hex(sc->session.gp.session_mac, 16));
sc_log(ctx, "SM GP init session: session KEK: %s", sc_dump_hex(sc->session.gp.session_kek, 16));
sc_log(ctx, "SM GP init session: session ENC: %s", sc_dump_hex(gp_session->session_enc, 16));
sc_log(ctx, "SM GP init session: session MAC: %s", sc_dump_hex(gp_session->session_mac, 16));
sc_log(ctx, "SM GP init session: session KEK: %s", sc_dump_hex(gp_session->session_kek, 16));
memset(cksum, 0, sizeof(cksum));
rv = sm_gp_get_cryptogram(sc->session.gp.session_enc, sc->host_challenge, sc->card_challenge, cksum, sizeof(cksum));
rv = sm_gp_get_cryptogram(gp_session->session_enc, gp_session->host_challenge, gp_session->card_challenge, cksum, sizeof(cksum));
LOG_TEST_RET(ctx, rv, "SM GP init session: cannot get cryptogram");
sc_log(ctx, "SM GP init session: cryptogram: %s", sc_dump_hex(cksum, 8));
@ -318,11 +323,11 @@ sm_gp_init_session(struct sc_context *ctx, struct sm_secure_channel *sc,
void
sm_gp_close_session(struct sc_context *ctx, struct sm_secure_channel *sc)
sm_gp_close_session(struct sc_context *ctx, struct sm_gp_session *gp_session)
{
free(sc->session.gp.session_enc);
free(sc->session.gp.session_mac);
free(sc->session.gp.session_kek);
free(gp_session->session_enc);
free(gp_session->session_mac);
free(gp_session->session_kek);
}
@ -336,7 +341,7 @@ sm_gp_external_authentication(struct sc_context *ctx, struct sm_info *sm_info,
struct sc_remote_apdu *new_rapdu = NULL;
struct sc_apdu *apdu = NULL;
unsigned char host_cryptogram[8], raw_apdu[SC_MAX_APDU_BUFFER_SIZE];
struct sm_secure_channel *schannel = &sm_info->schannel;
struct sm_gp_session *gp_session = &sm_info->session.gp;
DES_cblock mac;
int rv, idx = 0, offs = 0;
@ -347,7 +352,7 @@ sm_gp_external_authentication(struct sc_context *ctx, struct sm_info *sm_info,
if (init_len != 0x1C)
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "SM GP authentication: invalid auth data length");
rv = sm_gp_parse_init_data(ctx, schannel, init_data, init_len);
rv = sm_gp_parse_init_data(ctx, gp_session, init_data, init_len);
LOG_TEST_RET(ctx, rv, "SM GP authentication: 'INIT DATA' parse error");
if (diversify_keyset) {
@ -355,10 +360,11 @@ sm_gp_external_authentication(struct sc_context *ctx, struct sm_info *sm_info,
LOG_TEST_RET(ctx, rv, "SM GP authentication: keyset diversification error");
}
rv = sm_gp_init_session(ctx, schannel, init_data + 20, 8);
rv = sm_gp_init_session(ctx, gp_session, init_data + 20, 8);
LOG_TEST_RET(ctx, rv, "SM GP authentication: init session error");
rv = sm_gp_get_cryptogram(schannel->session.gp.session_enc, schannel->card_challenge, schannel->host_challenge,
rv = sm_gp_get_cryptogram(gp_session->session_enc,
gp_session->card_challenge, gp_session->host_challenge,
host_cryptogram, sizeof(host_cryptogram));
LOG_TEST_RET(ctx, rv, "SM GP authentication: get host cryptogram error");
@ -372,19 +378,19 @@ sm_gp_external_authentication(struct sc_context *ctx, struct sm_info *sm_info,
apdu->cse = SC_APDU_CASE_3_SHORT;
apdu->cla = raw_apdu[offs++] = 0x84;
apdu->ins = raw_apdu[offs++] = 0x82;
apdu->p1 = raw_apdu[offs++] = sm_info->sm_params.gp.level;
apdu->p1 = raw_apdu[offs++] = gp_session->params.level;
apdu->p2 = raw_apdu[offs++] = 0;
apdu->lc = raw_apdu[offs++] = 0x10;
apdu->datalen = 0x10;
memcpy(raw_apdu + offs, host_cryptogram, 8);
offs += 8;
rv = sm_gp_get_mac(schannel->session.gp.session_mac, &schannel->session.gp.mac_icv, raw_apdu, offs, &mac);
rv = sm_gp_get_mac(gp_session->session_mac, &gp_session->mac_icv, raw_apdu, offs, &mac);
LOG_TEST_RET(ctx, rv, "SM GP authentication: get MAC error");
memcpy(new_rapdu->sbuf, host_cryptogram, 8);
memcpy(new_rapdu->sbuf + 8, mac, 8);
memcpy(schannel->session.gp.mac_icv, mac, 8);
memcpy(gp_session->mac_icv, mac, 8);
LOG_FUNC_RETURN(ctx, 1);
}
@ -431,9 +437,9 @@ sm_gp_securize_apdu(struct sc_context *ctx, struct sm_info *sm_info,
{
unsigned char buff[SC_MAX_APDU_BUFFER_SIZE + 24];
unsigned char *apdu_data = NULL;
unsigned gp_level = sm_info->sm_params.gp.level;
unsigned gp_index = sm_info->sm_params.gp.index;
struct sm_gp_session *gp_session = &sm_info->schannel.session.gp;
struct sm_gp_session *gp_session = &sm_info->session.gp;
unsigned gp_level = sm_info->session.gp.params.level;
unsigned gp_index = sm_info->session.gp.params.index;
DES_cblock mac;
unsigned char *encrypted = NULL;
size_t encrypted_len = 0;
@ -508,7 +514,7 @@ sm_gp_securize_apdu(struct sc_context *ctx, struct sm_info *sm_info,
free(encrypted);
}
memcpy(sm_info->schannel.session.gp.mac_icv, mac, 8);
memcpy(sm_info->session.gp.mac_icv, mac, 8);
LOG_FUNC_RETURN(ctx, rv);
}

View File

@ -62,7 +62,7 @@ int sm_gp_securize_apdu(struct sc_context *ctx, struct sm_info *sm_info,
char *init_data, struct sc_apdu *apdu);
int sm_gp_decode_card_answer(struct sc_context *ctx, struct sc_remote_data *rdata,
unsigned char *out, size_t out_len);
void sm_gp_close_session(struct sc_context *ctx, struct sm_secure_channel *sc);
void sm_gp_close_session(struct sc_context *ctx, struct sm_gp_session *gp_session);
/* CWA-14890 helper functions */

View File

@ -58,6 +58,8 @@ static int
sm_gp_config_get_keyset(struct sc_context *ctx, struct sm_info *sm_info)
{
scconf_block *sm_conf_block = NULL, **blocks;
struct sm_gp_keyset *gp_keyset = &sm_info->session.gp.gp_keyset;
const char *kmc = NULL;
unsigned char hex[48];
size_t hex_len = sizeof(hex);
@ -89,8 +91,8 @@ sm_gp_config_get_keyset(struct sc_context *ctx, struct sm_info *sm_info)
if (hex_len != 16 && hex_len != 48 )
return SC_ERROR_INVALID_DATA;
memcpy(sm_info->schannel.keyset.gp.kmc, hex, hex_len);
sm_info->schannel.keyset.gp.kmc_len = hex_len;
memcpy(gp_keyset->kmc, hex, hex_len);
gp_keyset->kmc_len = hex_len;
return SC_SUCCESS;
}
@ -99,9 +101,10 @@ sm_gp_config_get_keyset(struct sc_context *ctx, struct sm_info *sm_info)
static int
sm_cwa_config_get_keyset(struct sc_context *ctx, struct sm_info *sm_info)
{
struct sm_cwa_session *session_data = &sm_info->schannel.session.cwa;
struct sm_cwa_session *cwa_session = &sm_info->session.cwa;
struct sm_cwa_keyset *cwa_keyset = &sm_info->session.cwa.cwa_keyset;
scconf_block *sm_conf_block = NULL, **blocks;
struct sc_crt *crt_at = &sm_info->sm_params.cwa.crt_at;
struct sc_crt *crt_at = &sm_info->session.cwa.params.crt_at;
const char *value = NULL;
char name[128];
unsigned char hex[48];
@ -134,7 +137,7 @@ sm_cwa_config_get_keyset(struct sc_context *ctx, struct sm_info *sm_info)
sc_log(ctx, "keyset::enc(%i) %s", strlen(value), value);
if (strlen(value) == 16) {
memcpy(sm_info->schannel.keyset.cwa.enc, value, 16);
memcpy(cwa_keyset->enc, value, 16);
}
else {
hex_len = sizeof(hex);
@ -148,9 +151,9 @@ sm_cwa_config_get_keyset(struct sc_context *ctx, struct sm_info *sm_info)
if (hex_len != 16)
return SC_ERROR_INVALID_DATA;
memcpy(sm_info->schannel.keyset.cwa.enc, hex, hex_len);
memcpy(cwa_keyset->enc, hex, hex_len);
}
sc_log(ctx, "%s %s", name, sc_dump_hex(sm_info->schannel.keyset.cwa.enc, 16));
sc_log(ctx, "%s %s", name, sc_dump_hex(cwa_keyset->enc, 16));
/* Keyset MAC */
if (sm_info->current_aid.len && (crt_at->refs[0] & IASECC_OBJECT_REF_LOCAL))
@ -166,7 +169,7 @@ sm_cwa_config_get_keyset(struct sc_context *ctx, struct sm_info *sm_info)
sc_log(ctx, "keyset::mac(%i) %s", strlen(value), value);
if (strlen(value) == 16) {
memcpy(sm_info->schannel.keyset.cwa.mac, value, 16);
memcpy(cwa_keyset->mac, value, 16);
}
else {
hex_len = sizeof(hex);
@ -180,15 +183,15 @@ sm_cwa_config_get_keyset(struct sc_context *ctx, struct sm_info *sm_info)
if (hex_len != 16)
return SC_ERROR_INVALID_DATA;
memcpy(sm_info->schannel.keyset.cwa.mac, hex, hex_len);
memcpy(cwa_keyset->mac, hex, hex_len);
}
sc_log(ctx, "%s %s", name, sc_dump_hex(sm_info->schannel.keyset.cwa.mac, 16));
sc_log(ctx, "%s %s", name, sc_dump_hex(cwa_keyset->mac, 16));
sm_info->schannel.keyset.cwa.sdo_reference = crt_at->refs[0];
cwa_keyset->sdo_reference = crt_at->refs[0];
/* IFD parameters */
memset(session_data, 0, sizeof(struct sm_cwa_session));
//memset(cwa_session, 0, sizeof(struct sm_cwa_session));
value = scconf_get_str(sm_conf_block, "ifd_serial", NULL);
if (!value)
return SC_ERROR_SM_IFD_DATA_MISSING;
@ -199,27 +202,27 @@ sm_cwa_config_get_keyset(struct sc_context *ctx, struct sm_info *sm_info)
return SC_ERROR_UNKNOWN_DATA_RECEIVED;
}
if (hex_len != sizeof(session_data->ifd.sn)) {
if (hex_len != sizeof(cwa_session->ifd.sn)) {
sc_log(ctx, "SM get 'ifd_serial': invalid IFD serial length: %i", hex_len);
return SC_ERROR_UNKNOWN_DATA_RECEIVED;
}
memcpy(session_data->ifd.sn, hex, hex_len);
memcpy(cwa_session->ifd.sn, hex, hex_len);
rv = RAND_bytes(session_data->ifd.rnd, 8);
rv = RAND_bytes(cwa_session->ifd.rnd, 8);
if (!rv) {
sc_log(ctx, "Generate random error: %i", rv);
return SC_ERROR_SM_RAND_FAILED;
}
rv = RAND_bytes(session_data->ifd.k, 32);
rv = RAND_bytes(cwa_session->ifd.k, 32);
if (!rv) {
sc_log(ctx, "Generate random error: %i", rv);
return SC_ERROR_SM_RAND_FAILED;
}
sc_log(ctx, "IFD.Serial: %s", sc_dump_hex(session_data->ifd.sn, sizeof(session_data->ifd.sn)));
sc_log(ctx, "IFD.Rnd: %s", sc_dump_hex(session_data->ifd.rnd, sizeof(session_data->ifd.rnd)));
sc_log(ctx, "IFD.K: %s", sc_dump_hex(session_data->ifd.k, sizeof(session_data->ifd.k)));
sc_log(ctx, "IFD.Serial: %s", sc_dump_hex(cwa_session->ifd.sn, sizeof(cwa_session->ifd.sn)));
sc_log(ctx, "IFD.Rnd: %s", sc_dump_hex(cwa_session->ifd.rnd, sizeof(cwa_session->ifd.rnd)));
sc_log(ctx, "IFD.K: %s", sc_dump_hex(cwa_session->ifd.k, sizeof(cwa_session->ifd.k)));
return SC_SUCCESS;
}