示例#1
0
int
sm_cwa_decode_authentication_data(struct sc_context *ctx, struct sm_cwa_keyset *keyset,
		struct sm_cwa_session *session_data, unsigned char *auth_data)
{
	DES_cblock icv = {0, 0, 0, 0, 0, 0, 0, 0};
	DES_cblock cblock;
	unsigned char *decrypted = NULL;
	size_t decrypted_len;
	int rv;

	LOG_FUNC_CALLED(ctx);

	memset(icv, 0, sizeof(icv));
	rv = sm_cwa_get_mac(ctx, keyset->mac, &icv, session_data->mdata, 0x40, &cblock, 1);
	LOG_TEST_RET(ctx, rv, "Decode authentication data:  sm_ecc_get_mac failed");
	sc_debug(ctx, SC_LOG_DEBUG_SM, "MAC:%s", sc_dump_hex(cblock, sizeof(cblock)));

	if(memcmp(session_data->mdata + 0x40, cblock, 8))
		LOG_FUNC_RETURN(ctx, SC_ERROR_SM_AUTHENTICATION_FAILED);

	rv = sm_decrypt_des_cbc3(ctx, keyset->enc, session_data->mdata, session_data->mdata_len, &decrypted, &decrypted_len);
	LOG_TEST_RET(ctx, rv, "sm_ecc_decode_auth_data() DES CBC3 decrypt error");

	sc_debug(ctx, SC_LOG_DEBUG_SM,
	       "sm_ecc_decode_auth_data() decrypted(%"SC_FORMAT_LEN_SIZE_T"u) %s",
	       decrypted_len, sc_dump_hex(decrypted, decrypted_len));

	if (memcmp(decrypted, session_data->icc.rnd, 8)) {
		free(decrypted);
		LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
	}

	if (memcmp(decrypted + 8, session_data->icc.sn, 8)) {
		free(decrypted);
		LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
	}

	if (memcmp(decrypted + 16, session_data->ifd.rnd, 8)) {
		free(decrypted);
		LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
	}

	if (memcmp(decrypted + 24, session_data->ifd.sn, 8)) {
		free(decrypted);
		LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
	}

	memcpy(session_data->icc.k, decrypted + 32, 32);

	free(decrypted);
	LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}
示例#2
0
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->session.cwa;
	struct sc_apdu *apdu = &rapdu->apdu;
	unsigned char sbuf[0x400];
	DES_cblock cblock, icv;
	unsigned char *encrypted = NULL, edfb_data[0x200], mac_data[0x200];
	size_t encrypted_len, edfb_len = 0, mac_len = 0, offs;
	int rv;

	LOG_FUNC_CALLED(ctx);
	sc_log(ctx, "securize APDU (cla:%X,ins:%X,p1:%X,p2:%X,data(%i):%p)",
			apdu->cla, apdu->ins, apdu->p1, apdu->p2, apdu->datalen, apdu->data);

	sm_incr_ssc(session_data->ssc, sizeof(session_data->ssc));

	rv = sm_encrypt_des_cbc3(ctx, session_data->session_enc, apdu->data, apdu->datalen, &encrypted, &encrypted_len, 0);
	LOG_TEST_RET(ctx, rv, "securize APDU: DES CBC3 encryption failed");
	sc_log(ctx, "encrypted data (len:%i, %s)", encrypted_len, sc_dump_hex(encrypted, encrypted_len));

	offs = 0;
	if (apdu->ins & 0x01)   {
		edfb_data[offs++] = IASECC_SM_DO_TAG_TCG_ODD_INS;
		if (encrypted_len + 1 > 0x7F)
			edfb_data[offs++] = 0x81;
		edfb_data[offs++] = encrypted_len;
	}
	else   {
		edfb_data[offs++] = IASECC_SM_DO_TAG_TCG_EVEN_INS;
		if (encrypted_len + 1 > 0x7F)
			edfb_data[offs++] = 0x81;
		edfb_data[offs++] = encrypted_len + 1;
		edfb_data[offs++] = 0x01;
	}
	memcpy(edfb_data + offs, encrypted, encrypted_len);
	offs += encrypted_len;
	edfb_len = offs;
	sc_log(ctx, "securize APDU: EDFB(len:%i,%sà", edfb_len, sc_dump_hex(edfb_data, edfb_len));

	free(encrypted);
	encrypted = NULL;

	offs = 0;
	memcpy(mac_data + offs, session_data->ssc, 8);
	offs += 8;
	mac_data[offs++] = apdu->cla | 0x0C;
	mac_data[offs++] = apdu->ins;
	mac_data[offs++] = apdu->p1;
	mac_data[offs++] = apdu->p2;
	mac_data[offs++] = 0x80;
	mac_data[offs++] = 0x00;
	mac_data[offs++] = 0x00;
	mac_data[offs++] = 0x00;

	memcpy(mac_data + offs, edfb_data, edfb_len);
	offs += edfb_len;

	/* if (apdu->le)   { */
		mac_data[offs++] = IASECC_SM_DO_TAG_TLE;
		mac_data[offs++] = 1;
		mac_data[offs++] = apdu->le;
	/* } */

	mac_len = offs;
	sc_log(ctx, "securize APDU: MAC data(len:%i,%s)", mac_len, sc_dump_hex(mac_data, mac_len));

	memset(icv, 0, sizeof(icv));
	rv = sm_cwa_get_mac(ctx, session_data->session_mac, &icv, mac_data, mac_len, &cblock, 0);
	LOG_TEST_RET(ctx, rv, "securize APDU: MAC calculation error");
	sc_log(ctx, "securize APDU: MAC:%s", sc_dump_hex(cblock, sizeof(cblock)));

	offs = 0;
	if (edfb_len)   {
		memcpy(sbuf + offs, edfb_data, edfb_len);
		offs += edfb_len;
	}

	/* if (apdu->le)   { */
		sbuf[offs++] = IASECC_SM_DO_TAG_TLE;
		sbuf[offs++] = 1;
		sbuf[offs++] = apdu->le;
	/* } */

	sbuf[offs++] = IASECC_SM_DO_TAG_TCC;
	sbuf[offs++] = 8;
	memcpy(sbuf + offs, cblock, 8);
	offs += 8;
	sc_log(ctx, "securize APDU: SM data(len:%i,%s)", offs, sc_dump_hex(sbuf, offs));

	if (offs > sizeof(rapdu->sbuf))
		LOG_TEST_RET(ctx, SC_ERROR_BUFFER_TOO_SMALL, "securize APDU: buffer too small for encrypted data");

	apdu->cse = SC_APDU_CASE_4_SHORT;
	apdu->cla |= 0x0C;
	apdu->lc = offs;
	apdu->datalen = offs;
	memcpy((unsigned char *)apdu->data, sbuf, offs);

	sm_incr_ssc(session_data->ssc, sizeof(session_data->ssc));

	LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}
示例#3
0
int
sm_cwa_initialize(struct sc_context *ctx, struct sm_info *sm_info, struct sc_remote_data *rdata)
{
	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(cwa_session->icc.sn);
	struct sc_remote_apdu *new_rapdu = NULL;
	struct sc_apdu *apdu = NULL;
	unsigned char buf[0x100], *encrypted;
	size_t encrypted_len;
	DES_cblock icv = {0, 0, 0, 0, 0, 0, 0, 0}, cblock;
	int rv, offs;

	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(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", cwa_session->params.crt_at.refs[0]);

	if (!rdata || !rdata->alloc)
		LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);

	rv = rdata->alloc(rdata, &new_rapdu);
	LOG_TEST_RET(ctx, rv, "SM GP decode card answer: cannot allocate remote APDU");
	apdu = &new_rapdu->apdu;

	memcpy(&cwa_session->icc.rnd[0], cwa_session->card_challenge, 8);

	if (sn.len > icc_sn_len)
		memcpy(&cwa_session->icc.sn[0], &sn.value[sn.len - icc_sn_len], icc_sn_len);
	else
		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, cwa_session, buf, sizeof(buf));
		if (offs != 0x10)
			LOG_FUNC_RETURN(ctx, offs);
	}
	else   {
		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, 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));

	memcpy(buf, encrypted, encrypted_len);
	offs = encrypted_len;

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

	apdu->cse = SC_APDU_CASE_4_SHORT;
	apdu->cla = 0x00;
	apdu->ins = 0x82;
	apdu->p1 =  0x00;
	apdu->p2 =  0x00;
	apdu->lc =  encrypted_len + sizeof(cblock);
	apdu->le = encrypted_len + sizeof(cblock);
	apdu->datalen = encrypted_len + sizeof(cblock);
	memcpy(new_rapdu->sbuf, encrypted, encrypted_len);
	memcpy(new_rapdu->sbuf + encrypted_len, cblock, sizeof(cblock));

	free(encrypted);
	LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}