/* * Initialize profile */ struct sc_profile * sc_profile_new(void) { struct sc_pkcs15_card *p15card; struct sc_profile *pro; pro = (struct sc_profile *) calloc(1, sizeof(*pro)); if (pro == NULL) return NULL; pro->p15_spec = p15card = sc_pkcs15_card_new(); pro->protect_certificates = 1; pro->pkcs15.do_last_update = 1; if (p15card) { p15card->label = strdup("OpenSC Card"); p15card->manufacturer_id = strdup("OpenSC Project"); p15card->serial_number = strdup("0000"); p15card->flags = SC_PKCS15_CARD_FLAG_EID_COMPLIANT; p15card->version = 1; /* Set up EF(TokenInfo) and EF(ODF) */ p15card->file_tokeninfo = init_file(SC_FILE_TYPE_WORKING_EF); p15card->file_odf = init_file(SC_FILE_TYPE_WORKING_EF); p15card->file_unusedspace = init_file(SC_FILE_TYPE_WORKING_EF); } /* Assume card does RSA natively, but no DSA */ pro->rsa_access_flags = DEF_PRKEY_RSA_ACCESS; pro->dsa_access_flags = DEF_PRKEY_DSA_ACCESS; pro->pin_encoding = 0x01; pro->pin_minlen = 4; pro->pin_maxlen = 8; pro->keep_public_key = 1; return pro; }
int card_sync_card_to_virtual_fs_any_df( sc_card_t *card, struct _virtual_file_t *virtual_file, virtual_fs_t *virtual_fs, int type ) { int r = SC_SUCCESS; unsigned char *encoded_pkcs15 = NULL; size_t encoded_pkcs15_size = 0; sc_pkcs15_card_t *temp_pkcs15_card = NULL; sc_pkcs15_object_t *obj = NULL; unsigned char *card_data = NULL; size_t card_data_length = 0; SC_FUNC_CALLED(card->ctx, 1); if(!card || !virtual_file) return SC_ERROR_INVALID_ARGUMENTS; /* get file */ r = card_helper_read_file(card, &virtual_file->path, &card_data, &card_data_length); if(r < 0) goto end; /* create a new pkcs15_card structure */ temp_pkcs15_card = sc_pkcs15_card_new(); if(!temp_pkcs15_card) { r = SC_ERROR_OUT_OF_MEMORY; goto end; } /* we set some important fields */ temp_pkcs15_card->card = card; temp_pkcs15_card->file_app = sc_file_new(); if (!temp_pkcs15_card->file_app) { r = SC_ERROR_OUT_OF_MEMORY; goto end; } sc_format_path("3F00", &temp_pkcs15_card->file_app->path); temp_pkcs15_card->tokeninfo->flags=SC_PKCS15_TOKEN_PRN_GENERATION | SC_PKCS15_TOKEN_EID_COMPLIANT; /* Convert card df read to a list of same type of pkcs15 objects. This function uses our internal card decoding parser. */ r = sc_pkcs15_parse_card_df( temp_pkcs15_card, type, card_data, card_data_length ); if(r != SC_SUCCESS) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Card parsing failed\n"); goto end; } /* we need to correct some PKCS#15 data */ for(obj = temp_pkcs15_card->obj_list; obj != NULL; obj = obj->next) { switch(obj->type & SC_PKCS15_TYPE_CLASS_MASK) { case SC_PKCS15_TYPE_CERT: r = card_sync_card_to_virtual_fs_filter_cert(card, virtual_file, virtual_fs, obj); break; case SC_PKCS15_TYPE_PRKEY: r = card_sync_card_to_virtual_fs_filter_prkey(card, virtual_file, virtual_fs, obj); break; case SC_PKCS15_TYPE_PUBKEY: r = card_sync_card_to_virtual_fs_filter_pukey(card, virtual_file, virtual_fs, obj); break; case SC_PKCS15_TYPE_AUTH: if(obj->data) { sc_pkcs15_pin_info_t * pin=obj->data; /* remove security officer pin */ pin->flags &= (~SC_PKCS15_PIN_FLAG_SO_PIN); sc_format_path("3F00", &pin->path); pin->stored_length= (pin->max_length>pin->stored_length) ? pin->max_length : pin->stored_length; } break; case SC_PKCS15_TYPE_DATA_OBJECT: r = card_sync_card_to_virtual_fs_filter_data_object(card, virtual_file, virtual_fs, obj); break; default: /* ignore this object */ break; } } if(r != SC_SUCCESS) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Object filtering failed\n"); goto end; } /* generate pkcs#15 stream for the appropiate object type */ r = sc_standard_pkcs15_encode_any_df( card->ctx, temp_pkcs15_card, type, /* encode only specific objects type */ &encoded_pkcs15, &encoded_pkcs15_size ); if(r != SC_SUCCESS) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Standard PKCS#15 encoding failed\n"); goto end; } r = virtual_file_data_update(virtual_file, 0, encoded_pkcs15, encoded_pkcs15_size); if(r == SC_SUCCESS) { /* add a trailing 0 */ r = virtual_file_data_update(virtual_file, encoded_pkcs15_size, (const unsigned char *)"\0", 1); } end: if(card_data) { free(card_data); card_data = NULL; } if(temp_pkcs15_card) { /* set to NULL without freeing because we reused structure */ temp_pkcs15_card->card = NULL; /* now free temp structure */ sc_pkcs15_card_free(temp_pkcs15_card); temp_pkcs15_card = NULL; } if(encoded_pkcs15) { free(encoded_pkcs15); encoded_pkcs15 = NULL; } SC_FUNC_RETURN(card->ctx, 1, r); }
int sc_pkcs15_bind(sc_card_t *card, struct sc_pkcs15_card **p15card_out) { struct sc_pkcs15_card *p15card = NULL; sc_context_t *ctx; scconf_block *conf_block = NULL, **blocks; int i, r, emu_first, enable_emu; assert(sc_card_valid(card) && p15card_out != NULL); ctx = card->ctx; SC_FUNC_CALLED(ctx, 1); p15card = sc_pkcs15_card_new(); if (p15card == NULL) return SC_ERROR_OUT_OF_MEMORY; p15card->card = card; for (i = 0; ctx->conf_blocks[i] != NULL; i++) { blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[i], "framework", "pkcs15"); if (blocks && blocks[0] != NULL) conf_block = blocks[0]; free(blocks); } if (conf_block) { p15card->opts.use_cache = scconf_get_bool(conf_block, "use_caching", 0); } r = sc_lock(card); if (r) { sc_error(ctx, "sc_lock() failed: %s\n", sc_strerror(r)); sc_pkcs15_card_free(p15card); SC_FUNC_RETURN(ctx, 1, r); } enable_emu = scconf_get_bool(conf_block, "enable_pkcs15_emulation", 1); if (enable_emu) { emu_first = scconf_get_bool(conf_block, "try_emulation_first", 0); if (emu_first || sc_pkcs15_is_emulation_only(card)) { r = sc_pkcs15_bind_synthetic(p15card); if (r == SC_SUCCESS) goto done; r = sc_pkcs15_bind_internal(p15card); if (r < 0) goto error; } else { r = sc_pkcs15_bind_internal(p15card); if (r == SC_SUCCESS) goto done; r = sc_pkcs15_bind_synthetic(p15card); if (r < 0) goto error; } } else { r = sc_pkcs15_bind_internal(p15card); if (r < 0) goto error; } done: *p15card_out = p15card; sc_unlock(card); return 0; error: sc_unlock(card); sc_pkcs15_card_free(p15card); SC_FUNC_RETURN(ctx, 1, r); }
int card_helper_create_cert_file(sc_card_t *card, struct _virtual_file_t *virtual_file, size_t fcert_len, struct _virtual_file_t **certificate_virtual_file) { int r = SC_SUCCESS; sc_path_t fcert_path; sc_pkcs15_unusedspace_t *unused_space=NULL; sc_pkcs15_card_t *temp_p15card = NULL; int old_use_virtual_fs; /*!< backup of use_virtual_fs */ assert(card!=NULL && virtual_file!=NULL && certificate_virtual_file!=NULL); SC_FUNC_CALLED(card->ctx, 1); /* we backup use_virtual_fs */ old_use_virtual_fs = card_is_virtual_fs_active(card); /* we want to use card without virtual fs */ card_set_virtual_fs_state(card, 0); if(*certificate_virtual_file) { virtual_file_free(*certificate_virtual_file); *certificate_virtual_file = NULL; } memset(&fcert_path, 0, sizeof(struct sc_path)); /* 2. Look for a suitable file on UnusedSpace struct which fits the final certificate file size. 2.1 If found, take file's path to reuse it. 2.2 If not, create a file on Certificate Directory with final certificate len as its size */ /* we create a fake p15card structure */ temp_p15card = sc_pkcs15_card_new(); temp_p15card->card = card; r = sc_find_free_unusedspace( temp_p15card, fcert_len, &unused_space ); if (r!=SC_SUCCESS) goto chccf_end; if(unused_space) { /* we got a path */ r = sc_path_set_dnie ( &fcert_path, unused_space->path.type, unused_space->path.value, unused_space->path.len, unused_space->path.index, unused_space->path.count ); if (r!=SC_SUCCESS) goto chccf_end; } else { sc_path_t temp_path; /* move to certificate DF */ sc_format_path("3F006061", &temp_path); r = card_select_file(card, &temp_path, NULL); if(r != SC_SUCCESS) goto chccf_end; /* we start at 0x7001 file ID */ sc_format_path("7001", &fcert_path); do { r = card_create_cert_file( card, &fcert_path, fcert_len ); if (r == SC_ERROR_OBJECT_ALREADY_EXISTS) { fcert_path.value[1]++; } if(r!=SC_SUCCESS && r!=SC_ERROR_OBJECT_ALREADY_EXISTS) goto chccf_end; } while (r!=SC_SUCCESS); r = SC_SUCCESS; } /* create certificate file into vfs */ r = virtual_fs_append_new_virtual_file( DRVDATA(card)->virtual_fs, &fcert_path, virtual_file->data, virtual_file->data_size, virtual_file->data_size, 1, virtual_file_sync_state_synced, card_sync_card_to_virtual_fs_certificate_file_callback, virtual_file_sync_state_sync_pending, card_sync_virtual_fs_to_card_certificate_file_callback ); if(r != SC_SUCCESS) goto chccf_end; /* retrieve just created virtual file */ *certificate_virtual_file = virtual_fs_find_by_path( DRVDATA(card)->virtual_fs, &fcert_path ); chccf_end: /* we restore use_virtual_fs */ card_set_virtual_fs_state(card, old_use_virtual_fs); if (unused_space) { /* Delete UnusedSpace object if reused and also frees reserved memory */ sc_pkcs15_remove_unusedspace(temp_p15card, unused_space); } if (temp_p15card) { /* set to NULL without freeing because we reused structure */ temp_p15card->card = NULL; /* now free temp structure */ sc_pkcs15_card_free(temp_p15card); temp_p15card = NULL; } SC_FUNC_RETURN(card->ctx, 1, r); }