⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 card-starcos.c

📁 读写Smart卡加解密接口的程序
💻 C
📖 第 1 页 / 共 3 页
字号:
	sc_starcos_ex_data_t ex_dat;	struct sc_cardctl_starcos_key_attr_st *key_attr = NULL;	assert(card != NULL && env != NULL);	ex_dat.key = SC_STARCOS_PRV_DATA;	if (get_ex_data(card, &ex_dat) != SC_SUCCESS)		return SC_ERROR_INTERNAL;	mse = (starcos_sec_data_t *)ex_dat.data;	p     = mse->buf;	keyID = env->key_ref[0];	algID = env->algorithm_ref & 0xFF;	ex_dat.key = SC_STARCOS_EX_KEY(SC_STARCOS_KEY_ATTR, keyID);	if (!get_ex_data(card, &ex_dat))		key_attr = (struct sc_cardctl_starcos_key_attr_st *) ex_dat.data;	if (env->operation == SC_SEC_OPERATION_SIGN && key_attr &&	    key_attr->flag == SC_SEC_OPERATION_AUTHENTICATE)	{		/* XXX We want to create a signature with a authentication 		 * key => change operation to SC_SEC_OPERATION_AUTHENTICATE.		 */		operation = SC_SEC_OPERATION_AUTHENTICATE;		algID     = 0x01;		/* the INTERNAL AUTHENTICATE command does not add		 * the PKCS#1 digest info structure		 */		mse->fix_digestInfo = env->algorithm_flags;	}	else		operation = env->operation;	switch (operation)	{	case SC_SEC_OPERATION_DECIPHER:		mse->sec_ops = SC_SEC_OPERATION_DECIPHER;		mse->p1 = 0x81;		mse->p2 = 0xB8;		break;	case SC_SEC_OPERATION_SIGN:		mse->sec_ops = SC_SEC_OPERATION_SIGN;		mse->p1 = 0x41;		mse->p2 = 0xB6;		break;	case SC_SEC_OPERATION_AUTHENTICATE:		mse->sec_ops = SC_SEC_OPERATION_AUTHENTICATE;		mse->p1 = 0x41;		mse->p2 = 0xa4;		break;	default:		return SC_ERROR_INVALID_ARGUMENTS;	}	if (env->flags & SC_SEC_ENV_ALG_REF_PRESENT)	{		*p++ = 0x80;		*p++ = 0x01;		*p++ = algID;	}	else if (env->flags & SC_SEC_ENV_ALG_PRESENT &&		 env->algorithm == SC_ALGORITHM_RSA)  	{		/* set the method to use based on the algorithm_flags */		if (operation == SC_SEC_OPERATION_DECIPHER)		{			if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1)			{				*p++ = 0x80;				*p++ = 0x01;				*p++ = 0x02;			}			else 				return SC_ERROR_INVALID_ARGUMENTS;		}		else if (operation == SC_SEC_OPERATION_SIGN)		{			*p++ = 0x80;			*p++ = 0x01;			if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1)			{				if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1)					*p++ = 0x12;				else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_RIPEMD160)					*p++ = 0x22;				else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_MD5)					*p++ = 0x32;				else					return SC_ERROR_INVALID_ARGUMENTS;			}			else if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_ISO9796)			{				if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1)					*p++ = 0x11;				else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_RIPEMD160)					*p++ = 0x21;				else					return SC_ERROR_INVALID_ARGUMENTS;			}			else				return SC_ERROR_INVALID_ARGUMENTS;		}		else if (operation == SC_SEC_OPERATION_AUTHENTICATE)		{			if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1)			{				*p++ = 0x80;				*p++ = 0x01;				*p++ = 0x01;			}			else 				return SC_ERROR_INVALID_ARGUMENTS;		}		else			return SC_ERROR_INVALID_ARGUMENTS;	}	if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT)	{		if (env->flags & SC_SEC_ENV_KEY_REF_ASYMMETRIC)			*p++ = 0x83;		else			*p++ = 0x84;		*p++ = env->key_ref_len;		memcpy(p, env->key_ref, env->key_ref_len);		p += env->key_ref_len;	}	mse->buf_len = p - mse->buf;	return SC_SUCCESS;}static int starcos_compute_signature(struct sc_card *card,				     const u8 * data, size_t datalen,				     u8 * out, size_t outlen){	/* NOTE: data should point to a hash value */	int r;	struct sc_apdu apdu;	u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];	u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];	starcos_sec_data_t *mse;	sc_starcos_ex_data_t ex_dat;	assert(card != NULL && data != NULL && out != NULL);	if (datalen > SC_MAX_APDU_BUFFER_SIZE)		SC_FUNC_RETURN(card->ctx, 4, SC_ERROR_INVALID_ARGUMENTS);	ex_dat.key = SC_STARCOS_PRV_DATA;	if (get_ex_data(card, &ex_dat) != SC_SUCCESS)		return SC_ERROR_INTERNAL;	mse = (starcos_sec_data_t *)ex_dat.data;	/* first step: MSE */	if (mse->sec_ops == 0)		SC_FUNC_RETURN(card->ctx, 4, SC_ERROR_INVALID_ARGUMENTS);	sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, mse->p1,		       mse->p2);	apdu.data    = mse->buf;	apdu.datalen = mse->buf_len;	apdu.lc      = mse->buf_len;	apdu.le      = 0;	r = sc_transmit_apdu(card, &apdu);	SC_TEST_RET(card->ctx, r, "APDU transmit failed");	if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)		SC_FUNC_RETURN(card->ctx, 4, sc_check_sw(card, apdu.sw1, apdu.sw2));	/* the second step depends on the signature method used:	 * INTERNAL AUTHENTICATE or COMPUTE SIGNATURE */	if (mse->sec_ops == SC_SEC_OPERATION_SIGN)	{		/* second step: set the hash value */		sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x2A,			       0x90, 0x81);		apdu.resp = rbuf;		apdu.resplen = sizeof(rbuf);		apdu.le = 0;		memcpy(sbuf, data, datalen);		apdu.data = sbuf;		apdu.lc = datalen;		apdu.datalen = datalen;		r = sc_transmit_apdu(card, &apdu);		SC_TEST_RET(card->ctx, r, "APDU transmit failed");		if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)			SC_FUNC_RETURN(card->ctx, 4, 				       sc_check_sw(card, apdu.sw1, apdu.sw2));		/* third and final step: calculate the signature */		sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0x2A,			       0x9E, 0x9A);		apdu.resp = rbuf;		apdu.resplen = sizeof(rbuf);		apdu.le = 256;		apdu.lc = 0;		apdu.datalen = 0;		apdu.sensitive = 1;		r = sc_transmit_apdu(card, &apdu);		SC_TEST_RET(card->ctx, r, "APDU transmit failed");		if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)		{			int len = apdu.resplen > outlen ? outlen : apdu.resplen;			memcpy(out, apdu.resp, len);			SC_FUNC_RETURN(card->ctx, 4, len);		}	}	else if (mse->sec_ops == SC_SEC_OPERATION_AUTHENTICATE)	{		size_t tmp_len;		/* second and final step: compute the signature */		sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x88,			       0x10, 0x00);		/* create DigestInfo structure ? */		if (mse->fix_digestInfo)		{			unsigned int flags = mse->fix_digestInfo & SC_ALGORITHM_RSA_HASHES;			tmp_len = sizeof(sbuf);			r = sc_pkcs1_encode(card->ctx, flags, data, datalen,					sbuf, &tmp_len, sizeof(sbuf));			if (r < 0)				return r;		}		else		{			memcpy(sbuf, data, datalen);			tmp_len = datalen;		}		apdu.lc = tmp_len;		apdu.data = sbuf;		apdu.datalen = tmp_len;		apdu.resp = rbuf;		apdu.resplen = sizeof(rbuf);		apdu.le = 256;		r = sc_transmit_apdu(card, &apdu);		SC_TEST_RET(card->ctx, r, "APDU transmit failed");		{			int len = apdu.resplen > outlen ? outlen : apdu.resplen;			memcpy(out, apdu.resp, len);			SC_FUNC_RETURN(card->ctx, 4, len);		}	}	else		SC_FUNC_RETURN(card->ctx, 4, SC_ERROR_INVALID_ARGUMENTS);	/* clear the old mse state */	memset(mse, 0, sizeof(starcos_sec_data_t));	SC_FUNC_RETURN(card->ctx, 4, sc_check_sw(card, apdu.sw1, apdu.sw2));}static int starcos_decipher(struct sc_card *card,			    const u8 * crgram, size_t crgram_len,			    u8 * out, size_t outlen){	int r;	struct sc_apdu apdu;	u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];	u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];	starcos_sec_data_t *mse;	sc_starcos_ex_data_t ex_dat;	assert(card != NULL && crgram != NULL && out != NULL);	SC_FUNC_CALLED(card->ctx, 2);	if (crgram_len > 255)		SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_INVALID_ARGUMENTS);	/* MSE */	ex_dat.key = SC_STARCOS_PRV_DATA;	if (get_ex_data(card, &ex_dat) != SC_SUCCESS)		return SC_ERROR_INTERNAL;	mse = (starcos_sec_data_t *)ex_dat.data;	if (mse->sec_ops == 0)		SC_FUNC_RETURN(card->ctx, 4, SC_ERROR_INVALID_ARGUMENTS);	sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, mse->p1,		       mse->p2);	apdu.data    = mse->buf;	apdu.datalen = mse->buf_len;	apdu.lc      = mse->buf_len;	apdu.le      = 0;	r = sc_transmit_apdu(card, &apdu);	SC_TEST_RET(card->ctx, r, "APDU transmit failed");	if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)		SC_FUNC_RETURN(card->ctx, 4, sc_check_sw(card, apdu.sw1, apdu.sw2));	/* INS: 0x2A  PERFORM SECURITY OPERATION	 * P1:  0x80  Resp: Plain value	 * P2:  0x86  Cmd: Padding indicator byte followed by cryptogram */	sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x80, 0x86);	apdu.resp = rbuf;	apdu.resplen = sizeof(rbuf); /* FIXME */	apdu.sensitive = 1;		sbuf[0] = 0; /* padding indicator byte, 0x00 = No further indication */	memcpy(sbuf + 1, crgram, crgram_len);	apdu.data = sbuf;	apdu.lc = crgram_len + 1;	apdu.datalen = crgram_len + 1;	apdu.le = 256;	r = sc_transmit_apdu(card, &apdu);	SC_TEST_RET(card->ctx, r, "APDU transmit failed");	if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {		int len = apdu.resplen > outlen ? outlen : apdu.resplen;		memcpy(out, apdu.resp, len);		SC_FUNC_RETURN(card->ctx, 2, len);	}	/* clear the old mse state */	memset(mse, 0, sizeof(starcos_sec_data_t));	SC_FUNC_RETURN(card->ctx, 2, sc_check_sw(card, apdu.sw1, apdu.sw2));}static int starcos_check_sw(struct sc_card *card, int sw1, int sw2){	const int err_count = sizeof(starcos_errors)/sizeof(starcos_errors[0]);	int i;	if (card->ctx->debug >= 3)		sc_debug(card->ctx, "sw1 = 0x%02x, sw2 = 0x%02x\n", sw1, sw2);  	if (sw1 == 0x90)		return SC_NO_ERROR;	if (sw1 == 0x63 && (sw2 & ~0x0f) == 0xc0 )	{		sc_error(card->ctx, "Verification failed (remaining tries: %d)\n",		(sw2 & 0x0f));		return SC_ERROR_PIN_CODE_INCORRECT;	}  	/* check starcos error messages */	for (i = 0; i < err_count; i++)		if (starcos_errors[i].SWs == ((sw1 << 8) | sw2))		{			sc_error(card->ctx, "%s\n", starcos_errors[i].errorstr);			return starcos_errors[i].errorno;		}  	/* iso error */	return iso_ops->check_sw(card, sw1, sw2);}static int starcos_card_ctl(struct sc_card *card, unsigned long cmd, void *ptr){	switch (cmd)	{	case SC_CARDCTL_STARCOS_SET_EX_DATA:		return set_ex_data(card, (sc_starcos_ex_data_t *)ptr);	case SC_CARDCTL_STARCOS_GET_EX_DATA:		return get_ex_data(card, (sc_starcos_ex_data_t *)ptr);	case SC_CARDCTL_STARCOS_FREE_EX_DATA:		free_ex_data(card, ((sc_starcos_ex_data_t *)ptr)->key);		return SC_SUCCESS;	case SC_CARDCTL_STARCOS_FREE_ALL_EX_DATA:		free_all_ex_data(card);		return SC_SUCCESS;	default:		return SC_ERROR_NOT_SUPPORTED;	}	return SC_ERROR_NOT_SUPPORTED;}static int starcos_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data,			   int *tries_left){	if (data->cmd == SC_PIN_CMD_VERIFY) {		u8  pinId = (u8) data->pin_reference;		sc_starcos_ex_data_t ex_dat;		ex_dat.key = SC_STARCOS_EX_KEY(SC_STARCOS_PIN_ATTR, pinId);		if (get_ex_data(card, &ex_dat) == SC_SUCCESS) {			int r;			struct sc_cardctl_starcos_pin_attr_st *pin_attr;			pin_attr = (struct sc_cardctl_starcos_pin_attr_st *)ex_dat.data;			if (!pin_attr->verify_once)				return SC_SUCCESS;			r = iso_ops->pin_cmd(card, data, tries_left);			if (r == SC_SUCCESS)				pin_attr->verify_once = 0;			return r;		}	}			return iso_ops->pin_cmd(card, data, tries_left);}static struct sc_card_driver * sc_get_driver(void){	struct sc_card_driver *iso_drv = sc_get_iso7816_driver();	if (iso_ops == NULL)		iso_ops = iso_drv->ops;  	starcos_ops = *iso_drv->ops;	starcos_ops.match_card = starcos_match_card;	starcos_ops.init   = starcos_init;	starcos_ops.finish = starcos_finish;	starcos_ops.select_file = starcos_select_file;	starcos_ops.check_sw    = starcos_check_sw;	starcos_ops.create_file = starcos_create_file;	starcos_ops.delete_file = starcos_delete_file;	starcos_ops.set_security_env  = starcos_set_security_env;	starcos_ops.compute_signature = starcos_compute_signature;	starcos_ops.decipher    = starcos_decipher;	starcos_ops.card_ctl    = starcos_card_ctl;	starcos_ops.pin_cmd     = starcos_pin_cmd;  	return &starcos_drv;}struct sc_card_driver * sc_get_starcos_driver(void){	return sc_get_driver();}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -