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

📄 card-starcos.c

📁 读写Smart卡加解密接口的程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * card-starcos.c: Support for STARCOS SPK 2.3 cards * * Copyright (C) 2003  J鰎n Zukowski <zukowski@trustcenter.de> and  *                     Nils Larsch   <larsch@trustcenter.de>, TrustCenter AG * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include "internal.h"#include "asn1.h"#include "cardctl.h"#include <stdlib.h>#include <string.h>/* TODO: - secure messaging  *       - Starcos ACs <-> OpenSC ACs *       - CREATE EF/MF/DF doesn't really work */static const char *starcos_atrs[] = {  "3B:B7:94:00:c0:24:31:fe:65:53:50:4b:32:33:90:00:b4",  "3B:B7:94:00:81:31:fe:65:53:50:4b:32:33:90:00:d1",  NULL};static struct sc_card_operations starcos_ops;static struct sc_card_operations *iso_ops = NULL;static struct sc_card_driver starcos_drv = {	"driver for STARCOS SPK 2.3 cards",	"starcos",	&starcos_ops};const static struct sc_card_error starcos_errors[] = {	{ 0x6600, SC_ERROR_INCORRECT_PARAMETERS, "Error setting the security env"},	{ 0x66F0, SC_ERROR_INCORRECT_PARAMETERS, "No space left for padding"},	{ 0x69F0, SC_ERROR_NOT_ALLOWED,          "Command not allowed"},	{ 0x6A89, SC_ERROR_FILE_ALREADY_EXISTS,  "Files exists"},	{ 0x6A8A, SC_ERROR_FILE_ALREADY_EXISTS,  "Application exists"},	{ 0x6F01, SC_ERROR_CARD_CMD_FAILED, "public key not complete"},	{ 0x6F02, SC_ERROR_CARD_CMD_FAILED, "data overflow"},	{ 0x6F03, SC_ERROR_CARD_CMD_FAILED, "invalid command sequence"},	{ 0x6F05, SC_ERROR_CARD_CMD_FAILED, "security enviroment invalid"},	{ 0x6F07, SC_ERROR_FILE_NOT_FOUND, "key part not found"},	{ 0x6F08, SC_ERROR_CARD_CMD_FAILED, "signature failed"},	{ 0x6F0A, SC_ERROR_INCORRECT_PARAMETERS, "key format does not match key length"},	{ 0x6F0B, SC_ERROR_INCORRECT_PARAMETERS, "length of key component inconsistent with algorithm"},	{ 0x6F81, SC_ERROR_CARD_CMD_FAILED, "system error"}};/* internal structure to save the current security enviroment */typedef struct starcos_sec_data {	int    sec_ops;	/* the currently selected security operation,			 * i.e. SC_SEC_OPERATION_AUTHENTICATE etc. */	u8     buf[SC_MAX_APDU_BUFFER_SIZE]; /* apdu data */	size_t buf_len;	u8     p1, p2;	/* apdu parameters */	int    fix_digestInfo;} starcos_sec_data_t;/* some ex_data functions */static int get_ex_data(sc_card_t *card, sc_starcos_ex_data_t *in_dat){	sc_starcos_ex_data_t *tmp = (sc_starcos_ex_data_t *)card->drv_data;	while (tmp) {		if (tmp->key == in_dat->key) {			in_dat->data = tmp->data;			return SC_SUCCESS;		}		tmp = tmp->next;	}	return SC_ERROR_OBJECT_NOT_FOUND;}static int append_ex_data(sc_card_t *card, sc_starcos_ex_data_t *in_dat){	sc_starcos_ex_data_t *tmp = (sc_starcos_ex_data_t *)card->drv_data,			     *new_dat;	new_dat = (sc_starcos_ex_data_t *) malloc(sizeof(*new_dat));	if (!new_dat)		return SC_ERROR_INTERNAL;	new_dat->next = NULL;	new_dat->key  = in_dat->key;	new_dat->data = in_dat->data;	new_dat->free_func = in_dat->free_func;	if (!card->drv_data) {		card->drv_data = new_dat;		return SC_SUCCESS;	}	while (tmp->next)		tmp = tmp->next;	tmp->next = new_dat;	return SC_SUCCESS;}static int set_ex_data(sc_card_t *card, sc_starcos_ex_data_t *in_dat){	sc_starcos_ex_data_t *tmp = (sc_starcos_ex_data_t  *) card->drv_data;	while (tmp) {		if (tmp->key == in_dat->key) {			if (tmp->free_func)				tmp->free_func(tmp->data);			else				free(tmp->data);			tmp->data = in_dat->data;			tmp->free_func = in_dat->free_func;			return SC_SUCCESS;		}		tmp = tmp->next;	}	return append_ex_data(card, in_dat);}static void free_all_ex_data(sc_card_t *card){	sc_starcos_ex_data_t *tmp = (sc_starcos_ex_data_t *)card->drv_data;	while (tmp) {		sc_starcos_ex_data_t *next = tmp->next;		if (tmp->free_func)			tmp->free_func(tmp->data);		else			free(tmp->data);		free(tmp);		tmp = next;	}	card->drv_data = NULL;}static void free_ex_data(sc_card_t *card, unsigned long key){	sc_starcos_ex_data_t **p  = (sc_starcos_ex_data_t **)&card->drv_data,			     *tmp = (sc_starcos_ex_data_t  *) card->drv_data;	while (tmp) {		if (tmp->key == key) {			*p = tmp->next;			if (tmp->free_func)				tmp->free_func(tmp->data);			else				free(tmp->data);			free(tmp);			return;		}		p   = &tmp->next;		tmp =  tmp->next;	}}/* internal function to copy a sc_path_t object */static int copy_path(sc_path_t *dest, const sc_path_t *src){	if ( !dest || !src )		return SC_ERROR_INVALID_ARGUMENTS;	dest->type  = src->type;	dest->len   = src->len;	dest->index = src->index;	memcpy(dest->value, src->value, src->len);	return SC_NO_ERROR;}/* the starcos part */static int starcos_match_card(struct sc_card *card){	int i, match = -1;  	for (i = 0; starcos_atrs[i] != NULL; i++) 	{		u8 defatr[SC_MAX_ATR_SIZE];		size_t len = sizeof(defatr);		const char *atrp = starcos_atrs[i];      		if (sc_hex_to_bin(atrp, defatr, &len))			continue;		if (len != card->atr_len)			continue;		if (memcmp(card->atr, defatr, len) != 0)			continue;		match = i + 1;		break;    	}	if (match == -1)		return 0;  	return i;}static int starcos_init(struct sc_card *card){	int type, flags;	starcos_sec_data_t  *sec_data;	sc_starcos_ex_data_t tmp_data;	sec_data = (starcos_sec_data_t *) malloc(sizeof(starcos_sec_data_t));	if (!sec_data)		return SC_ERROR_OUT_OF_MEMORY;	memset(sec_data, 0, sizeof(starcos_sec_data_t));	tmp_data.key  = SC_STARCOS_PRV_DATA;	tmp_data.data = sec_data;	tmp_data.free_func = NULL;	card->name = "StarCOS";	card->cla = 0x00;	if (set_ex_data(card, &tmp_data)) {		free(sec_data);		return SC_ERROR_INTERNAL;	}	/* set the supported algorithm */	type = starcos_match_card(card);	if (type == 1 || type == 2)	{		/* Starcos SPK 2.3 card */		flags = SC_ALGORITHM_RSA_PAD_PKCS1 			| SC_ALGORITHM_RSA_PAD_ISO9796			| SC_ALGORITHM_RSA_HASH_NONE			| SC_ALGORITHM_RSA_HASH_SHA1			| SC_ALGORITHM_RSA_HASH_MD5			| SC_ALGORITHM_RSA_HASH_RIPEMD160			| SC_ALGORITHM_RSA_HASH_MD5_SHA1;		_sc_card_add_rsa_alg(card, 512, flags, 0x10001);		_sc_card_add_rsa_alg(card, 768, flags, 0x10001);		_sc_card_add_rsa_alg(card,1024, flags, 0x10001);	}	else		return SC_ERROR_INTERNAL;	/* we need read_binary&friends with max 128 bytes per read */	card->max_le = 0x80;	return 0;}static int starcos_finish(struct sc_card *card){	if (card->drv_data)		free_all_ex_data(card);	return 0;}static void process_fci(struct sc_context *ctx, struct sc_file *file,		       const u8 *buf, size_t buflen){	/* NOTE: According to the Starcos S 2.1 manual it's possible	 *       that a SELECT DF returns as a FCI arbitrary data which	 *       is stored in a object file (in the corresponding DF)	 *       with the tag 0x6f.	 */	size_t taglen, len = buflen;	const u8 *tag = NULL, *p = buf;  	if (ctx->debug >= 3)		sc_debug(ctx, "processing FCI bytes\n");	/* defaults */	file->type = SC_FILE_TYPE_WORKING_EF;	file->ef_structure = SC_FILE_EF_UNKNOWN;	file->shareable = 0;	file->record_length = 0;	file->size = 0;  	tag = sc_asn1_find_tag(ctx, p, len, 0x80, &taglen);	if (tag != NULL && taglen >= 2) 	{		int bytes = (tag[0] << 8) + tag[1];		if (ctx->debug >= 3)			sc_debug(ctx, "  bytes in file: %d\n", bytes);		file->size = bytes;	}  	tag = sc_asn1_find_tag(ctx, p, len, 0x82, &taglen);	if (tag != NULL) 	{		const char *type = "unknown";		const char *structure = "unknown";		if (taglen == 1 && tag[0] == 0x01) 		{			/* transparent EF */			type = "working EF";			structure = "transparent";			file->type = SC_FILE_TYPE_WORKING_EF;			file->ef_structure = SC_FILE_EF_TRANSPARENT;		}		else if (taglen == 1 && tag[0] == 0x11) 		{			/* object EF */			type = "working EF";			structure = "object";			file->type = SC_FILE_TYPE_WORKING_EF;			file->ef_structure = SC_FILE_EF_TRANSPARENT; /* TODO */		}		else if (taglen == 3 && tag[1] == 0x21)		{			type = "working EF";			file->record_length = tag[2];			file->type = SC_FILE_TYPE_WORKING_EF;			/* linear fixed, cyclic or compute */			switch ( tag[0] )			{				case 0x02:					structure = "linear fixed";					file->ef_structure = SC_FILE_EF_LINEAR_FIXED;					break;				case 0x07:					structure = "cyclic";					file->ef_structure = SC_FILE_EF_CYCLIC;					break;				case 0x17:					structure = "compute";					file->ef_structure = SC_FILE_EF_UNKNOWN;					break;				default:					structure = "unknown";					file->ef_structure = SC_FILE_EF_UNKNOWN;					file->record_length = 0;					break;			}		}		if (ctx->debug >= 3) 		{	 		sc_debug(ctx, "  type: %s\n", type);			sc_debug(ctx, "  EF structure: %s\n", structure);		}	}	file->magic = SC_FILE_MAGIC;}static int starcos_select_aid(struct sc_card *card,			      u8 aid[16], size_t len,			      struct sc_file **file_out){	sc_apdu_t apdu;	sc_file_t *file = NULL;	int r;	size_t i = 0;	if (!card )		SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_INVALID_ARGUMENTS);	if (file_out)		*file_out = NULL;  	sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 0x04, 0x0C);	apdu.lc = len;	apdu.data = (u8*)aid;	apdu.datalen = len;	apdu.resplen = 0;	apdu.le = 0;	r = sc_transmit_apdu(card, &apdu);	SC_TEST_RET(card->ctx, r, "APDU transmit failed");	/* check return value */	if (!(apdu.sw1 == 0x90 && apdu.sw2 == 0x00) && apdu.sw1 != 0x61 )    		SC_FUNC_RETURN(card->ctx, 2, sc_check_sw(card, apdu.sw1, apdu.sw2));  	/* update cache */	card->cache.current_path.type = SC_PATH_TYPE_DF_NAME;	card->cache.current_path.len = len;	memcpy(card->cache.current_path.value, aid, len);	if (file_out)	{		file = sc_file_new();		if (file == NULL)			SC_FUNC_RETURN(card->ctx, 0, SC_ERROR_OUT_OF_MEMORY);		file->type = SC_FILE_TYPE_DF;		file->ef_structure = SC_FILE_EF_UNKNOWN;		file->path.len = 0;		file->size = 0;		/* AID */		for (i = 0; i < len; i++)  			file->name[i] = aid[i];		file->namelen = len;		file->id = 0x0000;		file->magic = SC_FILE_MAGIC;		*file_out = file;	}	SC_FUNC_RETURN(card->ctx, 2, SC_SUCCESS);}static int starcos_select_fid(struct sc_card *card,			      u8 id_hi, u8 id_lo,			      struct sc_file **file_out){	sc_apdu_t apdu;	u8 data[] = {id_hi, id_lo};	u8 resp[SC_MAX_APDU_BUFFER_SIZE];	int bIsDF = 0, r;	if (!card )		SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_INVALID_ARGUMENTS);	if (file_out)		*file_out = NULL;	/* request FCI to distinguish between EFs and DFs */	sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0x00, 0x00);

⌨️ 快捷键说明

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