static int ctapi_connect(sc_reader_t *reader) { struct ctapi_private_data *priv = GET_PRIV_DATA(reader); char rv; u8 cmd[9], rbuf[256], sad, dad; unsigned short lr; int r; cmd[0] = CTBCS_CLA; cmd[1] = CTBCS_INS_REQUEST; cmd[2] = CTBCS_P1_INTERFACE1; cmd[3] = CTBCS_P2_REQUEST_GET_ATR; cmd[4] = 0x00; dad = 1; sad = 2; lr = 256; rv = priv->funcs.CT_data(priv->ctn, &dad, &sad, 5, cmd, &lr, rbuf); if (rv || rbuf[lr-2] != 0x90) { sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "Error activating card: %d\n", rv); return SC_ERROR_TRANSMIT_FAILED; } if (lr < 2) SC_FUNC_RETURN(reader->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INTERNAL); lr -= 2; if (lr > SC_MAX_ATR_SIZE) return SC_ERROR_INTERNAL; reader->atr.len = lr; memcpy(reader->atr.value, rbuf, lr); r = _sc_parse_atr(reader); return 0; }
int sc_connect_card(sc_reader_t *reader, sc_card_t **card_out) { sc_card_t *card; sc_context_t *ctx; struct sc_card_driver *driver; int i, r = 0, idx, connected = 0; if (card_out == NULL || reader == NULL) return SC_ERROR_INVALID_ARGUMENTS; ctx = reader->ctx; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); if (reader->ops->connect == NULL) LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); card = sc_card_new(ctx); if (card == NULL) LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); r = reader->ops->connect(reader); if (r) goto err; connected = 1; card->reader = reader; card->ctx = ctx; if (reader->flags & SC_READER_ENABLE_ESCAPE) sc_detect_escape_cmds(reader); memcpy(&card->atr, &reader->atr, sizeof(card->atr)); memcpy(&card->uid, &reader->uid, sizeof(card->uid)); _sc_parse_atr(reader); /* See if the ATR matches any ATR specified in the config file */ if ((driver = ctx->forced_driver) == NULL) { sc_log(ctx, "matching configured ATRs"); for (i = 0; ctx->card_drivers[i] != NULL; i++) { driver = ctx->card_drivers[i]; if (driver->atr_map == NULL || !strcmp(driver->short_name, "default")) { driver = NULL; continue; } sc_log(ctx, "trying driver '%s'", driver->short_name); idx = _sc_match_atr(card, driver->atr_map, NULL); if (idx >= 0) { struct sc_atr_table *src = &driver->atr_map[idx]; sc_log(ctx, "matched driver '%s'", driver->name); /* It's up to card driver to notice these correctly */ card->name = src->name; card->type = src->type; card->flags = src->flags; break; } driver = NULL; } } if (driver != NULL) { /* Forced driver, or matched via ATR mapping from config file */ card->driver = driver; memcpy(card->ops, card->driver->ops, sizeof(struct sc_card_operations)); if (card->ops->match_card != NULL) if (card->ops->match_card(card) != 1) sc_log(ctx, "driver '%s' match_card() failed: %s (will continue anyway)", card->driver->name, sc_strerror(r)); if (card->ops->init != NULL) { r = card->ops->init(card); if (r) { sc_log(ctx, "driver '%s' init() failed: %s", card->driver->name, sc_strerror(r)); goto err; } } } else { sc_card_t uninitialized = *card; sc_log(ctx, "matching built-in ATRs"); for (i = 0; ctx->card_drivers[i] != NULL; i++) { /* FIXME If we had a clean API description, we'd propably get a * cleaner implementation of the driver's match_card and init, * which should normally *not* modify the card object if * unsuccessful. However, after years of relentless hacking, reality * is different: The card object is changed in virtually every card * driver so in order to prevent unwanted interaction, we reset the * card object here and hope that the card driver at least doesn't * allocate any internal ressources that need to be freed. If we * had more time, we should refactor the existing code to not * modify sc_card_t until complete success (possibly by combining * `match_card()` and `init()`) */ *card = uninitialized; struct sc_card_driver *drv = ctx->card_drivers[i]; const struct sc_card_operations *ops = drv->ops; sc_log(ctx, "trying driver '%s'", drv->short_name); if (ops == NULL || ops->match_card == NULL) { continue; } else if (!(ctx->flags & SC_CTX_FLAG_ENABLE_DEFAULT_DRIVER) && !strcmp("default", drv->short_name)) { sc_log(ctx , "ignore 'default' card driver"); continue; } /* Needed if match_card() needs to talk with the card (e.g. card-muscle) */ *card->ops = *ops; if (ops->match_card(card) != 1) continue; sc_log(ctx, "matched: %s", drv->name); memcpy(card->ops, ops, sizeof(struct sc_card_operations)); card->driver = drv; r = ops->init(card); if (r) { sc_log(ctx, "driver '%s' init() failed: %s", drv->name, sc_strerror(r)); if (r == SC_ERROR_INVALID_CARD) { card->driver = NULL; continue; } goto err; } break; } } if (card->driver == NULL) { sc_log(ctx, "unable to find driver for inserted card"); r = SC_ERROR_INVALID_CARD; goto err; } if (card->name == NULL) card->name = card->driver->name; /* initialize max_send_size/max_recv_size to a meaningful value */ card->max_recv_size = sc_get_max_recv_size(card); card->max_send_size = sc_get_max_send_size(card); sc_log(ctx, "card info name:'%s', type:%i, flags:0x%lX, max_send/recv_size:%"SC_FORMAT_LEN_SIZE_T"u/%"SC_FORMAT_LEN_SIZE_T"u", card->name, card->type, card->flags, card->max_send_size, card->max_recv_size); #ifdef ENABLE_SM /* Check, if secure messaging module present. */ r = sc_card_sm_check(card); if (r) { sc_log(ctx, "cannot load secure messaging module"); goto err; } #endif *card_out = card; LOG_FUNC_RETURN(ctx, SC_SUCCESS); err: if (connected) reader->ops->disconnect(reader); if (card != NULL) sc_card_free(card); LOG_FUNC_RETURN(ctx, r); }
int sc_connect_card(sc_reader_t *reader, sc_card_t **card_out) { sc_card_t *card; sc_context_t *ctx; struct sc_card_driver *driver; int i, r = 0, idx, connected = 0; if (card_out == NULL || reader == NULL) return SC_ERROR_INVALID_ARGUMENTS; ctx = reader->ctx; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); if (reader->ops->connect == NULL) SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_NOT_SUPPORTED); card = sc_card_new(ctx); if (card == NULL) SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_OUT_OF_MEMORY); r = reader->ops->connect(reader); if (r) goto err; connected = 1; card->reader = reader; card->ctx = ctx; memcpy(&card->atr, &reader->atr, sizeof(card->atr)); _sc_parse_atr(reader); /* See if the ATR matches any ATR specified in the config file */ if ((driver = ctx->forced_driver) == NULL) { sc_debug(ctx, SC_LOG_DEBUG_MATCH, "matching configured ATRs"); for (i = 0; ctx->card_drivers[i] != NULL; i++) { driver = ctx->card_drivers[i]; if (driver->atr_map == NULL || !strcmp(driver->short_name, "default")) { driver = NULL; continue; } sc_debug(ctx, SC_LOG_DEBUG_MATCH, "trying driver: %s", driver->short_name); idx = _sc_match_atr(card, driver->atr_map, NULL); if (idx >= 0) { struct sc_atr_table *src = &driver->atr_map[idx]; sc_debug(ctx, SC_LOG_DEBUG_MATCH, "matched: %s", driver->name); /* It's up to card driver to notice these correctly */ card->name = src->name; card->type = src->type; card->flags = src->flags; break; } driver = NULL; } } if (driver != NULL) { /* Forced driver, or matched via ATR mapping from * config file */ card->driver = driver; memcpy(card->ops, card->driver->ops, sizeof(struct sc_card_operations)); if (card->ops->init != NULL) { r = card->ops->init(card); if (r) { sc_debug(ctx, SC_LOG_DEBUG_MATCH, "driver '%s' init() failed: %s", card->driver->name, sc_strerror(r)); goto err; } } } else { sc_debug(ctx, SC_LOG_DEBUG_MATCH, "matching built-in ATRs"); for (i = 0; ctx->card_drivers[i] != NULL; i++) { struct sc_card_driver *drv = ctx->card_drivers[i]; const struct sc_card_operations *ops = drv->ops; sc_debug(ctx, SC_LOG_DEBUG_MATCH, "trying driver: %s", drv->short_name); if (ops == NULL || ops->match_card == NULL) continue; /* Needed if match_card() needs to talk with the card (e.g. card-muscle) */ *card->ops = *ops; if (ops->match_card(card) != 1) continue; sc_debug(ctx, SC_LOG_DEBUG_MATCH, "matched: %s", drv->name); memcpy(card->ops, ops, sizeof(struct sc_card_operations)); card->driver = drv; r = ops->init(card); if (r) { sc_debug(ctx, SC_LOG_DEBUG_MATCH, "driver '%s' init() failed: %s", drv->name, sc_strerror(r)); if (r == SC_ERROR_INVALID_CARD) { card->driver = NULL; continue; } goto err; } break; } } if (card->driver == NULL) { sc_debug(ctx, SC_LOG_DEBUG_MATCH, "unable to find driver for inserted card"); r = SC_ERROR_INVALID_CARD; goto err; } if (card->name == NULL) card->name = card->driver->name; *card_out = card; /* Override card limitations with reader limitations. * Note that zero means no limitations at all. */ if ((card->max_recv_size == 0) || ((reader->driver->max_recv_size != 0) && (reader->driver->max_recv_size < card->max_recv_size))) { card->max_recv_size = reader->driver->max_recv_size; } if ((card->max_send_size == 0) || ((reader->driver->max_send_size != 0) && (reader->driver->max_send_size < card->max_send_size))) { card->max_send_size = reader->driver->max_send_size; } sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "card info name:'%s', type:%i, flags:0x%X, max_send/recv_size:%i/%i", card->name, card->type, card->flags, card->max_send_size, card->max_recv_size); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, 0); err: if (connected) reader->ops->disconnect(reader); if (card != NULL) sc_card_free(card); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, r); }
int sc_connect_card(sc_reader_t *reader, sc_card_t **card_out) { sc_card_t *card; sc_context_t *ctx; struct sc_card_driver *driver; int i, r = 0, idx, connected = 0; if (card_out == NULL || reader == NULL) return SC_ERROR_INVALID_ARGUMENTS; ctx = reader->ctx; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); if (reader->ops->connect == NULL) LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); card = sc_card_new(ctx); if (card == NULL) LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); r = reader->ops->connect(reader); if (r) goto err; connected = 1; card->reader = reader; card->ctx = ctx; memcpy(&card->atr, &reader->atr, sizeof(card->atr)); _sc_parse_atr(reader); /* See if the ATR matches any ATR specified in the config file */ if ((driver = ctx->forced_driver) == NULL) { sc_log(ctx, "matching configured ATRs"); for (i = 0; ctx->card_drivers[i] != NULL; i++) { driver = ctx->card_drivers[i]; if (driver->atr_map == NULL || !strcmp(driver->short_name, "default")) { driver = NULL; continue; } sc_log(ctx, "trying driver '%s'", driver->short_name); idx = _sc_match_atr(card, driver->atr_map, NULL); if (idx >= 0) { struct sc_atr_table *src = &driver->atr_map[idx]; sc_log(ctx, "matched driver '%s'", driver->name); /* It's up to card driver to notice these correctly */ card->name = src->name; card->type = src->type; card->flags = src->flags; break; } driver = NULL; } } if (driver != NULL) { /* Forced driver, or matched via ATR mapping from config file */ card->driver = driver; memcpy(card->ops, card->driver->ops, sizeof(struct sc_card_operations)); if (card->ops->match_card != NULL) if (card->ops->match_card(card) != 1) sc_log(ctx, "driver '%s' match_card() failed: %s (will continue anyway)", card->driver->name, sc_strerror(r)); if (card->ops->init != NULL) { r = card->ops->init(card); if (r) { sc_log(ctx, "driver '%s' init() failed: %s", card->driver->name, sc_strerror(r)); goto err; } } } else { sc_log(ctx, "matching built-in ATRs"); for (i = 0; ctx->card_drivers[i] != NULL; i++) { struct sc_card_driver *drv = ctx->card_drivers[i]; const struct sc_card_operations *ops = drv->ops; sc_log(ctx, "trying driver '%s'", drv->short_name); if (ops == NULL || ops->match_card == NULL) { continue; } else if (!(ctx->flags & SC_CTX_FLAG_ENABLE_DEFAULT_DRIVER) && !strcmp("default", drv->short_name)) { sc_log(ctx , "ignore 'default' card driver"); continue; } /* Needed if match_card() needs to talk with the card (e.g. card-muscle) */ *card->ops = *ops; if (ops->match_card(card) != 1) continue; sc_log(ctx, "matched: %s", drv->name); memcpy(card->ops, ops, sizeof(struct sc_card_operations)); card->driver = drv; r = ops->init(card); if (r) { sc_log(ctx, "driver '%s' init() failed: %s", drv->name, sc_strerror(r)); if (r == SC_ERROR_INVALID_CARD) { card->driver = NULL; continue; } goto err; } break; } } if (card->driver == NULL) { sc_log(ctx, "unable to find driver for inserted card"); r = SC_ERROR_INVALID_CARD; goto err; } if (card->name == NULL) card->name = card->driver->name; /* initialize max_send_size/max_recv_size to a meaningfull value */ card->max_recv_size = sc_get_max_recv_size(card); card->max_send_size = sc_get_max_send_size(card); sc_log(ctx, "card info name:'%s', type:%i, flags:0x%X, max_send/recv_size:%i/%i", card->name, card->type, card->flags, card->max_send_size, card->max_recv_size); #ifdef ENABLE_SM /* Check, if secure messaging module present. */ r = sc_card_sm_check(card); if (r) { sc_log(ctx, "cannot load secure messaging module"); goto err; } #endif *card_out = card; LOG_FUNC_RETURN(ctx, SC_SUCCESS); err: if (connected) reader->ops->disconnect(reader); if (card != NULL) sc_card_free(card); LOG_FUNC_RETURN(ctx, r); }