📄 card-starcos.c
字号:
/* * 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 + -