int sc_update_binary(sc_card_t *card, unsigned int idx, const u8 *buf, size_t count, unsigned long flags) { size_t max_lc = sc_get_max_send_size(card); int r; if (card == NULL || card->ops == NULL || buf == NULL) { return SC_ERROR_INVALID_ARGUMENTS; } sc_log(card->ctx, "called; %"SC_FORMAT_LEN_SIZE_T"u bytes at index %d", count, idx); if (count == 0) return 0; #ifdef ENABLE_SM if (card->sm_ctx.ops.update_binary) { r = card->sm_ctx.ops.update_binary(card, idx, buf, count); if (r) LOG_FUNC_RETURN(card->ctx, r); } #endif if (card->ops->update_binary == NULL) LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); if (count > max_lc) { int bytes_written = 0; const u8 *p = buf; r = sc_lock(card); LOG_TEST_RET(card->ctx, r, "sc_lock() failed"); while (count > 0) { size_t n = count > max_lc? max_lc : count; r = sc_update_binary(card, idx, p, n, flags); if (r < 0) { sc_unlock(card); LOG_TEST_RET(card->ctx, r, "sc_update_binary() failed"); } p += r; idx += r; bytes_written += r; count -= r; if (r == 0) { sc_unlock(card); LOG_FUNC_RETURN(card->ctx, bytes_written); } } sc_unlock(card); LOG_FUNC_RETURN(card->ctx, bytes_written); } r = card->ops->update_binary(card, idx, buf, count, flags); LOG_FUNC_RETURN(card->ctx, r); }
static void fixup_transceive_length(const struct sc_card *card, struct sc_apdu *apdu) { assert(card != NULL && apdu != NULL); if (apdu->lc > sc_get_max_send_size(card)) { /* The lower layers will automatically do chaining */ apdu->flags |= SC_APDU_FLAGS_CHAINING; } if (apdu->le > sc_get_max_recv_size(card)) { /* The lower layers will automatically do a GET RESPONSE, if possible. * All other workarounds must be carried out by the upper layers. */ apdu->le = sc_get_max_recv_size(card); } }
int sc_write_binary(sc_card_t *card, unsigned int idx, const u8 *buf, size_t count, unsigned long flags) { size_t max_lc = sc_get_max_send_size(card); int r; assert(card != NULL && card->ops != NULL && buf != NULL); sc_log(card->ctx, "called; %d bytes at index %d", count, idx); if (count == 0) LOG_FUNC_RETURN(card->ctx, 0); if (card->ops->write_binary == NULL) LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); if (count > max_lc) { int bytes_written = 0; const u8 *p = buf; r = sc_lock(card); LOG_TEST_RET(card->ctx, r, "sc_lock() failed"); while (count > 0) { size_t n = count > max_lc? max_lc : count; r = sc_write_binary(card, idx, p, n, flags); if (r < 0) { sc_unlock(card); LOG_TEST_RET(card->ctx, r, "sc_write_binary() failed"); } p += r; idx += r; bytes_written += r; count -= r; if (r == 0) { sc_unlock(card); LOG_FUNC_RETURN(card->ctx, bytes_written); } } sc_unlock(card); LOG_FUNC_RETURN(card->ctx, bytes_written); } r = card->ops->write_binary(card, idx, buf, count, flags); LOG_FUNC_RETURN(card->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) 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) 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); }