int sc_pkcs15_bind_synthetic(sc_pkcs15_card_t *p15card) { sc_context_t *ctx = p15card->card->ctx; scconf_block *conf_block, **blocks, *blk; sc_pkcs15emu_opt_t opts; int i, r = SC_ERROR_WRONG_CARD; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); memset(&opts, 0, sizeof(opts)); conf_block = NULL; conf_block = sc_get_conf_block(ctx, "framework", "pkcs15", 1); if (!conf_block) { /* no conf file found => try bultin drivers */ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "no conf file (or section), trying all builtin emulators\n"); for (i = 0; builtin_emulators[i].name; i++) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "trying %s\n", builtin_emulators[i].name); r = builtin_emulators[i].handler(p15card, &opts); if (r == SC_SUCCESS) /* we got a hit */ goto out; } } else { /* we have a conf file => let's use it */ int builtin_enabled; const scconf_list *list, *item; builtin_enabled = scconf_get_bool(conf_block, "enable_builtin_emulation", 1); list = scconf_find_list(conf_block, "builtin_emulators"); /* FIXME: rename to enabled_emulators */ if (builtin_enabled && list) { /* get the list of enabled emulation drivers */ for (item = list; item; item = item->next) { /* go through the list of builtin drivers */ const char *name = item->data; sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "trying %s\n", name); for (i = 0; builtin_emulators[i].name; i++) if (!strcmp(builtin_emulators[i].name, name)) { r = builtin_emulators[i].handler(p15card, &opts); if (r == SC_SUCCESS) /* we got a hit */ goto out; } } } else if (builtin_enabled) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "no emulator list in config file, trying all builtin emulators\n"); for (i = 0; builtin_emulators[i].name; i++) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "trying %s\n", builtin_emulators[i].name); r = builtin_emulators[i].handler(p15card, &opts); if (r == SC_SUCCESS) /* we got a hit */ goto out; } } /* search for 'emulate foo { ... }' entries in the conf file */ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "searching for 'emulate foo { ... }' blocks\n"); blocks = scconf_find_blocks(ctx->conf, conf_block, "emulate", NULL); for (i = 0; blocks && (blk = blocks[i]) != NULL; i++) { const char *name = blk->name->data; sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "trying %s\n", name); r = parse_emu_block(p15card, blk); if (r == SC_SUCCESS) { free(blocks); goto out; } } if (blocks) free(blocks); } /* Total failure */ return SC_ERROR_WRONG_CARD; out: if (r == SC_SUCCESS) { p15card->magic = SC_PKCS15_CARD_MAGIC; p15card->flags |= SC_PKCS15_CARD_FLAG_EMULATED; } else if (r != SC_ERROR_WRONG_CARD) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Failed to load card emulator: %s\n", sc_strerror(r)); } return r; }
static int ctapi_load_module(sc_context_t *ctx, struct ctapi_global_private_data *gpriv, scconf_block *conf) { const char *val; struct ctapi_functions funcs; struct ctapi_module *mod; const scconf_list *list; scconf_block *conf_block = NULL; void *dlh; int r, i, NumUnits; u8 cmd[5], rbuf[256], sad, dad; unsigned short lr; list = scconf_find_list(conf, "ports"); if (list == NULL) { sc_log(ctx, "No ports configured."); return -1; } val = conf->name->data; dlh = sc_dlopen(val); if (!dlh) { sc_log(ctx, "Unable to open shared library '%s': %s", val, sc_dlerror()); return -1; } funcs.CT_init = (CT_INIT_TYPE *) sc_dlsym(dlh, "CT_init"); if (!funcs.CT_init) goto symerr; funcs.CT_close = (CT_CLOSE_TYPE *) sc_dlsym(dlh, "CT_close"); if (!funcs.CT_close) goto symerr; funcs.CT_data = (CT_DATA_TYPE *) sc_dlsym(dlh, "CT_data"); if (!funcs.CT_data) goto symerr; mod = add_module(gpriv, val, dlh); if (!mod) goto symerr; for (; list != NULL; list = list->next) { int port; char namebuf[128]; char rv; sc_reader_t *reader; struct ctapi_private_data *priv; if (sscanf(list->data, "%d", &port) != 1) { sc_log(ctx, "Port '%s' is not a number.", list->data); continue; } rv = funcs.CT_init((unsigned short)mod->ctn_count, (unsigned short)port); if (rv) { sc_log(ctx, "CT_init() failed with %d", rv); continue; } reader = calloc(1, sizeof(sc_reader_t)); priv = calloc(1, sizeof(struct ctapi_private_data)); if (!priv || !reader) { free(reader); free(priv); return SC_ERROR_OUT_OF_MEMORY; } reader->drv_data = priv; reader->ops = &ctapi_ops; reader->driver = &ctapi_drv; snprintf(namebuf, sizeof(namebuf), "CT-API %s, port %d", mod->name, port); reader->name = strdup(namebuf); priv->funcs = funcs; priv->ctn = mod->ctn_count; reader->max_send_size = SC_READER_SHORT_APDU_MAX_SEND_SIZE; reader->max_recv_size = SC_READER_SHORT_APDU_MAX_RECV_SIZE; conf_block = sc_get_conf_block(ctx, "reader_driver", "ctapi", 1); if (conf_block) { reader->max_send_size = scconf_get_int(conf_block, "max_send_size", reader->max_send_size); reader->max_recv_size = scconf_get_int(conf_block, "max_recv_size", reader->max_recv_size); if (scconf_get_bool(conf_block, "enable_escape", 0)) reader->flags |= SC_READER_ENABLE_ESCAPE; } r = _sc_add_reader(ctx, reader); if (r) { funcs.CT_close((unsigned short)mod->ctn_count); free(priv); free(reader->name); free(reader); break; } /* Detect functional units of the reader according to CT-BCS spec version 1.0 (14.04.2004, http://www.teletrust.de/down/mct1-0_t4.zip) */ cmd[0] = CTBCS_CLA; cmd[1] = CTBCS_INS_STATUS; cmd[2] = CTBCS_P1_CT_KERNEL; cmd[3] = CTBCS_P2_STATUS_TFU; cmd[4] = 0x00; dad = 1; sad = 2; lr = 256; rv = priv->funcs.CT_data(priv->ctn, &dad, &sad, 5, cmd, &lr, rbuf); if (rv || (lr < 4) || (rbuf[lr-2] != 0x90)) { sc_log(reader->ctx, "Error getting status of terminal: %d, using defaults", rv); } if (rbuf[0] != CTBCS_P2_STATUS_TFU) { /* Number of slots might also detected by using CTBCS_P2_STATUS_ICC. If you think that's important please do it... ;) */ sc_log(reader->ctx, "Invalid data object returned on CTBCS_P2_STATUS_TFU: 0x%x", rbuf[0]); } NumUnits = rbuf[1]; if (NumUnits + 4 > lr) { sc_log(reader->ctx, "Invalid data returned: %d functional units, size %d", NumUnits, rv); } priv->ctapi_functional_units = 0; for(i = 0; i < NumUnits; i++) { switch(rbuf[i+2]) { case CTBCS_P1_INTERFACE1: case CTBCS_P1_INTERFACE2: case CTBCS_P1_INTERFACE3: case CTBCS_P1_INTERFACE4: case CTBCS_P1_INTERFACE5: case CTBCS_P1_INTERFACE6: case CTBCS_P1_INTERFACE7: case CTBCS_P1_INTERFACE8: case CTBCS_P1_INTERFACE9: case CTBCS_P1_INTERFACE10: case CTBCS_P1_INTERFACE11: case CTBCS_P1_INTERFACE12: case CTBCS_P1_INTERFACE13: case CTBCS_P1_INTERFACE14: /* Maybe a weak point here if multiple interfaces are present and not returned in the "canonical" order. This is not forbidden by the specs, but why should anyone want to do that? */ sc_log(reader->ctx, "Found slot id 0x%x", rbuf[i+2]); break; case CTBCS_P1_DISPLAY: priv->ctapi_functional_units |= CTAPI_FU_DISPLAY; sc_log(reader->ctx, "Display detected"); break; case CTBCS_P1_KEYPAD: priv->ctapi_functional_units |= CTAPI_FU_KEYBOARD; sc_log(reader->ctx, "Keypad detected"); break; case CTBCS_P1_PRINTER: priv->ctapi_functional_units |= CTAPI_FU_PRINTER; sc_log(reader->ctx, "Printer detected"); break; case CTBCS_P1_FINGERPRINT: case CTBCS_P1_VOICEPRINT: case CTBCS_P1_DSV: case CTBCS_P1_FACE_RECOGNITION: case CTBCS_P1_IRISSCAN: priv->ctapi_functional_units |= CTAPI_FU_BIOMETRIC; sc_log(reader->ctx, "Biometric sensor detected"); break; default: sc_log(reader->ctx, "Unknown functional unit 0x%x", rbuf[i+2]); } } /* CT-BCS does not define Keyboard/Display for each slot, so I assume those additional units can be used for each slot */ if (priv->ctapi_functional_units) { if (priv->ctapi_functional_units & CTAPI_FU_KEYBOARD) reader->capabilities |= SC_READER_CAP_PIN_PAD; if (priv->ctapi_functional_units & CTAPI_FU_DISPLAY) reader->capabilities |= SC_READER_CAP_DISPLAY; } ctapi_reset(reader); refresh_attributes(reader); mod->ctn_count++; } return 0; symerr: sc_log(ctx, "Unable to resolve CT-API symbols."); sc_dlclose(dlh); return -1; }
void load_pkcs11_parameters(struct sc_pkcs11_config *conf, sc_context_t * ctx) { scconf_block *conf_block = NULL; char *unblock_style = NULL; char *create_slots_for_pins = NULL, *op, *tmp; /* Set defaults */ conf->plug_and_play = 1; conf->max_virtual_slots = 16; if (strcmp(ctx->app_name, "onepin-opensc-pkcs11") == 0) { conf->slots_per_card = 1; } else { conf->slots_per_card = 4; } conf->hide_empty_tokens = 1; conf->lock_login = 0; conf->pin_unblock_style = SC_PKCS11_PIN_UNBLOCK_NOT_ALLOWED; conf->create_puk_slot = 0; conf->zero_ckaid_for_ca_certs = 0; conf->create_slots_flags = SC_PKCS11_SLOT_CREATE_ALL; conf_block = sc_get_conf_block(ctx, "pkcs11", NULL, 1); if (!conf_block) return; /* contains the defaults, if there is a "pkcs11" config block */ conf->plug_and_play = scconf_get_bool(conf_block, "plug_and_play", conf->plug_and_play); conf->max_virtual_slots = scconf_get_int(conf_block, "max_virtual_slots", conf->max_virtual_slots); conf->slots_per_card = scconf_get_int(conf_block, "slots_per_card", conf->slots_per_card); conf->hide_empty_tokens = scconf_get_bool(conf_block, "hide_empty_tokens", conf->hide_empty_tokens); conf->lock_login = scconf_get_bool(conf_block, "lock_login", conf->lock_login); unblock_style = (char *)scconf_get_str(conf_block, "user_pin_unblock_style", NULL); if (unblock_style && !strcmp(unblock_style, "set_pin_in_unlogged_session")) conf->pin_unblock_style = SC_PKCS11_PIN_UNBLOCK_UNLOGGED_SETPIN; else if (unblock_style && !strcmp(unblock_style, "set_pin_in_specific_context")) conf->pin_unblock_style = SC_PKCS11_PIN_UNBLOCK_SCONTEXT_SETPIN; else if (unblock_style && !strcmp(unblock_style, "init_pin_in_so_session")) conf->pin_unblock_style = SC_PKCS11_PIN_UNBLOCK_SO_LOGGED_INITPIN; conf->create_puk_slot = scconf_get_bool(conf_block, "create_puk_slot", conf->create_puk_slot); conf->zero_ckaid_for_ca_certs = scconf_get_bool(conf_block, "zero_ckaid_for_ca_certs", conf->zero_ckaid_for_ca_certs); create_slots_for_pins = (char *)scconf_get_str(conf_block, "create_slots_for_pins", "all"); conf->create_slots_flags = 0; tmp = strdup(create_slots_for_pins); op = strtok(tmp, " ,"); while (op) { if (!strcmp(op, "user")) conf->create_slots_flags |= SC_PKCS11_SLOT_FOR_PIN_USER; else if (!strcmp(op, "sign")) conf->create_slots_flags |= SC_PKCS11_SLOT_FOR_PIN_SIGN; else if (!strcmp(op, "application")) conf->create_slots_flags |= SC_PKCS11_SLOT_FOR_APPLICATION; else if (!strcmp(op, "all")) conf->create_slots_flags |= SC_PKCS11_SLOT_CREATE_ALL; op = strtok(NULL, " ,"); } free(tmp); sc_log(ctx, "PKCS#11 options: plug_and_play=%d max_virtual_slots=%d slots_per_card=%d " "hide_empty_tokens=%d lock_login=%d pin_unblock_style=%d " "zero_ckaid_for_ca_certs=%d create_slots_flags=0x%X", conf->plug_and_play, conf->max_virtual_slots, conf->slots_per_card, conf->hide_empty_tokens, conf->lock_login, conf->pin_unblock_style, conf->zero_ckaid_for_ca_certs, conf->create_slots_flags); }