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

📄 card-starcos.c

📁 读写Smart卡加解密接口的程序
💻 C
📖 第 1 页 / 共 3 页
字号:
	apdu.resp = (u8*)resp;	apdu.resplen = SC_MAX_APDU_BUFFER_SIZE;	apdu.le = 256;	apdu.lc = 2;	apdu.data = (u8*)data;	apdu.datalen = 2;	r = sc_transmit_apdu(card, &apdu);	SC_TEST_RET(card->ctx, r, "APDU transmit failed");	if (apdu.p2 == 0x00 && apdu.sw1 == 0x62 && apdu.sw2 == 0x84 )	{		/* no FCI => we have a DF (see comment in process_fci()) */		bIsDF = 1;		apdu.p2 = 0x0C;		apdu.cse = SC_APDU_CASE_3_SHORT;		apdu.resplen = 0;		apdu.le = 0;		r = sc_transmit_apdu(card, &apdu);		SC_TEST_RET(card->ctx, r, "APDU re-transmit failed");    	}	else if (apdu.sw1 == 0x61 || (apdu.sw1 == 0x90 && apdu.sw2 == 0x00))	{		/* SELECT returned some data (possible FCI) =>		 * try a READ BINARY to see if a EF is selected */		sc_apdu_t apdu2;		u8 resp2[2];		sc_format_apdu(card, &apdu2, SC_APDU_CASE_2_SHORT, 0xB0, 0, 0);		apdu2.resp = (u8*)resp2;		apdu2.resplen = 2;		apdu2.le = 1;		apdu2.lc = 0;		r = sc_transmit_apdu(card, &apdu2);		SC_TEST_RET(card->ctx, r, "APDU transmit failed");		if (apdu2.sw1 == 0x69 && apdu2.sw2 == 0x86)			/* no current EF is selected => we have a DF */			bIsDF = 1;	}	if (apdu.sw1 != 0x61 && (apdu.sw1 != 0x90 || apdu.sw2 != 0x00))		SC_FUNC_RETURN(card->ctx, 2, sc_check_sw(card, apdu.sw1, apdu.sw2));	/* update cache */	if (bIsDF)	{		card->cache.current_path.type = SC_PATH_TYPE_PATH;		card->cache.current_path.value[0] = 0x3f;		card->cache.current_path.value[1] = 0x00;		if (id_hi == 0x3f && id_lo == 0x00)			card->cache.current_path.len = 2;		else		{			card->cache.current_path.len = 4;			card->cache.current_path.value[2] = id_hi;			card->cache.current_path.value[3] = id_lo;		}	}	if (file_out)	{		sc_file_t *file = sc_file_new();		if (!file)			SC_FUNC_RETURN(card->ctx, 0, SC_ERROR_OUT_OF_MEMORY);		file->id = (id_hi << 8) + id_lo;		copy_path(&file->path, &card->cache.current_path);		if (bIsDF)		{			/* we have a DF */			file->type = SC_FILE_TYPE_DF;			file->ef_structure = SC_FILE_EF_UNKNOWN;			file->size = 0;			file->namelen = 0;			file->magic = SC_FILE_MAGIC;			*file_out = file;		}		else /* bIsDF == 0 */		{			/* ok, assume we have a EF */			if (apdu.resp[0] != 0x6F)			{				/* missing tag */				free(file);				SC_FUNC_RETURN(card->ctx, 2,				       SC_ERROR_UNKNOWN_DATA_RECEIVED);			}			/* check length of the FCI data */			if (apdu.resp[1] <= apdu.resplen-2)				process_fci(card->ctx,file,apdu.resp+2, apdu.resp[1]);			*file_out = file;		}	}	else if (file_out)		*file_out = NULL;	SC_FUNC_RETURN(card->ctx, 2, SC_SUCCESS);}static int starcos_select_file(struct sc_card *card,			       const struct sc_path *in_path,			       struct sc_file **file_out){	u8 pathbuf[SC_MAX_PATH_SIZE], *path = pathbuf;	int    r;	size_t i, pathlen;	if ( !card || !in_path )		SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_INVALID_ARGUMENTS);	if (card->ctx->debug >= 4)	{		char buf[128], *p_buf = buf;		for (i = 0; i < card->cache.current_path.len; i++) 		{			sprintf(p_buf, "%02X", card->cache.current_path.value[i]);			p_buf += 2;		}		p_buf[0] = 0x00;		sc_debug(card->ctx, "current path (%s, %s): %s (len: %u)\n",			(card->cache.current_path.type==SC_PATH_TYPE_DF_NAME?"aid":"path"),			(card->cache_valid?"valid":"invalid"),			buf, card->cache.current_path.len);	}  	memcpy(path, in_path->value, in_path->len);	pathlen = in_path->len;	if (in_path->type == SC_PATH_TYPE_FILE_ID)	{	/* SELECT EF/DF with ID */		/* Select with 2byte File-ID */		if (pathlen != 2)			SC_FUNC_RETURN(card->ctx,2,SC_ERROR_INVALID_ARGUMENTS);		return starcos_select_fid(card, path[0], path[1], file_out);	}	else if (in_path->type == SC_PATH_TYPE_DF_NAME)      	{	/* SELECT DF with AID */		/* Select with 1-16byte Application-ID */		if (card->cache_valid 		    && card->cache.current_path.type == SC_PATH_TYPE_DF_NAME		    && card->cache.current_path.len == pathlen		    && memcmp(card->cache.current_path.value, pathbuf, pathlen) == 0 )		{			if (card->ctx->debug >= 4)				sc_debug(card->ctx, "cache hit\n");			SC_FUNC_RETURN(card->ctx, 2, SC_SUCCESS);		}		else			return starcos_select_aid(card, pathbuf, pathlen, file_out);	}	else if (in_path->type == SC_PATH_TYPE_PATH)	{		u8 n_pathbuf[SC_MAX_PATH_SIZE];		int bMatch = -1;		/* Select with path (sequence of File-IDs) */		/* Starcos (S 2.1 and SPK 2.3) only supports one		 * level of subdirectories, therefore a path is		 * at most 3 FID long (the last one being the FID		 * of a EF) => pathlen must be even and less than 6		 */		if (pathlen%2 != 0 || pathlen > 6 || pathlen <= 0)			SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_INVALID_ARGUMENTS);		/* if pathlen == 6 then the first FID must be MF (== 3F00) */		if (pathlen == 6 && ( path[0] != 0x3f || path[1] != 0x00 ))			SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_INVALID_ARGUMENTS);		/* unify path (the first FID should be MF) */		if (path[0] != 0x3f || path[1] != 0x00)		{			n_pathbuf[0] = 0x3f;			n_pathbuf[1] = 0x00;			for (i=0; i< pathlen; i++)				n_pathbuf[i+2] = pathbuf[i];			path = n_pathbuf;			pathlen += 2; 		}			/* check current working directory */		if (card->cache_valid 		    && card->cache.current_path.type == SC_PATH_TYPE_PATH		    && card->cache.current_path.len >= 2		    && card->cache.current_path.len <= pathlen )		{			bMatch = 0;			for (i=0; i < card->cache.current_path.len; i+=2)				if (card->cache.current_path.value[i] == path[i] 				    && card->cache.current_path.value[i+1] == path[i+1] )					bMatch += 2;		}		if ( card->cache_valid && bMatch >= 0 )		{			if ( pathlen - bMatch == 2 )				/* we are in the rigth directory */				return starcos_select_fid(card, path[bMatch], path[bMatch+1], file_out);			else if ( pathlen - bMatch > 2 )			{				/* two more steps to go */				sc_path_t new_path;					/* first step: change directory */				r = starcos_select_fid(card, path[bMatch], path[bMatch+1], NULL);				SC_TEST_RET(card->ctx, r, "SELECT FILE (DF-ID) failed");						new_path.type = SC_PATH_TYPE_PATH;				new_path.len  = pathlen - bMatch-2;				memcpy(new_path.value, &(path[bMatch+2]), new_path.len);				/* final step: select file */				return starcos_select_file(card, &new_path, file_out);      			}			else /* if (bMatch - pathlen == 0) */			{				/* done: we are already in the				 * requested directory */				if ( card->ctx->debug >= 4 )					sc_debug(card->ctx, "cache hit\n");				/* TODO: Should SELECT DF be called again ? 				 *       (Calling SELECT DF resets the status 				 *       of the current DF).				 */#if 0				/* SELECT the DF again */				return starcos_select_fid(card, path[pathlen-2],						path[pathlen-1], file_out);#else				/* copy file info (if necessary) */				if (file_out)				{					sc_file_t *file = sc_file_new();					if (!file)						SC_FUNC_RETURN(card->ctx, 0,							SC_ERROR_OUT_OF_MEMORY);					file->id = (path[pathlen-2] << 8) +						   path[pathlen-1];					copy_path(&file->path,						&card->cache.current_path);					file->type = SC_FILE_TYPE_DF;					file->ef_structure = SC_FILE_EF_UNKNOWN;					file->size = 0;					file->namelen = 0;					file->magic = SC_FILE_MAGIC;					*file_out = file;				}				/* nothing left to do */				return SC_SUCCESS;#endif 			}		}		else		{			/* no usable cache */			for ( i=0; i<pathlen-2; i+=2 )			{				r = starcos_select_fid(card, path[i], path[i+1], NULL);				SC_TEST_RET(card->ctx, r, "SELECT FILE (DF-ID) failed");			}			return starcos_select_fid(card, path[pathlen-2], path[pathlen-1], file_out);		}	}	else		SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_INVALID_ARGUMENTS);  	SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_INTERNAL);}static int starcos_create_file(struct sc_card *card, struct sc_file *file){	int r, i;	size_t len;	u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];	struct sc_apdu apdu;	len = SC_MAX_APDU_BUFFER_SIZE;	if (file->type == SC_FILE_TYPE_WORKING_EF)	{		/* create a EF */		/* FIXME: use variable AC etc. */		/* set the FID */		sbuf[0] = (file->id & 0xffff) >> 8;		sbuf[1] = (file->id & 0x00ff);		/* set ACs */		for (i=0; i<9; i++)			sbuf[2+i] = 0x00;		/* set SM byte (not supported) */		sbuf[11] = 0x00;		/* set SID */		sbuf[12] = 0x00;		/* set EF-INFO and EF descriptor */		switch (file->ef_structure)		{		case SC_FILE_EF_LINEAR_FIXED:			sbuf[13] = 0x82;			sbuf[14] = file->record_count & 0xff;			sbuf[15] = file->record_length & 0xff;			break;		case SC_FILE_EF_CYCLIC:			sbuf[13] = 0x84;			sbuf[14] = file->record_count & 0xff;			sbuf[15] = file->record_length & 0xff;			break;		case SC_FILE_EF_TRANSPARENT:			sbuf[13] = 0x81;			sbuf[14] = (file->size & 0xffff) >> 8;			sbuf[15] = (file->size & 0x00ff);			break;#if 0		case SC_FILE_EF_OBJECT:		case SC_FILE_EF_COMPUTE:#endif		default:			return SC_ERROR_INVALID_ARGUMENTS;		}		sc_format_apdu(card,&apdu,SC_APDU_CASE_3_SHORT,0xE0,0x03,0x00);		len = 16;	}	else if (file->type == SC_FILE_TYPE_DF)	{		size_t namelen = file->namelen;		/* create a DF */		/* first step: REGISTER DF to allocate the required memory */		sc_format_apdu(card,&apdu,SC_APDU_CASE_3_SHORT,0x52,			       (file->size & 0xffff) >> 8, file->size & 0xff);		sbuf[0] = (file->id & 0xffff) >> 8;		sbuf[1] = file->id & 0xff;		if (namelen)		{			sbuf[2] = namelen & 0xff;			memcpy(sbuf+3, file->name, namelen);		}		else		{	/* Starcos seems to need a AID name */			sbuf[2] = 2;			sbuf[3] = sbuf[0];			sbuf[4] = sbuf[1];			namelen = 2;		}		apdu.cla    |= 0x80;		apdu.lc      = 3 + namelen;		apdu.datalen = 3 + namelen;		apdu.data    = sbuf;		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));		/* second step: create the DF */		/* FIXME: use variable parameters */		/* set the ISF space */		sbuf[19] = 0x00;		sbuf[20] = 0x80;		/* set AC CREATE EF */		sbuf[21] = 0x00;		/* set AC CREATE KEY */		sbuf[22] = 0x00;		/* set SM byte CR */		sbuf[23] = 0x00;		/* set SM byte ISF */		sbuf[24] = 0x00;		sc_format_apdu(card,&apdu,SC_APDU_CASE_3_SHORT,0xE0,0x01,0x00);		len = 25;	}		apdu.cla |= 0x80;  /* this is an proprietary extension */	apdu.lc = len;	apdu.datalen = len;	apdu.data = sbuf;	r = sc_transmit_apdu(card, &apdu);	SC_TEST_RET(card->ctx, r, "APDU transmit failed");	return sc_check_sw(card, apdu.sw1, apdu.sw2);}/* DELETE works only for the MF (<=> clearing the whole filesystem) * (and only with test cards) */static int starcos_delete_file(struct sc_card *card, const struct sc_path *path){	int r;	u8 sbuf[2];	struct sc_apdu apdu;	SC_FUNC_CALLED(card->ctx, 1);	if (path->type != SC_PATH_TYPE_FILE_ID && path->len != 2)	{		sc_error(card->ctx, "File type has to be SC_PATH_TYPE_FILE_ID\n");		SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);	}	sbuf[0] = path->value[0];	sbuf[1] = path->value[1];	if (sbuf[0] != 0x3f || sbuf[1] != 0x00)	{		sc_error(card->ctx, "Only the MF can be deleted\n");		SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);	}	sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE4, 0x00, 0x00);	apdu.cla |= 0x80;	apdu.lc   = 2;	apdu.datalen = 2;	apdu.data = sbuf;		r = sc_transmit_apdu(card, &apdu);	SC_TEST_RET(card->ctx, r, "APDU transmit failed");	return sc_check_sw(card, apdu.sw1, apdu.sw2);}static int starcos_set_security_env(struct sc_card *card,				    const struct sc_security_env *env,				    int se_num){	/* NOTE: starcos_set_security_env() does not call MSE!	 *       MSE is called immediately before the corresponding 	 *       crypto operation by the corresponding function.	 *       starcos_set_security_env() evaluates the sc_security_env	 *       argument and inserts the information in the	 *       starcos_mse_state structure.	 */	starcos_sec_data_t  *mse;	u8                  *p, keyID, algID;	int                  operation;

⌨️ 快捷键说明

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